Merge branch 'features/webhooks' into dev
This commit is contained in:
		
						commit
						0eae3c3ea3
					
				@ -14,7 +14,7 @@ services:
 | 
				
			|||||||
    image: mongo
 | 
					    image: mongo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  identity-api-test:
 | 
					  identity-api-test:
 | 
				
			||||||
    image: eshop/identity-api-test:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/identity-api-test:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Identity/Identity.API/Dockerfile
 | 
					      dockerfile: src/Services/Identity/Identity.API/Dockerfile
 | 
				
			||||||
@ -22,7 +22,7 @@ services:
 | 
				
			|||||||
      - sql-data-test
 | 
					      - sql-data-test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  basket-api-test:
 | 
					  basket-api-test:
 | 
				
			||||||
    image: eshop/basket-api-test:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/basket-api-test:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Basket/Basket.API/Dockerfile
 | 
					      dockerfile: src/Services/Basket/Basket.API/Dockerfile
 | 
				
			||||||
@ -35,7 +35,7 @@ services:
 | 
				
			|||||||
      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
					      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  basket-api-unit-test:
 | 
					  basket-api-unit-test:
 | 
				
			||||||
    image: eshop/basket-api-test:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/basket-api-test:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Basket/Basket.API/Dockerfile
 | 
					      dockerfile: src/Services/Basket/Basket.API/Dockerfile
 | 
				
			||||||
@ -48,7 +48,7 @@ services:
 | 
				
			|||||||
      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
					      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  catalog-api-test:
 | 
					  catalog-api-test:
 | 
				
			||||||
    image: eshop/catalog-api-test:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/catalog-api-test:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Catalog/Catalog.API/Dockerfile
 | 
					      dockerfile: src/Services/Catalog/Catalog.API/Dockerfile
 | 
				
			||||||
@ -60,7 +60,7 @@ services:
 | 
				
			|||||||
      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
					      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  catalog-api-unit-test:
 | 
					  catalog-api-unit-test:
 | 
				
			||||||
    image: eshop/catalog-api-test:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/catalog-api-test:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Catalog/Catalog.API/Dockerfile
 | 
					      dockerfile: src/Services/Catalog/Catalog.API/Dockerfile
 | 
				
			||||||
@ -72,7 +72,7 @@ services:
 | 
				
			|||||||
      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
					      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ordering-api-test:
 | 
					  ordering-api-test:
 | 
				
			||||||
    image: eshop/ordering-api-test:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/ordering-api-test:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Ordering/Ordering.API/Dockerfile
 | 
					      dockerfile: src/Services/Ordering/Ordering.API/Dockerfile
 | 
				
			||||||
@ -84,7 +84,7 @@ services:
 | 
				
			|||||||
      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
					      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ordering-api-unit-test:
 | 
					  ordering-api-unit-test:
 | 
				
			||||||
    image: eshop/ordering-api-test:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/ordering-api-test:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Ordering/Ordering.API/Dockerfile
 | 
					      dockerfile: src/Services/Ordering/Ordering.API/Dockerfile
 | 
				
			||||||
@ -96,7 +96,7 @@ services:
 | 
				
			|||||||
      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests  
 | 
					      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  marketing-api-test:
 | 
					  marketing-api-test:
 | 
				
			||||||
    image: eshop/marketing-api-test:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/marketing-api-test:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Marketing/Marketing.API/Dockerfile
 | 
					      dockerfile: src/Services/Marketing/Marketing.API/Dockerfile
 | 
				
			||||||
@ -110,7 +110,7 @@ services:
 | 
				
			|||||||
      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
					      - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests-results/}:/tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  payment-api-test:
 | 
					  payment-api-test:
 | 
				
			||||||
    image: eshop/payment-api-test:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/payment-api-test:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Payment/Payment.API/Dockerfile
 | 
					      dockerfile: src/Services/Payment/Payment.API/Dockerfile
 | 
				
			||||||
@ -118,7 +118,7 @@ services:
 | 
				
			|||||||
      - rabbitmq-test
 | 
					      - rabbitmq-test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  locations-api-test:
 | 
					  locations-api-test:
 | 
				
			||||||
    image: eshop/locations-api-test:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/locations-api-test:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Location/Locations.API/Dockerfile
 | 
					      dockerfile: src/Services/Location/Locations.API/Dockerfile
 | 
				
			||||||
 | 
				
			|||||||
@ -41,6 +41,8 @@ services:
 | 
				
			|||||||
      - OrderingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102
 | 
					      - OrderingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102
 | 
				
			||||||
      - MobileShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5120
 | 
					      - MobileShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5120
 | 
				
			||||||
      - WebShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5121
 | 
					      - WebShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5121
 | 
				
			||||||
 | 
					      - WebhooksApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5113
 | 
				
			||||||
 | 
					      - WebhooksWebClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5114
 | 
				
			||||||
      - UseCustomizationData=True  
 | 
					      - UseCustomizationData=True  
 | 
				
			||||||
      - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
 | 
					      - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
 | 
				
			||||||
      - OrchestratorType=${ORCHESTRATOR_TYPE}
 | 
					      - OrchestratorType=${ORCHESTRATOR_TYPE}
 | 
				
			||||||
@ -182,6 +184,19 @@ services:
 | 
				
			|||||||
    ports:
 | 
					    ports:
 | 
				
			||||||
      - "5109:80"   # Important: In a production environment your should remove the external port (5109) kept here for microservice debugging purposes. 
 | 
					      - "5109:80"   # Important: In a production environment your should remove the external port (5109) kept here for microservice debugging purposes. 
 | 
				
			||||||
                    # The API Gateway redirects and access through the internal port (80).
 | 
					                    # The API Gateway redirects and access through the internal port (80).
 | 
				
			||||||
 | 
					  webhooks.api:
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      - ASPNETCORE_ENVIRONMENT=Development
 | 
				
			||||||
 | 
					      - ASPNETCORE_URLS=http://0.0.0.0:80
 | 
				
			||||||
 | 
					      - ConnectionString=${ESHOP_AZURE_WEBHOOKS_DB:-Server=sql.data;Database=Microsoft.eShopOnContainers.Services.WebhooksDb;User Id=sa;Password=Pass@word}
 | 
				
			||||||
 | 
					      - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq}
 | 
				
			||||||
 | 
					      - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME}
 | 
				
			||||||
 | 
					      - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD}    
 | 
				
			||||||
 | 
					      - IdentityUrl=http://identity.api  
 | 
				
			||||||
 | 
					      - IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
 | 
				
			||||||
 | 
					    ports:
 | 
				
			||||||
 | 
					      - "5113:80"   # Important: In a production environment your should remove the external port (5109) kept here for microservice debugging purposes. 
 | 
				
			||||||
 | 
					                    # The API Gateway redirects and access through the internal port (80).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mobileshoppingapigw:
 | 
					  mobileshoppingapigw:
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
@ -380,3 +395,13 @@ services:
 | 
				
			|||||||
    ports:
 | 
					    ports:
 | 
				
			||||||
      - "5100:80"
 | 
					      - "5100:80"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  webhooks.client:
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      - ASPNETCORE_URLS=http://0.0.0.0:80
 | 
				
			||||||
 | 
					      - Token=6168DB8D-DC58-4094-AF24-483278923590      # Webhooks are registered with this token (any value is valid) but the client won't check it
 | 
				
			||||||
 | 
					      - IdentityUrl=http://10.0.75.1:5105
 | 
				
			||||||
 | 
					      - CallBackUrl=http://localhost:5114
 | 
				
			||||||
 | 
					      - WebhooksUrl=http://webhooks.api
 | 
				
			||||||
 | 
					      - SelfUrl=http://webhooks.client/
 | 
				
			||||||
 | 
					    ports:
 | 
				
			||||||
 | 
					      - "5114:80"
 | 
				
			||||||
@ -14,7 +14,7 @@ services:
 | 
				
			|||||||
    image: rabbitmq:3-management-alpine
 | 
					    image: rabbitmq:3-management-alpine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  identity.api:
 | 
					  identity.api:
 | 
				
			||||||
    image: eshop/identity.api:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/identity.api:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Identity/Identity.API/Dockerfile    
 | 
					      dockerfile: src/Services/Identity/Identity.API/Dockerfile    
 | 
				
			||||||
@ -22,7 +22,7 @@ services:
 | 
				
			|||||||
      - sql.data
 | 
					      - sql.data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  basket.api:
 | 
					  basket.api:
 | 
				
			||||||
    image: eshop/basket.api:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/basket.api:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Basket/Basket.API/Dockerfile    
 | 
					      dockerfile: src/Services/Basket/Basket.API/Dockerfile    
 | 
				
			||||||
@ -32,7 +32,7 @@ services:
 | 
				
			|||||||
      - rabbitmq
 | 
					      - rabbitmq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  catalog.api:
 | 
					  catalog.api:
 | 
				
			||||||
    image: eshop/catalog.api:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/catalog.api:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Catalog/Catalog.API/Dockerfile
 | 
					      dockerfile: src/Services/Catalog/Catalog.API/Dockerfile
 | 
				
			||||||
@ -41,7 +41,7 @@ services:
 | 
				
			|||||||
      - rabbitmq
 | 
					      - rabbitmq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ordering.api:
 | 
					  ordering.api:
 | 
				
			||||||
    image: eshop/ordering.api:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/ordering.api:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Ordering/Ordering.API/Dockerfile    
 | 
					      dockerfile: src/Services/Ordering/Ordering.API/Dockerfile    
 | 
				
			||||||
@ -50,7 +50,7 @@ services:
 | 
				
			|||||||
      - rabbitmq
 | 
					      - rabbitmq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ordering.backgroundtasks:
 | 
					  ordering.backgroundtasks:
 | 
				
			||||||
    image: eshop/ordering.backgroundtasks:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/ordering.backgroundtasks:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile    
 | 
					      dockerfile: src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile    
 | 
				
			||||||
@ -59,7 +59,7 @@ services:
 | 
				
			|||||||
      - rabbitmq
 | 
					      - rabbitmq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  marketing.api:
 | 
					  marketing.api:
 | 
				
			||||||
    image: eshop/marketing.api:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/marketing.api:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Marketing/Marketing.API/Dockerfile    
 | 
					      dockerfile: src/Services/Marketing/Marketing.API/Dockerfile    
 | 
				
			||||||
@ -70,7 +70,7 @@ services:
 | 
				
			|||||||
      - rabbitmq
 | 
					      - rabbitmq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  payment.api:
 | 
					  payment.api:
 | 
				
			||||||
    image: eshop/payment.api:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/payment.api:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Payment/Payment.API/Dockerfile
 | 
					      dockerfile: src/Services/Payment/Payment.API/Dockerfile
 | 
				
			||||||
@ -78,7 +78,7 @@ services:
 | 
				
			|||||||
      - rabbitmq    
 | 
					      - rabbitmq    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  locations.api:
 | 
					  locations.api:
 | 
				
			||||||
    image: eshop/locations.api:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/locations.api:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Location/Locations.API/Dockerfile
 | 
					      dockerfile: src/Services/Location/Locations.API/Dockerfile
 | 
				
			||||||
@ -86,8 +86,16 @@ services:
 | 
				
			|||||||
      - nosql.data
 | 
					      - nosql.data
 | 
				
			||||||
      - rabbitmq
 | 
					      - rabbitmq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  webhooks.api:
 | 
				
			||||||
 | 
					    image: ${REGISTRY:-eshop}/webhooks.api:${TAG:-latest}
 | 
				
			||||||
 | 
					    build:
 | 
				
			||||||
 | 
					      context: .
 | 
				
			||||||
 | 
					      dockerfile: src/Services/Webhooks/Webhooks.API/Dockerfile
 | 
				
			||||||
 | 
					    depends_on:
 | 
				
			||||||
 | 
					      - sql.data    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mobileshoppingapigw:
 | 
					  mobileshoppingapigw:
 | 
				
			||||||
    image: eshop/ocelotapigw:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/ocelotapigw:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
 | 
					      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
 | 
				
			||||||
@ -102,7 +110,7 @@ services:
 | 
				
			|||||||
      - basket.api
 | 
					      - basket.api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mobilemarketingapigw:
 | 
					  mobilemarketingapigw:
 | 
				
			||||||
    image: eshop/ocelotapigw:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/ocelotapigw:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
 | 
					      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
 | 
				
			||||||
@ -117,7 +125,7 @@ services:
 | 
				
			|||||||
      - basket.api
 | 
					      - basket.api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  webshoppingapigw:
 | 
					  webshoppingapigw:
 | 
				
			||||||
    image: eshop/ocelotapigw:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/ocelotapigw:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
 | 
					      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
 | 
				
			||||||
@ -132,7 +140,7 @@ services:
 | 
				
			|||||||
      - basket.api
 | 
					      - basket.api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  webmarketingapigw:
 | 
					  webmarketingapigw:
 | 
				
			||||||
    image: eshop/ocelotapigw:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/ocelotapigw:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
 | 
					      dockerfile: src/ApiGateways/ApiGw-Base/Dockerfile
 | 
				
			||||||
@ -147,7 +155,7 @@ services:
 | 
				
			|||||||
      - basket.api
 | 
					      - basket.api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mobileshoppingagg:
 | 
					  mobileshoppingagg:
 | 
				
			||||||
    image: eshop/mobileshoppingagg:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/mobileshoppingagg:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile
 | 
					      dockerfile: src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile
 | 
				
			||||||
@ -162,7 +170,7 @@ services:
 | 
				
			|||||||
      - basket.api
 | 
					      - basket.api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  webshoppingagg:
 | 
					  webshoppingagg:
 | 
				
			||||||
    image: eshop/webshoppingagg:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/webshoppingagg:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile
 | 
					      dockerfile: src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile
 | 
				
			||||||
@ -177,7 +185,7 @@ services:
 | 
				
			|||||||
      - basket.api
 | 
					      - basket.api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ordering.signalrhub:
 | 
					  ordering.signalrhub:
 | 
				
			||||||
    image: eshop/ordering.signalrhub:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/ordering.signalrhub:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Services/Ordering/Ordering.SignalrHub/Dockerfile
 | 
					      dockerfile: src/Services/Ordering/Ordering.SignalrHub/Dockerfile
 | 
				
			||||||
@ -192,13 +200,13 @@ services:
 | 
				
			|||||||
      - basket.api
 | 
					      - basket.api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  webstatus:
 | 
					  webstatus:
 | 
				
			||||||
    image: eshop/webstatus:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/webstatus:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Web/WebStatus/Dockerfile
 | 
					      dockerfile: src/Web/WebStatus/Dockerfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  webspa:
 | 
					  webspa:
 | 
				
			||||||
    image: eshop/webspa:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/webspa:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Web/WebSPA/Dockerfile    
 | 
					      dockerfile: src/Web/WebSPA/Dockerfile    
 | 
				
			||||||
@ -208,7 +216,7 @@ services:
 | 
				
			|||||||
#      - webmarketingapigw
 | 
					#      - webmarketingapigw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  webmvc:
 | 
					  webmvc:
 | 
				
			||||||
    image: eshop/webmvc:${TAG:-latest}
 | 
					    image: ${REGISTRY:-eshop}/webmvc:${TAG:-latest}
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
      dockerfile: src/Web/WebMVC/Dockerfile    
 | 
					      dockerfile: src/Web/WebMVC/Dockerfile    
 | 
				
			||||||
@ -217,3 +225,10 @@ services:
 | 
				
			|||||||
      - webshoppingapigw
 | 
					      - webshoppingapigw
 | 
				
			||||||
      - webmarketingapigw
 | 
					      - webmarketingapigw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  webhooks.client:
 | 
				
			||||||
 | 
					    image: ${REGISTRY:-eshop}/webhooks.client:${TAG:-latest}
 | 
				
			||||||
 | 
					    build:
 | 
				
			||||||
 | 
					      context: .
 | 
				
			||||||
 | 
					      dockerfile: src/Web/WebhookClient/Dockerfile
 | 
				
			||||||
 | 
					    depends_on:
 | 
				
			||||||
 | 
					      - webhooks.api    
 | 
				
			||||||
@ -140,6 +140,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Payment", "Payment", "{C61C
 | 
				
			|||||||
EndProject
 | 
					EndProject
 | 
				
			||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Payment.API", "src\Services\Payment\Payment.API\Payment.API.csproj", "{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84}"
 | 
					Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Payment.API", "src\Services\Payment\Payment.API\Payment.API.csproj", "{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84}"
 | 
				
			||||||
EndProject
 | 
					EndProject
 | 
				
			||||||
 | 
					Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Webhooks", "Webhooks", "{E0AA11C4-2873-461D-8F82-53392530FB7A}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
 | 
					Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Webhooks.API", "src\Services\Webhooks\Webhooks.API\Webhooks.API.csproj", "{84E2016E-0435-44C6-8020-3D288AA38B2C}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
 | 
					Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebhookClient", "src\Web\WebhookClient\WebhookClient.csproj", "{766D7E92-6AF0-476C-ADD5-282BF4D8C576}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
Global
 | 
					Global
 | 
				
			||||||
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
						GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
				
			||||||
		Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
 | 
							Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
 | 
				
			||||||
@ -1642,6 +1648,102 @@ Global
 | 
				
			|||||||
		{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84}.Release|x64.Build.0 = Release|Any CPU
 | 
							{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84}.Release|x64.Build.0 = Release|Any CPU
 | 
				
			||||||
		{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84}.Release|x86.ActiveCfg = Release|Any CPU
 | 
							{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84}.Release|x86.ActiveCfg = Release|Any CPU
 | 
				
			||||||
		{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84}.Release|x86.Build.0 = Release|Any CPU
 | 
							{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84}.Release|x86.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|ARM.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|ARM.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|iPhone.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|x64.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|x64.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|x86.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.AppStore|x86.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|ARM.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|ARM.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|iPhone.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|x64.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Debug|x86.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|ARM.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|ARM.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|iPhone.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|iPhone.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|x64.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|x64.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|x86.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C}.Release|x86.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|ARM.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|ARM.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|iPhone.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|x64.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|x64.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|x86.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.AppStore|x86.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|ARM.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|ARM.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|iPhone.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|iPhone.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|x64.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|x64.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|x86.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Debug|x86.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|ARM.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|ARM.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|iPhone.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|iPhone.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|x64.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|x64.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|x86.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576}.Release|x86.Build.0 = Release|Any CPU
 | 
				
			||||||
	EndGlobalSection
 | 
						EndGlobalSection
 | 
				
			||||||
	GlobalSection(SolutionProperties) = preSolution
 | 
						GlobalSection(SolutionProperties) = preSolution
 | 
				
			||||||
		HideSolutionNode = FALSE
 | 
							HideSolutionNode = FALSE
 | 
				
			||||||
@ -1703,6 +1805,9 @@ Global
 | 
				
			|||||||
		{120CABB3-0FEA-4B40-B4B5-2D3041798C80} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B}
 | 
							{120CABB3-0FEA-4B40-B4B5-2D3041798C80} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B}
 | 
				
			||||||
		{C61C5CFE-4876-4A46-A96E-5BBF596A984A} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
 | 
							{C61C5CFE-4876-4A46-A96E-5BBF596A984A} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
 | 
				
			||||||
		{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84} = {C61C5CFE-4876-4A46-A96E-5BBF596A984A}
 | 
							{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84} = {C61C5CFE-4876-4A46-A96E-5BBF596A984A}
 | 
				
			||||||
 | 
							{E0AA11C4-2873-461D-8F82-53392530FB7A} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
 | 
				
			||||||
 | 
							{84E2016E-0435-44C6-8020-3D288AA38B2C} = {E0AA11C4-2873-461D-8F82-53392530FB7A}
 | 
				
			||||||
 | 
							{766D7E92-6AF0-476C-ADD5-282BF4D8C576} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04}
 | 
				
			||||||
	EndGlobalSection
 | 
						EndGlobalSection
 | 
				
			||||||
	GlobalSection(ExtensibilityGlobals) = postSolution
 | 
						GlobalSection(ExtensibilityGlobals) = postSolution
 | 
				
			||||||
		SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9}
 | 
							SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9}
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,8 @@ app:                                                  # app global settings
 | 
				
			|||||||
      payment: payment-api                            # ingress entry for payment api
 | 
					      payment: payment-api                            # ingress entry for payment api
 | 
				
			||||||
      locations: locations-api                        # ingress entry for locations api
 | 
					      locations: locations-api                        # ingress entry for locations api
 | 
				
			||||||
      marketing: marketing-api                        # ingress entry for marketing api
 | 
					      marketing: marketing-api                        # ingress entry for marketing api
 | 
				
			||||||
 | 
					      webhooks: webhooks-api                          # ingress entry for webhooks api
 | 
				
			||||||
 | 
					      webhooksweb: webhooks-web                       # ingress entry for webhooks web demo client
 | 
				
			||||||
  svc:
 | 
					  svc:
 | 
				
			||||||
      basket: basket                                    # service name for basket api
 | 
					      basket: basket                                    # service name for basket api
 | 
				
			||||||
      catalog: catalog                                  # service name for catalog api
 | 
					      catalog: catalog                                  # service name for catalog api
 | 
				
			||||||
@ -41,3 +43,5 @@ app:                                                  # app global settings
 | 
				
			|||||||
      payment: payment                                  # service name for payment api
 | 
					      payment: payment                                  # service name for payment api
 | 
				
			||||||
      locations: locations                              # service name for locations api
 | 
					      locations: locations                              # service name for locations api
 | 
				
			||||||
      marketing: marketing                              # service name for marketing ap
 | 
					      marketing: marketing                              # service name for marketing ap
 | 
				
			||||||
 | 
					      webhooks: webhooks                                # service name for webhooks api
 | 
				
			||||||
 | 
					      webhooksweb: webhooksweb                          # service name for webhooks web
 | 
				
			||||||
 | 
				
			|||||||
@ -61,7 +61,7 @@ if (-not [string]::IsNullOrEmpty($registry)) {
 | 
				
			|||||||
Write-Host "Begin eShopOnContainers installation using Helm" -ForegroundColor Green
 | 
					Write-Host "Begin eShopOnContainers installation using Helm" -ForegroundColor Green
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$infras = ("sql-data", "nosql-data", "rabbitmq", "keystore-data", "basket-data")
 | 
					$infras = ("sql-data", "nosql-data", "rabbitmq", "keystore-data", "basket-data")
 | 
				
			||||||
$charts = ("eshop-common", "apigwmm", "apigwms", "apigwwm", "apigwws", "basket-api","catalog-api", "identity-api", "locations-api", "marketing-api", "mobileshoppingagg","ordering-api","ordering-backgroundtasks","ordering-signalrhub", "payment-api", "webmvc", "webshoppingagg", "webspa", "webstatus")
 | 
					$charts = ("eshop-common", "apigwmm", "apigwms", "apigwwm", "apigwws", "basket-api","catalog-api", "identity-api", "locations-api", "marketing-api", "mobileshoppingagg","ordering-api","ordering-backgroundtasks","ordering-signalrhub", "payment-api", "webmvc", "webshoppingagg", "webspa", "webstatus", "webhooks-api", "webhooks-web")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if ($deployInfrastructure) {
 | 
					if ($deployInfrastructure) {
 | 
				
			||||||
    foreach ($infra in $infras) {
 | 
					    foreach ($infra in $infras) {
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,8 @@
 | 
				
			|||||||
{{- $mobileshoppingagg := include "url-of" (list .Values.app.ingress.entries.mobileshoppingagg .) -}}
 | 
					{{- $mobileshoppingagg := include "url-of" (list .Values.app.ingress.entries.mobileshoppingagg .) -}}
 | 
				
			||||||
{{- $webhoppingagg := include "url-of" (list .Values.app.ingress.entries.webshoppingagg .) -}}
 | 
					{{- $webhoppingagg := include "url-of" (list .Values.app.ingress.entries.webshoppingagg .) -}}
 | 
				
			||||||
{{- $xamarincallback := include "url-of" (list "xamarincallback" .) -}}
 | 
					{{- $xamarincallback := include "url-of" (list "xamarincallback" .) -}}
 | 
				
			||||||
 | 
					{{- $webhooks_url := include "url-of" (list .Values.app.ingress.entries.webhooks .) -}}
 | 
				
			||||||
 | 
					{{- $webhooksweb_url := include "url-of" (list .Values.app.ingress.entries.webhooksweb .) -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
apiVersion: v1
 | 
					apiVersion: v1
 | 
				
			||||||
kind: ConfigMap
 | 
					kind: ConfigMap
 | 
				
			||||||
@ -32,4 +34,7 @@ data:
 | 
				
			|||||||
  mobileshoppingagg_e: http://{{ $mobileshoppingagg }}
 | 
					  mobileshoppingagg_e: http://{{ $mobileshoppingagg }}
 | 
				
			||||||
  webshoppingagg_e: http://{{ $webhoppingagg }}
 | 
					  webshoppingagg_e: http://{{ $webhoppingagg }}
 | 
				
			||||||
  xamarin_callback_e: http://{{ $xamarincallback }}
 | 
					  xamarin_callback_e: http://{{ $xamarincallback }}
 | 
				
			||||||
 | 
					  webhooksapi_e:  http://{{ $webhooks_url }}
 | 
				
			||||||
 | 
					  webhooksweb_e: http://{{ $webhooksweb_url }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -54,6 +54,10 @@ env:
 | 
				
			|||||||
      key: webshoppingagg_e
 | 
					      key: webshoppingagg_e
 | 
				
			||||||
    - name: XamarinCallback
 | 
					    - name: XamarinCallback
 | 
				
			||||||
      key: xamarin_callback_e
 | 
					      key: xamarin_callback_e
 | 
				
			||||||
 | 
					    - name: WebhooksApiClient
 | 
				
			||||||
 | 
					      key: webhooksapi_e
 | 
				
			||||||
 | 
					    - name: WebhooksWebClient
 | 
				
			||||||
 | 
					      key: webhooksweb_e
 | 
				
			||||||
  values:
 | 
					  values:
 | 
				
			||||||
    - name: ASPNETCORE_ENVIRONMENT
 | 
					    - name: ASPNETCORE_ENVIRONMENT
 | 
				
			||||||
      value: Development
 | 
					      value: Development
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,8 @@ inf:
 | 
				
			|||||||
      db: IdentityDb        # Ordering API SQL db name
 | 
					      db: IdentityDb        # Ordering API SQL db name
 | 
				
			||||||
    marketing:
 | 
					    marketing:
 | 
				
			||||||
      db: MarketingDb        # Marketing API SQL db name
 | 
					      db: MarketingDb        # Marketing API SQL db name
 | 
				
			||||||
 | 
					    webhooks:
 | 
				
			||||||
 | 
					      db: WebhooksDb            # Webhooks DB
 | 
				
			||||||
  mongo:
 | 
					  mongo:
 | 
				
			||||||
#    host: my-nosql-data     # Uncomment to use specify custom mongo host. By default nosql-data is used
 | 
					#    host: my-nosql-data     # Uncomment to use specify custom mongo host. By default nosql-data is used
 | 
				
			||||||
    locations:
 | 
					    locations:
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										21
									
								
								k8s/helm/webhooks-api/.helmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								k8s/helm/webhooks-api/.helmignore
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					# Patterns to ignore when building packages.
 | 
				
			||||||
 | 
					# This supports shell glob matching, relative path matching, and
 | 
				
			||||||
 | 
					# negation (prefixed with !). Only one pattern per line.
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					# Common VCS dirs
 | 
				
			||||||
 | 
					.git/
 | 
				
			||||||
 | 
					.gitignore
 | 
				
			||||||
 | 
					.bzr/
 | 
				
			||||||
 | 
					.bzrignore
 | 
				
			||||||
 | 
					.hg/
 | 
				
			||||||
 | 
					.hgignore
 | 
				
			||||||
 | 
					.svn/
 | 
				
			||||||
 | 
					# Common backup files
 | 
				
			||||||
 | 
					*.swp
 | 
				
			||||||
 | 
					*.bak
 | 
				
			||||||
 | 
					*.tmp
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					# Various IDEs
 | 
				
			||||||
 | 
					.project
 | 
				
			||||||
 | 
					.idea/
 | 
				
			||||||
 | 
					*.tmproj
 | 
				
			||||||
							
								
								
									
										5
									
								
								k8s/helm/webhooks-api/Chart.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								k8s/helm/webhooks-api/Chart.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					appVersion: "1.0"
 | 
				
			||||||
 | 
					description: A Helm chart for Kubernetes
 | 
				
			||||||
 | 
					name: webhooks-api
 | 
				
			||||||
 | 
					version: 0.1.0
 | 
				
			||||||
							
								
								
									
										8
									
								
								k8s/helm/webhooks-api/templates/NOTES.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								k8s/helm/webhooks-api/templates/NOTES.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					eShop Ordering API installed.
 | 
				
			||||||
 | 
					-----------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This API is not directly exposed outside cluster. If need to access it use:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "webhooks-api.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
 | 
				
			||||||
 | 
					echo "Visit http://127.0.0.1:8080 to use your application"
 | 
				
			||||||
 | 
					kubectl port-forward $POD_NAME 8080:80
 | 
				
			||||||
							
								
								
									
										32
									
								
								k8s/helm/webhooks-api/templates/_helpers.tpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								k8s/helm/webhooks-api/templates/_helpers.tpl
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					{{/* vim: set filetype=mustache: */}}
 | 
				
			||||||
 | 
					{{/*
 | 
				
			||||||
 | 
					Expand the name of the chart.
 | 
				
			||||||
 | 
					*/}}
 | 
				
			||||||
 | 
					{{- define "webhooks-api.name" -}}
 | 
				
			||||||
 | 
					{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{/*
 | 
				
			||||||
 | 
					Create a default fully qualified app name.
 | 
				
			||||||
 | 
					We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
 | 
				
			||||||
 | 
					If release name contains chart name it will be used as a full name.
 | 
				
			||||||
 | 
					*/}}
 | 
				
			||||||
 | 
					{{- define "webhooks-api.fullname" -}}
 | 
				
			||||||
 | 
					{{- if .Values.fullnameOverride -}}
 | 
				
			||||||
 | 
					{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- $name := default .Chart.Name .Values.nameOverride -}}
 | 
				
			||||||
 | 
					{{- if contains $name .Release.Name -}}
 | 
				
			||||||
 | 
					{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{/*
 | 
				
			||||||
 | 
					Create chart name and version as used by the chart label.
 | 
				
			||||||
 | 
					*/}}
 | 
				
			||||||
 | 
					{{- define "webhooks-api.chart" -}}
 | 
				
			||||||
 | 
					{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
							
								
								
									
										51
									
								
								k8s/helm/webhooks-api/templates/_names.tpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								k8s/helm/webhooks-api/templates/_names.tpl
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					{{- define "suffix-name" -}}
 | 
				
			||||||
 | 
					{{- if .Values.app.name -}}
 | 
				
			||||||
 | 
					{{- .Values.app.name -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- .Release.Name -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{- define "sql-name" -}}
 | 
				
			||||||
 | 
					{{- if .Values.inf.sql.host -}}
 | 
				
			||||||
 | 
					{{- .Values.inf.sql.host -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- printf "%s" "sql-data" -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{- define "mongo-name" -}}
 | 
				
			||||||
 | 
					{{- if .Values.inf.mongo.host -}}
 | 
				
			||||||
 | 
					{{- .Values.inf.mongo.host -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- printf "%s" "nosql-data" -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{- define "url-of" -}}
 | 
				
			||||||
 | 
					{{- $name := first .}}
 | 
				
			||||||
 | 
					{{- $ctx := last .}}
 | 
				
			||||||
 | 
					{{- if eq $name "" -}}
 | 
				
			||||||
 | 
					{{- $ctx.Values.inf.k8s.dns -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}}                {{/*Value is just <dns>/<name> */}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{- define "pathBase" -}}
 | 
				
			||||||
 | 
					{{- if .Values.inf.k8s.suffix -}}
 | 
				
			||||||
 | 
					{{- $suffix := include "suffix-name" . -}}
 | 
				
			||||||
 | 
					{{- printf "%s-%s"  .Values.pathBase $suffix -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- .Values.pathBase -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{- define "fqdn-image" -}}
 | 
				
			||||||
 | 
					{{- if .Values.inf.registry -}}
 | 
				
			||||||
 | 
					{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- .Values.image.repository -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
							
								
								
									
										20
									
								
								k8s/helm/webhooks-api/templates/configmap.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								k8s/helm/webhooks-api/templates/configmap.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					{{- $name := include "webhooks-api.fullname" . -}}
 | 
				
			||||||
 | 
					{{- $sqlsrv := include "sql-name" . -}}
 | 
				
			||||||
 | 
					{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: ConfigMap
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: "cfg-{{ $name }}"
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    app: {{ template "webhooks-api.name" . }}
 | 
				
			||||||
 | 
					    chart: {{ template "webhooks-api.chart" .}}
 | 
				
			||||||
 | 
					    release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					    heritage: {{ .Release.Service }}
 | 
				
			||||||
 | 
					data:
 | 
				
			||||||
 | 
					  webhooks__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.webhooks.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }};
 | 
				
			||||||
 | 
					  urls__IdentityUrl: http://{{ $identity }}
 | 
				
			||||||
 | 
					  urls__IdentityUrlExternal: http://{{ $identity }}
 | 
				
			||||||
 | 
					  all__EventBusConnection: {{ .Values.inf.eventbus.constr }}
 | 
				
			||||||
 | 
					  all__InstrumentationKey: {{ .Values.inf.appinsights.key }}
 | 
				
			||||||
 | 
					  all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}"
 | 
				
			||||||
							
								
								
									
										71
									
								
								k8s/helm/webhooks-api/templates/deployment.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								k8s/helm/webhooks-api/templates/deployment.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					{{- $name := include "webhooks-api.fullname" . -}}
 | 
				
			||||||
 | 
					{{- $cfgname := printf "%s-%s" "cfg" $name -}}
 | 
				
			||||||
 | 
					apiVersion: apps/v1beta2
 | 
				
			||||||
 | 
					kind: Deployment
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: {{ template "webhooks-api.fullname" . }}
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    ufo: {{ $cfgname}}
 | 
				
			||||||
 | 
					    app: {{ template "webhooks-api.name" . }}
 | 
				
			||||||
 | 
					    chart: {{ template "webhooks-api.chart" . }}
 | 
				
			||||||
 | 
					    release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					    heritage: {{ .Release.Service }}
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  replicas: {{ .Values.replicaCount }}
 | 
				
			||||||
 | 
					  selector:
 | 
				
			||||||
 | 
					    matchLabels:
 | 
				
			||||||
 | 
					      app: {{ template "webhooks-api.name" . }}
 | 
				
			||||||
 | 
					      release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					  template:
 | 
				
			||||||
 | 
					    metadata:
 | 
				
			||||||
 | 
					      labels:
 | 
				
			||||||
 | 
					        app: {{ template "webhooks-api.name" . }}
 | 
				
			||||||
 | 
					        release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					    spec:
 | 
				
			||||||
 | 
					      {{ if .Values.inf.registry -}}
 | 
				
			||||||
 | 
					      imagePullSecrets:
 | 
				
			||||||
 | 
					      - name: {{ .Values.inf.registry.secretName }}
 | 
				
			||||||
 | 
					      {{- end }}
 | 
				
			||||||
 | 
					      containers:
 | 
				
			||||||
 | 
					        - name: {{ .Chart.Name }}
 | 
				
			||||||
 | 
					          image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}"
 | 
				
			||||||
 | 
					          imagePullPolicy: {{ .Values.image.pullPolicy }}
 | 
				
			||||||
 | 
					          env:
 | 
				
			||||||
 | 
					            - name: PATH_BASE
 | 
				
			||||||
 | 
					              value: {{ include "pathBase" . }}
 | 
				
			||||||
 | 
					            - name: k8sname
 | 
				
			||||||
 | 
					              value: {{ .Values.clusterName }}
 | 
				
			||||||
 | 
					          {{- if .Values.env.values -}}
 | 
				
			||||||
 | 
					          {{- range .Values.env.values }}
 | 
				
			||||||
 | 
					            - name: {{ .name }}
 | 
				
			||||||
 | 
					              value: {{ .value | quote }}
 | 
				
			||||||
 | 
					          {{- end -}}
 | 
				
			||||||
 | 
					          {{- end -}}
 | 
				
			||||||
 | 
					          {{- if .Values.env.configmap -}}
 | 
				
			||||||
 | 
					          {{- range .Values.env.configmap }}
 | 
				
			||||||
 | 
					            - name: {{ .name }}
 | 
				
			||||||
 | 
					              valueFrom:
 | 
				
			||||||
 | 
					                configMapKeyRef:
 | 
				
			||||||
 | 
					                  name: {{ $cfgname }}
 | 
				
			||||||
 | 
					                  key: {{ .key }}
 | 
				
			||||||
 | 
					          {{- end -}}
 | 
				
			||||||
 | 
					          {{- end }}
 | 
				
			||||||
 | 
					          ports:
 | 
				
			||||||
 | 
					            - name: http
 | 
				
			||||||
 | 
					              containerPort: 80
 | 
				
			||||||
 | 
					              protocol: TCP
 | 
				
			||||||
 | 
					          resources:
 | 
				
			||||||
 | 
					{{ toYaml .Values.resources | indent 12 }}
 | 
				
			||||||
 | 
					    {{- with .Values.nodeSelector }}
 | 
				
			||||||
 | 
					      nodeSelector:
 | 
				
			||||||
 | 
					{{ toYaml . | indent 8 }}
 | 
				
			||||||
 | 
					    {{- end }}
 | 
				
			||||||
 | 
					    {{- with .Values.affinity }}
 | 
				
			||||||
 | 
					      affinity:
 | 
				
			||||||
 | 
					{{ toYaml . | indent 8 }}
 | 
				
			||||||
 | 
					    {{- end }}
 | 
				
			||||||
 | 
					    {{- with .Values.tolerations }}
 | 
				
			||||||
 | 
					      tolerations:
 | 
				
			||||||
 | 
					{{ toYaml . | indent 8 }}
 | 
				
			||||||
 | 
					    {{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										33
									
								
								k8s/helm/webhooks-api/templates/ingress.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								k8s/helm/webhooks-api/templates/ingress.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					{{- if .Values.ingress.enabled -}}
 | 
				
			||||||
 | 
					{{- $ingressPath := include "pathBase" . -}}
 | 
				
			||||||
 | 
					apiVersion: extensions/v1beta1
 | 
				
			||||||
 | 
					kind: Ingress
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: {{ template "webhooks-api.fullname" . }}
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    app: {{ template "webhooks-api.name" . }}
 | 
				
			||||||
 | 
					    chart: {{ template "webhooks-api.chart" . }}
 | 
				
			||||||
 | 
					    release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					    heritage: {{ .Release.Service }}
 | 
				
			||||||
 | 
					{{- with .Values.ingress.annotations }}
 | 
				
			||||||
 | 
					  annotations:
 | 
				
			||||||
 | 
					{{ toYaml . | indent 4 }}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					{{- if .Values.ingress.tls }}
 | 
				
			||||||
 | 
					  tls:
 | 
				
			||||||
 | 
					  {{- range .Values.ingress.tls }}
 | 
				
			||||||
 | 
					    - hosts:
 | 
				
			||||||
 | 
					        - {{ .Values.inf.k8s.dns }}
 | 
				
			||||||
 | 
					      secretName: {{ .secretName }}
 | 
				
			||||||
 | 
					  {{- end }}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					  rules:
 | 
				
			||||||
 | 
					    - host: {{ .Values.inf.k8s.dns }}
 | 
				
			||||||
 | 
					      http:
 | 
				
			||||||
 | 
					        paths:
 | 
				
			||||||
 | 
					          - path: {{ $ingressPath }}
 | 
				
			||||||
 | 
					            backend:
 | 
				
			||||||
 | 
					              serviceName: {{  .Values.app.svc.webhooks }}
 | 
				
			||||||
 | 
					              servicePort: http
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
							
								
								
									
										19
									
								
								k8s/helm/webhooks-api/templates/service.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								k8s/helm/webhooks-api/templates/service.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: Service
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: {{ .Values.app.svc.webhooks }}
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    app: {{ template "webhooks-api.name" . }}
 | 
				
			||||||
 | 
					    chart: {{ template "webhooks-api.chart" . }}
 | 
				
			||||||
 | 
					    release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					    heritage: {{ .Release.Service }}
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  type: {{ .Values.service.type }}
 | 
				
			||||||
 | 
					  ports:
 | 
				
			||||||
 | 
					    - port: {{ .Values.service.port }}
 | 
				
			||||||
 | 
					      targetPort: http
 | 
				
			||||||
 | 
					      protocol: TCP
 | 
				
			||||||
 | 
					      name: http
 | 
				
			||||||
 | 
					  selector:
 | 
				
			||||||
 | 
					    app: {{ template "webhooks-api.name" . }}
 | 
				
			||||||
 | 
					    release: {{ .Release.Name }}
 | 
				
			||||||
							
								
								
									
										53
									
								
								k8s/helm/webhooks-api/values.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								k8s/helm/webhooks-api/values.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					replicaCount: 1
 | 
				
			||||||
 | 
					clusterName: eshop-aks
 | 
				
			||||||
 | 
					pathBase: /webhooks-api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					image:
 | 
				
			||||||
 | 
					  repository: eshop/webhooks.api
 | 
				
			||||||
 | 
					  tag: latest
 | 
				
			||||||
 | 
					  pullPolicy: IfNotPresent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					service:
 | 
				
			||||||
 | 
					  type: ClusterIP
 | 
				
			||||||
 | 
					  port: 80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ingress:
 | 
				
			||||||
 | 
					  enabled: true
 | 
				
			||||||
 | 
					  annotations: {}
 | 
				
			||||||
 | 
					  hosts:
 | 
				
			||||||
 | 
					    - chart-example.local
 | 
				
			||||||
 | 
					  tls: []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					resources: {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nodeSelector: {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tolerations: []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					affinity: {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# env defines the environment variables that will be declared in the pod
 | 
				
			||||||
 | 
					env:
 | 
				
			||||||
 | 
					  urls:
 | 
				
			||||||
 | 
					  # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap).
 | 
				
			||||||
 | 
					  configmap:
 | 
				
			||||||
 | 
					    - name: ConnectionString
 | 
				
			||||||
 | 
					      key: webhooks__ConnectionString
 | 
				
			||||||
 | 
					    - name: ApplicationInsights__InstrumentationKey
 | 
				
			||||||
 | 
					      key: all__InstrumentationKey
 | 
				
			||||||
 | 
					    - name: EventBusConnection
 | 
				
			||||||
 | 
					      key: all__EventBusConnection
 | 
				
			||||||
 | 
					    - name: AzureServiceBusEnabled
 | 
				
			||||||
 | 
					      key: all__UseAzureServiceBus
 | 
				
			||||||
 | 
					    - name: IdentityUrl
 | 
				
			||||||
 | 
					      key: urls__IdentityUrl
 | 
				
			||||||
 | 
					    - name: IdentityUrlExternal
 | 
				
			||||||
 | 
					      key: urls__IdentityUrlExternal
 | 
				
			||||||
 | 
					      # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
 | 
				
			||||||
 | 
					  values:
 | 
				
			||||||
 | 
					    - name: ASPNETCORE_ENVIRONMENT
 | 
				
			||||||
 | 
					      value: Development
 | 
				
			||||||
 | 
					    - name: OrchestratorType
 | 
				
			||||||
 | 
					      value: 'K8S'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										21
									
								
								k8s/helm/webhooks-web/.helmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								k8s/helm/webhooks-web/.helmignore
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					# Patterns to ignore when building packages.
 | 
				
			||||||
 | 
					# This supports shell glob matching, relative path matching, and
 | 
				
			||||||
 | 
					# negation (prefixed with !). Only one pattern per line.
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					# Common VCS dirs
 | 
				
			||||||
 | 
					.git/
 | 
				
			||||||
 | 
					.gitignore
 | 
				
			||||||
 | 
					.bzr/
 | 
				
			||||||
 | 
					.bzrignore
 | 
				
			||||||
 | 
					.hg/
 | 
				
			||||||
 | 
					.hgignore
 | 
				
			||||||
 | 
					.svn/
 | 
				
			||||||
 | 
					# Common backup files
 | 
				
			||||||
 | 
					*.swp
 | 
				
			||||||
 | 
					*.bak
 | 
				
			||||||
 | 
					*.tmp
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					# Various IDEs
 | 
				
			||||||
 | 
					.project
 | 
				
			||||||
 | 
					.idea/
 | 
				
			||||||
 | 
					*.tmproj
 | 
				
			||||||
							
								
								
									
										5
									
								
								k8s/helm/webhooks-web/Chart.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								k8s/helm/webhooks-web/Chart.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					appVersion: "1.0"
 | 
				
			||||||
 | 
					description: A Helm chart for Kubernetes
 | 
				
			||||||
 | 
					name: webhooks-web
 | 
				
			||||||
 | 
					version: 0.1.0
 | 
				
			||||||
							
								
								
									
										8
									
								
								k8s/helm/webhooks-web/templates/NOTES.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								k8s/helm/webhooks-web/templates/NOTES.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					eShop Ordering API installed.
 | 
				
			||||||
 | 
					-----------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This API is not directly exposed outside cluster. If need to access it use:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "webhooks-web.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
 | 
				
			||||||
 | 
					echo "Visit http://127.0.0.1:8080 to use your application"
 | 
				
			||||||
 | 
					kubectl port-forward $POD_NAME 8080:80
 | 
				
			||||||
							
								
								
									
										32
									
								
								k8s/helm/webhooks-web/templates/_helpers.tpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								k8s/helm/webhooks-web/templates/_helpers.tpl
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					{{/* vim: set filetype=mustache: */}}
 | 
				
			||||||
 | 
					{{/*
 | 
				
			||||||
 | 
					Expand the name of the chart.
 | 
				
			||||||
 | 
					*/}}
 | 
				
			||||||
 | 
					{{- define "webhooks-web.name" -}}
 | 
				
			||||||
 | 
					{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{/*
 | 
				
			||||||
 | 
					Create a default fully qualified app name.
 | 
				
			||||||
 | 
					We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
 | 
				
			||||||
 | 
					If release name contains chart name it will be used as a full name.
 | 
				
			||||||
 | 
					*/}}
 | 
				
			||||||
 | 
					{{- define "webhooks-web.fullname" -}}
 | 
				
			||||||
 | 
					{{- if .Values.fullnameOverride -}}
 | 
				
			||||||
 | 
					{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- $name := default .Chart.Name .Values.nameOverride -}}
 | 
				
			||||||
 | 
					{{- if contains $name .Release.Name -}}
 | 
				
			||||||
 | 
					{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{/*
 | 
				
			||||||
 | 
					Create chart name and version as used by the chart label.
 | 
				
			||||||
 | 
					*/}}
 | 
				
			||||||
 | 
					{{- define "webhooks-web.chart" -}}
 | 
				
			||||||
 | 
					{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
							
								
								
									
										51
									
								
								k8s/helm/webhooks-web/templates/_names.tpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								k8s/helm/webhooks-web/templates/_names.tpl
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					{{- define "suffix-name" -}}
 | 
				
			||||||
 | 
					{{- if .Values.app.name -}}
 | 
				
			||||||
 | 
					{{- .Values.app.name -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- .Release.Name -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{- define "sql-name" -}}
 | 
				
			||||||
 | 
					{{- if .Values.inf.sql.host -}}
 | 
				
			||||||
 | 
					{{- .Values.inf.sql.host -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- printf "%s" "sql-data" -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{- define "mongo-name" -}}
 | 
				
			||||||
 | 
					{{- if .Values.inf.mongo.host -}}
 | 
				
			||||||
 | 
					{{- .Values.inf.mongo.host -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- printf "%s" "nosql-data" -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{- define "url-of" -}}
 | 
				
			||||||
 | 
					{{- $name := first .}}
 | 
				
			||||||
 | 
					{{- $ctx := last .}}
 | 
				
			||||||
 | 
					{{- if eq $name "" -}}
 | 
				
			||||||
 | 
					{{- $ctx.Values.inf.k8s.dns -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}}                {{/*Value is just <dns>/<name> */}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{- define "pathBase" -}}
 | 
				
			||||||
 | 
					{{- if .Values.inf.k8s.suffix -}}
 | 
				
			||||||
 | 
					{{- $suffix := include "suffix-name" . -}}
 | 
				
			||||||
 | 
					{{- printf "%s-%s"  .Values.pathBase $suffix -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- .Values.pathBase -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{- define "fqdn-image" -}}
 | 
				
			||||||
 | 
					{{- if .Values.inf.registry -}}
 | 
				
			||||||
 | 
					{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}}
 | 
				
			||||||
 | 
					{{- else -}}
 | 
				
			||||||
 | 
					{{- .Values.image.repository -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
 | 
					{{- end -}}
 | 
				
			||||||
							
								
								
									
										19
									
								
								k8s/helm/webhooks-web/templates/configmap.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								k8s/helm/webhooks-web/templates/configmap.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					{{- $name := include "webhooks-web.fullname" . -}}
 | 
				
			||||||
 | 
					{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}}
 | 
				
			||||||
 | 
					{{- $webhooksweb := include "url-of" (list .Values.app.ingress.entries.webhooksweb .) -}}
 | 
				
			||||||
 | 
					{{- $webhooks := include "url-of" (list .Values.app.ingress.entries.webhooks .) -}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: ConfigMap
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: "cfg-{{ $name }}"
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    app: {{ template "webhooks-web.name" . }}
 | 
				
			||||||
 | 
					    chart: {{ template "webhooks-web.chart" .}}
 | 
				
			||||||
 | 
					    release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					    heritage: {{ .Release.Service }}
 | 
				
			||||||
 | 
					data:
 | 
				
			||||||
 | 
					  urls__webhooks: http://{{ $webhooks }}
 | 
				
			||||||
 | 
					  identity_e: http://{{ $identity }}
 | 
				
			||||||
 | 
					  webhooksweb_e: http://{{ $webhooksweb }}
 | 
				
			||||||
 | 
					  urls_webhooksweb: http://{{ .Values.app.svc.webhooksweb }}
 | 
				
			||||||
							
								
								
									
										71
									
								
								k8s/helm/webhooks-web/templates/deployment.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								k8s/helm/webhooks-web/templates/deployment.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					{{- $name := include "webhooks-web.fullname" . -}}
 | 
				
			||||||
 | 
					{{- $cfgname := printf "%s-%s" "cfg" $name -}}
 | 
				
			||||||
 | 
					apiVersion: apps/v1beta2
 | 
				
			||||||
 | 
					kind: Deployment
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: {{ template "webhooks-web.fullname" . }}
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    ufo: {{ $cfgname}}
 | 
				
			||||||
 | 
					    app: {{ template "webhooks-web.name" . }}
 | 
				
			||||||
 | 
					    chart: {{ template "webhooks-web.chart" . }}
 | 
				
			||||||
 | 
					    release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					    heritage: {{ .Release.Service }}
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  replicas: {{ .Values.replicaCount }}
 | 
				
			||||||
 | 
					  selector:
 | 
				
			||||||
 | 
					    matchLabels:
 | 
				
			||||||
 | 
					      app: {{ template "webhooks-web.name" . }}
 | 
				
			||||||
 | 
					      release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					  template:
 | 
				
			||||||
 | 
					    metadata:
 | 
				
			||||||
 | 
					      labels:
 | 
				
			||||||
 | 
					        app: {{ template "webhooks-web.name" . }}
 | 
				
			||||||
 | 
					        release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					    spec:
 | 
				
			||||||
 | 
					      {{ if .Values.inf.registry -}}
 | 
				
			||||||
 | 
					      imagePullSecrets:
 | 
				
			||||||
 | 
					      - name: {{ .Values.inf.registry.secretName }}
 | 
				
			||||||
 | 
					      {{- end }}
 | 
				
			||||||
 | 
					      containers:
 | 
				
			||||||
 | 
					        - name: {{ .Chart.Name }}
 | 
				
			||||||
 | 
					          image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}"
 | 
				
			||||||
 | 
					          imagePullPolicy: {{ .Values.image.pullPolicy }}
 | 
				
			||||||
 | 
					          env:
 | 
				
			||||||
 | 
					            - name: PATH_BASE
 | 
				
			||||||
 | 
					              value: {{ include "pathBase" . }}
 | 
				
			||||||
 | 
					            - name: k8sname
 | 
				
			||||||
 | 
					              value: {{ .Values.clusterName }}
 | 
				
			||||||
 | 
					          {{- if .Values.env.values -}}
 | 
				
			||||||
 | 
					          {{- range .Values.env.values }}
 | 
				
			||||||
 | 
					            - name: {{ .name }}
 | 
				
			||||||
 | 
					              value: {{ .value | quote }}
 | 
				
			||||||
 | 
					          {{- end -}}
 | 
				
			||||||
 | 
					          {{- end -}}
 | 
				
			||||||
 | 
					          {{- if .Values.env.configmap -}}
 | 
				
			||||||
 | 
					          {{- range .Values.env.configmap }}
 | 
				
			||||||
 | 
					            - name: {{ .name }}
 | 
				
			||||||
 | 
					              valueFrom:
 | 
				
			||||||
 | 
					                configMapKeyRef:
 | 
				
			||||||
 | 
					                  name: {{ $cfgname }}
 | 
				
			||||||
 | 
					                  key: {{ .key }}
 | 
				
			||||||
 | 
					          {{- end -}}
 | 
				
			||||||
 | 
					          {{- end }}
 | 
				
			||||||
 | 
					          ports:
 | 
				
			||||||
 | 
					            - name: http
 | 
				
			||||||
 | 
					              containerPort: 80
 | 
				
			||||||
 | 
					              protocol: TCP
 | 
				
			||||||
 | 
					          resources:
 | 
				
			||||||
 | 
					{{ toYaml .Values.resources | indent 12 }}
 | 
				
			||||||
 | 
					    {{- with .Values.nodeSelector }}
 | 
				
			||||||
 | 
					      nodeSelector:
 | 
				
			||||||
 | 
					{{ toYaml . | indent 8 }}
 | 
				
			||||||
 | 
					    {{- end }}
 | 
				
			||||||
 | 
					    {{- with .Values.affinity }}
 | 
				
			||||||
 | 
					      affinity:
 | 
				
			||||||
 | 
					{{ toYaml . | indent 8 }}
 | 
				
			||||||
 | 
					    {{- end }}
 | 
				
			||||||
 | 
					    {{- with .Values.tolerations }}
 | 
				
			||||||
 | 
					      tolerations:
 | 
				
			||||||
 | 
					{{ toYaml . | indent 8 }}
 | 
				
			||||||
 | 
					    {{- end }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										33
									
								
								k8s/helm/webhooks-web/templates/ingress.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								k8s/helm/webhooks-web/templates/ingress.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					{{- if .Values.ingress.enabled -}}
 | 
				
			||||||
 | 
					{{- $ingressPath := include "pathBase" . -}}
 | 
				
			||||||
 | 
					apiVersion: extensions/v1beta1
 | 
				
			||||||
 | 
					kind: Ingress
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: {{ template "webhooks-web.fullname" . }}
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    app: {{ template "webhooks-web.name" . }}
 | 
				
			||||||
 | 
					    chart: {{ template "webhooks-web.chart" . }}
 | 
				
			||||||
 | 
					    release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					    heritage: {{ .Release.Service }}
 | 
				
			||||||
 | 
					{{- with .Values.ingress.annotations }}
 | 
				
			||||||
 | 
					  annotations:
 | 
				
			||||||
 | 
					{{ toYaml . | indent 4 }}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					{{- if .Values.ingress.tls }}
 | 
				
			||||||
 | 
					  tls:
 | 
				
			||||||
 | 
					  {{- range .Values.ingress.tls }}
 | 
				
			||||||
 | 
					    - hosts:
 | 
				
			||||||
 | 
					        - {{ .Values.inf.k8s.dns }}
 | 
				
			||||||
 | 
					      secretName: {{ .secretName }}
 | 
				
			||||||
 | 
					  {{- end }}
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
 | 
					  rules:
 | 
				
			||||||
 | 
					    - host: {{ .Values.inf.k8s.dns }}
 | 
				
			||||||
 | 
					      http:
 | 
				
			||||||
 | 
					        paths:
 | 
				
			||||||
 | 
					          - path: {{ $ingressPath }}
 | 
				
			||||||
 | 
					            backend:
 | 
				
			||||||
 | 
					              serviceName: {{  .Values.app.svc.webhooksweb }}
 | 
				
			||||||
 | 
					              servicePort: http
 | 
				
			||||||
 | 
					{{- end }}
 | 
				
			||||||
							
								
								
									
										19
									
								
								k8s/helm/webhooks-web/templates/service.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								k8s/helm/webhooks-web/templates/service.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: Service
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: {{ .Values.app.svc.webhooksweb }}
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    app: {{ template "webhooks-web.name" . }}
 | 
				
			||||||
 | 
					    chart: {{ template "webhooks-web.chart" . }}
 | 
				
			||||||
 | 
					    release: {{ .Release.Name }}
 | 
				
			||||||
 | 
					    heritage: {{ .Release.Service }}
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  type: {{ .Values.service.type }}
 | 
				
			||||||
 | 
					  ports:
 | 
				
			||||||
 | 
					    - port: {{ .Values.service.port }}
 | 
				
			||||||
 | 
					      targetPort: http
 | 
				
			||||||
 | 
					      protocol: TCP
 | 
				
			||||||
 | 
					      name: http
 | 
				
			||||||
 | 
					  selector:
 | 
				
			||||||
 | 
					    app: {{ template "webhooks-web.name" . }}
 | 
				
			||||||
 | 
					    release: {{ .Release.Name }}
 | 
				
			||||||
							
								
								
									
										52
									
								
								k8s/helm/webhooks-web/values.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								k8s/helm/webhooks-web/values.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					replicaCount: 1
 | 
				
			||||||
 | 
					clusterName: eshop-aks
 | 
				
			||||||
 | 
					pathBase: /webhooks-web
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					image:
 | 
				
			||||||
 | 
					  repository: eshop/webhooks.client
 | 
				
			||||||
 | 
					  tag: latest
 | 
				
			||||||
 | 
					  pullPolicy: IfNotPresent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					service:
 | 
				
			||||||
 | 
					  type: ClusterIP
 | 
				
			||||||
 | 
					  port: 80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ingress:
 | 
				
			||||||
 | 
					  enabled: true
 | 
				
			||||||
 | 
					  annotations: {}
 | 
				
			||||||
 | 
					  hosts:
 | 
				
			||||||
 | 
					    - chart-example.local
 | 
				
			||||||
 | 
					  tls: []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					resources: {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nodeSelector: {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tolerations: []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					affinity: {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# env defines the environment variables that will be declared in the pod
 | 
				
			||||||
 | 
					env:
 | 
				
			||||||
 | 
					  urls:
 | 
				
			||||||
 | 
					  # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap).
 | 
				
			||||||
 | 
					  configmap:
 | 
				
			||||||
 | 
					    - name: WebhooksUrl
 | 
				
			||||||
 | 
					      key: urls__webhooks
 | 
				
			||||||
 | 
					    - name: IdentityUrl
 | 
				
			||||||
 | 
					      key: identity_e
 | 
				
			||||||
 | 
					    - name: CallbackUrl
 | 
				
			||||||
 | 
					      key: webhooksweb_e
 | 
				
			||||||
 | 
					    - name: SelfUrl
 | 
				
			||||||
 | 
					      key: webhooksweb_e
 | 
				
			||||||
 | 
					      # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value)
 | 
				
			||||||
 | 
					  values:
 | 
				
			||||||
 | 
					    - name: ASPNETCORE_ENVIRONMENT
 | 
				
			||||||
 | 
					      value: Production
 | 
				
			||||||
 | 
					    - name: OrchestratorType
 | 
				
			||||||
 | 
					      value: 'K8S'
 | 
				
			||||||
 | 
					    - name: Token
 | 
				
			||||||
 | 
					      value: "WebHooks-Demo-Web"       # Can use whatever you want
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -6,7 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <PackageReference Include="Polly" Version="6.0.1" />
 | 
					    <PackageReference Include="Polly" Version="6.0.1" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" />
 | 
					    <PackageReference Include="Microsoft.AspNetCore.App" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</Project>
 | 
					</Project>
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
 | 
				
			|||||||
                new ApiResource("locations", "Locations Service"),
 | 
					                new ApiResource("locations", "Locations Service"),
 | 
				
			||||||
                new ApiResource("mobileshoppingagg", "Mobile Shopping Aggregator"),
 | 
					                new ApiResource("mobileshoppingagg", "Mobile Shopping Aggregator"),
 | 
				
			||||||
                new ApiResource("webshoppingagg", "Web Shopping Aggregator"),
 | 
					                new ApiResource("webshoppingagg", "Web Shopping Aggregator"),
 | 
				
			||||||
                new ApiResource("orders.signalrhub", "Ordering Signalr Hub")
 | 
					                new ApiResource("orders.signalrhub", "Ordering Signalr Hub"),
 | 
				
			||||||
 | 
					                new ApiResource("webhooks", "Webhooks registration Service"),
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -57,7 +58,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
 | 
				
			|||||||
                        "locations",
 | 
					                        "locations",
 | 
				
			||||||
                        "marketing",
 | 
					                        "marketing",
 | 
				
			||||||
                        "webshoppingagg",
 | 
					                        "webshoppingagg",
 | 
				
			||||||
                        "orders.signalrhub"
 | 
					                        "orders.signalrhub",
 | 
				
			||||||
 | 
					                        "webhooks"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                new Client
 | 
					                new Client
 | 
				
			||||||
@ -84,7 +86,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
 | 
				
			|||||||
                        "basket",
 | 
					                        "basket",
 | 
				
			||||||
                        "locations",
 | 
					                        "locations",
 | 
				
			||||||
                        "marketing",
 | 
					                        "marketing",
 | 
				
			||||||
                        "mobileshoppingagg"
 | 
					                        "mobileshoppingagg",
 | 
				
			||||||
 | 
					                        "webhooks"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    //Allow requesting refresh tokens for long lived API access
 | 
					                    //Allow requesting refresh tokens for long lived API access
 | 
				
			||||||
                    AllowOfflineAccess = true,
 | 
					                    AllowOfflineAccess = true,
 | 
				
			||||||
@ -122,7 +125,40 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
 | 
				
			|||||||
                        "locations",
 | 
					                        "locations",
 | 
				
			||||||
                        "marketing",
 | 
					                        "marketing",
 | 
				
			||||||
                        "webshoppingagg",
 | 
					                        "webshoppingagg",
 | 
				
			||||||
                        "orders.signalrhub"
 | 
					                        "orders.signalrhub",
 | 
				
			||||||
 | 
					                        "webhooks"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    AccessTokenLifetime = 60*60*2, // 2 hours
 | 
				
			||||||
 | 
					                    IdentityTokenLifetime= 60*60*2 // 2 hours
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                new Client
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ClientId = "webhooksclient",
 | 
				
			||||||
 | 
					                    ClientName = "Webhooks Client",
 | 
				
			||||||
 | 
					                    ClientSecrets = new List<Secret>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        new Secret("secret".Sha256())
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    ClientUri = $"{clientsUrl["WebhooksWeb"]}",                             // public uri of the client
 | 
				
			||||||
 | 
					                    AllowedGrantTypes = GrantTypes.Hybrid,
 | 
				
			||||||
 | 
					                    AllowAccessTokensViaBrowser = false,
 | 
				
			||||||
 | 
					                    RequireConsent = false,
 | 
				
			||||||
 | 
					                    AllowOfflineAccess = true,
 | 
				
			||||||
 | 
					                    AlwaysIncludeUserClaimsInIdToken = true,
 | 
				
			||||||
 | 
					                    RedirectUris = new List<string>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        $"{clientsUrl["WebhooksWeb"]}/signin-oidc"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    PostLogoutRedirectUris = new List<string>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        $"{clientsUrl["WebhooksWeb"]}/signout-callback-oidc"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    AllowedScopes = new List<string>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        IdentityServerConstants.StandardScopes.OpenId,
 | 
				
			||||||
 | 
					                        IdentityServerConstants.StandardScopes.Profile,
 | 
				
			||||||
 | 
					                        IdentityServerConstants.StandardScopes.OfflineAccess,
 | 
				
			||||||
 | 
					                        "webhooks"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    AccessTokenLifetime = 60*60*2, // 2 hours
 | 
					                    AccessTokenLifetime = 60*60*2, // 2 hours
 | 
				
			||||||
                    IdentityTokenLifetime= 60*60*2 // 2 hours
 | 
					                    IdentityTokenLifetime= 60*60*2 // 2 hours
 | 
				
			||||||
@ -157,7 +193,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
 | 
				
			|||||||
                        "basket",
 | 
					                        "basket",
 | 
				
			||||||
                        "locations",
 | 
					                        "locations",
 | 
				
			||||||
                        "marketing",
 | 
					                        "marketing",
 | 
				
			||||||
                        "webshoppingagg"
 | 
					                        "webshoppingagg",
 | 
				
			||||||
 | 
					                        "webhooks"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                new Client
 | 
					                new Client
 | 
				
			||||||
@ -249,6 +286,21 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
 | 
				
			|||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        "webshoppingagg"
 | 
					                        "webshoppingagg"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                new Client
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ClientId = "webhooksswaggerui",
 | 
				
			||||||
 | 
					                    ClientName = "WebHooks Service Swagger UI",
 | 
				
			||||||
 | 
					                    AllowedGrantTypes = GrantTypes.Implicit,
 | 
				
			||||||
 | 
					                    AllowAccessTokensViaBrowser = true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    RedirectUris = { $"{clientsUrl["WebhooksApi"]}/swagger/oauth2-redirect.html" },
 | 
				
			||||||
 | 
					                    PostLogoutRedirectUris = { $"{clientsUrl["WebhooksApi"]}/swagger/" },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    AllowedScopes =
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        "webhooks"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
 | 
				
			|||||||
            clientUrls.Add("OrderingApi", configuration.GetValue<string>("OrderingApiClient"));
 | 
					            clientUrls.Add("OrderingApi", configuration.GetValue<string>("OrderingApiClient"));
 | 
				
			||||||
            clientUrls.Add("MobileShoppingAgg", configuration.GetValue<string>("MobileShoppingAggClient"));
 | 
					            clientUrls.Add("MobileShoppingAgg", configuration.GetValue<string>("MobileShoppingAggClient"));
 | 
				
			||||||
            clientUrls.Add("WebShoppingAgg", configuration.GetValue<string>("WebShoppingAggClient"));
 | 
					            clientUrls.Add("WebShoppingAgg", configuration.GetValue<string>("WebShoppingAggClient"));
 | 
				
			||||||
 | 
					            clientUrls.Add("WebhooksApi", configuration.GetValue<string>("WebhooksApiClient"));
 | 
				
			||||||
 | 
					            clientUrls.Add("WebhooksWeb", configuration.GetValue<string>("WebhooksWebClient"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!context.Clients.Any())
 | 
					            if (!context.Clients.Any())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Controllers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class HomeController : Controller
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // GET: /<controller>/
 | 
				
			||||||
 | 
					        public IActionResult Index()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return new RedirectResult("~/swagger");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.ComponentModel.DataAnnotations;
 | 
				
			||||||
 | 
					using Webhooks.API.Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Controllers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhookSubscriptionRequest : IValidatableObject
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public string Url { get; set; }
 | 
				
			||||||
 | 
					        public string Token { get; set; }
 | 
				
			||||||
 | 
					        public string Event { get; set; }
 | 
				
			||||||
 | 
					        public string GrantUrl { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!Uri.IsWellFormedUriString(GrantUrl, UriKind.Absolute))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                yield return new ValidationResult("GrantUrl is not valid", new[] { nameof(GrantUrl) });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!Uri.IsWellFormedUriString(Url, UriKind.Absolute))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                yield return new ValidationResult("Url is not valid", new[] { nameof(Url) });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var isOk = Enum.TryParse<WebhookType>(Event, ignoreCase: true, result: out WebhookType whtype);
 | 
				
			||||||
 | 
					            if (!isOk)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                yield return new ValidationResult($"{Event} is invalid event name", new[] { nameof(Event) });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Net;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Webhooks.API.Infrastructure;
 | 
				
			||||||
 | 
					using Webhooks.API.Model;
 | 
				
			||||||
 | 
					using Webhooks.API.Services;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Controllers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [Route("api/v1/[controller]")]
 | 
				
			||||||
 | 
					    [ApiController]
 | 
				
			||||||
 | 
					    public class WebhooksController : ControllerBase
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly WebhooksContext _dbContext;
 | 
				
			||||||
 | 
					        private readonly IIdentityService _identityService;
 | 
				
			||||||
 | 
					        private readonly IGrantUrlTesterService _grantUrlTester;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public WebhooksController(WebhooksContext dbContext, IIdentityService identityService, IGrantUrlTesterService grantUrlTester)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _dbContext = dbContext;
 | 
				
			||||||
 | 
					            _identityService = identityService;
 | 
				
			||||||
 | 
					            _grantUrlTester = grantUrlTester;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Authorize]
 | 
				
			||||||
 | 
					        [HttpGet]
 | 
				
			||||||
 | 
					        [ProducesResponseType(typeof(IEnumerable<WebhookSubscription>), (int)HttpStatusCode.OK)]
 | 
				
			||||||
 | 
					        public async Task<IActionResult> ListByUser()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var userId = _identityService.GetUserIdentity();
 | 
				
			||||||
 | 
					            var data = await _dbContext.Subscriptions.Where(s => s.UserId == userId).ToListAsync();
 | 
				
			||||||
 | 
					            return Ok(data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Authorize]
 | 
				
			||||||
 | 
					        [HttpGet("{id:int}")]
 | 
				
			||||||
 | 
					        [ProducesResponseType(typeof(WebhookSubscription), (int)HttpStatusCode.OK)]
 | 
				
			||||||
 | 
					        [ProducesResponseType((int)HttpStatusCode.NotFound)]
 | 
				
			||||||
 | 
					        public async Task<IActionResult> GetByUserAndId(int id)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var userId = _identityService.GetUserIdentity();
 | 
				
			||||||
 | 
					            var subscription = await _dbContext.Subscriptions.SingleOrDefaultAsync(s => s.Id == id && s.UserId == userId);
 | 
				
			||||||
 | 
					            if (subscription != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return Ok(subscription);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return NotFound($"Subscriptions {id} not found");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Authorize]
 | 
				
			||||||
 | 
					        [HttpPost]
 | 
				
			||||||
 | 
					        [ProducesResponseType((int)HttpStatusCode.Created)]
 | 
				
			||||||
 | 
					        [ProducesResponseType((int)HttpStatusCode.BadRequest)]
 | 
				
			||||||
 | 
					        [ProducesResponseType(418)]
 | 
				
			||||||
 | 
					        public async Task<IActionResult> SubscribeWebhook(WebhookSubscriptionRequest request)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!ModelState.IsValid)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return ValidationProblem(ModelState);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var userId = _identityService.GetUserIdentity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var grantOk = await _grantUrlTester.TestGrantUrl(request.Url, request.GrantUrl, request.Token ?? string.Empty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (grantOk)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var subscription = new WebhookSubscription()
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Date = DateTime.UtcNow,
 | 
				
			||||||
 | 
					                    DestUrl = request.Url,
 | 
				
			||||||
 | 
					                    Token = request.Token,
 | 
				
			||||||
 | 
					                    Type = Enum.Parse<WebhookType>(request.Event, ignoreCase: true),
 | 
				
			||||||
 | 
					                    UserId = _identityService.GetUserIdentity()
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                _dbContext.Add(subscription);
 | 
				
			||||||
 | 
					                await _dbContext.SaveChangesAsync();
 | 
				
			||||||
 | 
					                return CreatedAtAction("GetByUserAndId", new { id = subscription.Id }, subscription);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return StatusCode(418, "Grant url can't be validated");
 | 
				
			||||||
 | 
					            }   
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Authorize]
 | 
				
			||||||
 | 
					        [HttpDelete("{id:int}")]
 | 
				
			||||||
 | 
					        [ProducesResponseType((int)HttpStatusCode.Accepted)]
 | 
				
			||||||
 | 
					        [ProducesResponseType((int)HttpStatusCode.NotFound)]
 | 
				
			||||||
 | 
					        public async Task<IActionResult> UnsubscribeWebhook(int id)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var userId = _identityService.GetUserIdentity();
 | 
				
			||||||
 | 
					            var subscription = await _dbContext.Subscriptions.SingleOrDefaultAsync(s => s.Id == id && s.UserId == userId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (subscription != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _dbContext.Remove(subscription);
 | 
				
			||||||
 | 
					                await _dbContext.SaveChangesAsync();
 | 
				
			||||||
 | 
					                return Accepted();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return NotFound($"Subscriptions {id} not found");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/Services/Webhooks/Webhooks.API/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/Services/Webhooks/Webhooks.API/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
 | 
				
			||||||
 | 
					WORKDIR /app
 | 
				
			||||||
 | 
					EXPOSE 80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM microsoft/dotnet:2.2-sdk AS build
 | 
				
			||||||
 | 
					WORKDIR /src
 | 
				
			||||||
 | 
					COPY ["src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj", "src/Services/Webhooks/Webhooks.API/"]
 | 
				
			||||||
 | 
					RUN dotnet restore "src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj"
 | 
				
			||||||
 | 
					COPY . .
 | 
				
			||||||
 | 
					WORKDIR "/src/src/Services/Webhooks/Webhooks.API"
 | 
				
			||||||
 | 
					RUN dotnet build "Webhooks.API.csproj" -c Release -o /app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM build AS publish
 | 
				
			||||||
 | 
					RUN dotnet publish "Webhooks.API.csproj" -c Release -o /app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM base AS final
 | 
				
			||||||
 | 
					WORKDIR /app
 | 
				
			||||||
 | 
					COPY --from=publish /app .
 | 
				
			||||||
 | 
					ENTRYPOINT ["dotnet", "Webhooks.API.dll"]
 | 
				
			||||||
@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Exceptions
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhooksDomainException : Exception
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Infrastructure.ActionResult
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    class InternalServerErrorObjectResult : ObjectResult
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public InternalServerErrorObjectResult(object error) : base(error)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            StatusCode = StatusCodes.Status500InternalServerError;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
 | 
					using Swashbuckle.AspNetCore.Swagger;
 | 
				
			||||||
 | 
					using Swashbuckle.AspNetCore.SwaggerGen;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Infrastructure
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class AuthorizeCheckOperationFilter : IOperationFilter
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public void Apply(Operation operation, OperationFilterContext context)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Check for authorize attribute
 | 
				
			||||||
 | 
					            var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType<AuthorizeAttribute>().Any() ||
 | 
				
			||||||
 | 
					                               context.ApiDescription.ActionAttributes().OfType<AuthorizeAttribute>().Any();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (hasAuthorize)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                operation.Responses.Add("401", new Response { Description = "Unauthorized" });
 | 
				
			||||||
 | 
					                operation.Responses.Add("403", new Response { Description = "Forbidden" });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                operation.Security = new List<IDictionary<string, IEnumerable<string>>>();
 | 
				
			||||||
 | 
					                operation.Security.Add(new Dictionary<string, IEnumerable<string>>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    { "oauth2", new [] { "webhooksapi" } }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc.Filters;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Net;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Webhooks.API.Exceptions;
 | 
				
			||||||
 | 
					using Webhooks.API.Infrastructure.ActionResult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Infrastructure
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class HttpGlobalExceptionFilter : IExceptionFilter
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IHostingEnvironment env;
 | 
				
			||||||
 | 
					        private readonly ILogger<HttpGlobalExceptionFilter> logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public HttpGlobalExceptionFilter(IHostingEnvironment env, ILogger<HttpGlobalExceptionFilter> logger)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.env = env;
 | 
				
			||||||
 | 
					            this.logger = logger;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void OnException(ExceptionContext context)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            logger.LogError(new EventId(context.Exception.HResult),
 | 
				
			||||||
 | 
					                context.Exception,
 | 
				
			||||||
 | 
					                context.Exception.Message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (context.Exception.GetType() == typeof(WebhooksDomainException))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var problemDetails = new ValidationProblemDetails()
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Instance = context.HttpContext.Request.Path,
 | 
				
			||||||
 | 
					                    Status = StatusCodes.Status400BadRequest,
 | 
				
			||||||
 | 
					                    Detail = "Please refer to the errors property for additional details."
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                context.Result = new BadRequestObjectResult(problemDetails);
 | 
				
			||||||
 | 
					                context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var json = new JsonErrorResponse
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Messages = new[] { "An error ocurred." }
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (env.IsDevelopment())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    json.DeveloperMeesage = context.Exception;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                context.Result = new InternalServerErrorObjectResult(json);
 | 
				
			||||||
 | 
					                context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            context.ExceptionHandled = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private class JsonErrorResponse
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public string[] Messages { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public object DeveloperMeesage { get; set; }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					using Microsoft.EntityFrameworkCore;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Design;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Webhooks.API.Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Infrastructure
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhooksContext : DbContext
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public WebhooksContext(DbContextOptions<WebhooksContext> options) : base(options)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        public DbSet<WebhookSubscription> Subscriptions { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class WebhooksContextDesignFactory : IDesignTimeDbContextFactory<WebhooksContext>
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public WebhooksContext CreateDbContext(string[] args)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var optionsBuilder = new DbContextOptionsBuilder<WebhooksContext>()
 | 
				
			||||||
 | 
					                .UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;Integrated Security=true");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return new WebhooksContext(optionsBuilder.Options);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.IntegrationEvents
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public int OrderId { get; }
 | 
				
			||||||
 | 
					        public IEnumerable<OrderStockItem> OrderStockItems { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public OrderStatusChangedToPaidIntegrationEvent(int orderId,
 | 
				
			||||||
 | 
					            IEnumerable<OrderStockItem> orderStockItems)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            OrderId = orderId;
 | 
				
			||||||
 | 
					            OrderStockItems = orderStockItems;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class OrderStockItem
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public int ProductId { get; }
 | 
				
			||||||
 | 
					        public int Units { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public OrderStockItem(int productId, int units)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ProductId = productId;
 | 
				
			||||||
 | 
					            Units = units;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Webhooks.API.Model;
 | 
				
			||||||
 | 
					using Webhooks.API.Services;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.IntegrationEvents
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class OrderStatusChangedToPaidIntegrationEventHandler : IIntegrationEventHandler<OrderStatusChangedToPaidIntegrationEvent>
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IWebhooksRetriever _retriever;
 | 
				
			||||||
 | 
					        private readonly IWebhooksSender _sender;
 | 
				
			||||||
 | 
					        private readonly ILogger _logger;
 | 
				
			||||||
 | 
					        public OrderStatusChangedToPaidIntegrationEventHandler(IWebhooksRetriever retriever, IWebhooksSender sender, ILogger<OrderStatusChangedToShippedIntegrationEventHandler> logger )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _retriever = retriever;
 | 
				
			||||||
 | 
					            _sender = sender;
 | 
				
			||||||
 | 
					            _logger = logger;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task Handle(OrderStatusChangedToPaidIntegrationEvent @event)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var subscriptions = await _retriever.GetSubscriptionsOfType(WebhookType.OrderPaid);
 | 
				
			||||||
 | 
					            _logger.LogInformation($"Received OrderStatusChangedToShippedIntegrationEvent and got {subscriptions.Count()} subscriptions to process");
 | 
				
			||||||
 | 
					            var whook = new WebhookData(WebhookType.OrderPaid, @event);
 | 
				
			||||||
 | 
					            await _sender.SendAll(subscriptions, whook);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.IntegrationEvents
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public int OrderId { get; private set; }
 | 
				
			||||||
 | 
					        public string OrderStatus { get; private set; }
 | 
				
			||||||
 | 
					        public string BuyerName { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public OrderStatusChangedToShippedIntegrationEvent(int orderId, string orderStatus, string buyerName)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            OrderId = orderId;
 | 
				
			||||||
 | 
					            OrderStatus = orderStatus;
 | 
				
			||||||
 | 
					            BuyerName = buyerName;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Webhooks.API.Model;
 | 
				
			||||||
 | 
					using Webhooks.API.Services;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.IntegrationEvents
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class OrderStatusChangedToShippedIntegrationEventHandler : IIntegrationEventHandler<OrderStatusChangedToShippedIntegrationEvent>
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IWebhooksRetriever _retriever;
 | 
				
			||||||
 | 
					        private readonly IWebhooksSender _sender;
 | 
				
			||||||
 | 
					        private readonly ILogger _logger;
 | 
				
			||||||
 | 
					        public OrderStatusChangedToShippedIntegrationEventHandler(IWebhooksRetriever retriever, IWebhooksSender sender, ILogger<OrderStatusChangedToShippedIntegrationEventHandler> logger )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _retriever = retriever;
 | 
				
			||||||
 | 
					            _sender = sender;
 | 
				
			||||||
 | 
					            _logger = logger;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task Handle(OrderStatusChangedToShippedIntegrationEvent @event)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var subscriptions = await _retriever.GetSubscriptionsOfType(WebhookType.OrderShipped);
 | 
				
			||||||
 | 
					            _logger.LogInformation($"Received OrderStatusChangedToShippedIntegrationEvent and got {subscriptions.Count()} subscriptions to process");
 | 
				
			||||||
 | 
					            var whook = new WebhookData(WebhookType.OrderShipped, @event);
 | 
				
			||||||
 | 
					            await _sender.SendAll(subscriptions, whook);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.IntegrationEvents
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class ProductPriceChangedIntegrationEvent : IntegrationEvent
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public int ProductId { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public decimal NewPrice { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public decimal OldPrice { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ProductId = productId;
 | 
				
			||||||
 | 
					            NewPrice = newPrice;
 | 
				
			||||||
 | 
					            OldPrice = oldPrice;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.IntegrationEvents
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler<ProductPriceChangedIntegrationEvent>
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public async Task Handle(ProductPriceChangedIntegrationEvent @event)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int i = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								src/Services/Webhooks/Webhooks.API/Migrations/20190118091148_Initial.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/Services/Webhooks/Webhooks.API/Migrations/20190118091148_Initial.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					// <auto-generated />
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Infrastructure;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Metadata;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Migrations;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
 | 
				
			||||||
 | 
					using Webhooks.API.Infrastructure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Migrations
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [DbContext(typeof(WebhooksContext))]
 | 
				
			||||||
 | 
					    [Migration("20190118091148_Initial")]
 | 
				
			||||||
 | 
					    partial class Initial
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        protected override void BuildTargetModel(ModelBuilder modelBuilder)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					#pragma warning disable 612, 618
 | 
				
			||||||
 | 
					            modelBuilder
 | 
				
			||||||
 | 
					                .HasAnnotation("ProductVersion", "2.2.1-servicing-10028")
 | 
				
			||||||
 | 
					                .HasAnnotation("Relational:MaxIdentifierLength", 128)
 | 
				
			||||||
 | 
					                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            modelBuilder.Entity("Webhooks.API.Model.WebhookSubscription", b =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    b.Property<int>("Id")
 | 
				
			||||||
 | 
					                        .ValueGeneratedOnAdd()
 | 
				
			||||||
 | 
					                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.Property<DateTime>("Date");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.Property<string>("DestUrl");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.Property<string>("Token");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.Property<int>("Type");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.Property<string>("UserId");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.HasKey("Id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.ToTable("Subscriptions");
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					#pragma warning restore 612, 618
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Metadata;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Migrations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Migrations
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public partial class Initial : Migration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        protected override void Up(MigrationBuilder migrationBuilder)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            migrationBuilder.CreateTable(
 | 
				
			||||||
 | 
					                name: "Subscriptions",
 | 
				
			||||||
 | 
					                columns: table => new
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Id = table.Column<int>(nullable: false)
 | 
				
			||||||
 | 
					                        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
 | 
				
			||||||
 | 
					                    Type = table.Column<int>(nullable: false),
 | 
				
			||||||
 | 
					                    Date = table.Column<DateTime>(nullable: false),
 | 
				
			||||||
 | 
					                    DestUrl = table.Column<string>(nullable: true),
 | 
				
			||||||
 | 
					                    Token = table.Column<string>(nullable: true),
 | 
				
			||||||
 | 
					                    UserId = table.Column<string>(nullable: true)
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                constraints: table =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    table.PrimaryKey("PK_Subscriptions", x => x.Id);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override void Down(MigrationBuilder migrationBuilder)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            migrationBuilder.DropTable(
 | 
				
			||||||
 | 
					                name: "Subscriptions");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					// <auto-generated />
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Infrastructure;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Metadata;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
 | 
				
			||||||
 | 
					using Webhooks.API.Infrastructure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Migrations
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [DbContext(typeof(WebhooksContext))]
 | 
				
			||||||
 | 
					    partial class WebhooksContextModelSnapshot : ModelSnapshot
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        protected override void BuildModel(ModelBuilder modelBuilder)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					#pragma warning disable 612, 618
 | 
				
			||||||
 | 
					            modelBuilder
 | 
				
			||||||
 | 
					                .HasAnnotation("ProductVersion", "2.2.1-servicing-10028")
 | 
				
			||||||
 | 
					                .HasAnnotation("Relational:MaxIdentifierLength", 128)
 | 
				
			||||||
 | 
					                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            modelBuilder.Entity("Webhooks.API.Model.WebhookSubscription", b =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    b.Property<int>("Id")
 | 
				
			||||||
 | 
					                        .ValueGeneratedOnAdd()
 | 
				
			||||||
 | 
					                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.Property<DateTime>("Date");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.Property<string>("DestUrl");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.Property<string>("Token");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.Property<int>("Type");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.Property<string>("UserId");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.HasKey("Id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    b.ToTable("Subscriptions");
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					#pragma warning restore 612, 618
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								src/Services/Webhooks/Webhooks.API/Model/WebhookData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Services/Webhooks/Webhooks.API/Model/WebhookData.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Model
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhookData
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public DateTime When { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public string Payload { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public string Type { get;  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public WebhookData(WebhookType hookType, object data)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            When = DateTime.UtcNow;
 | 
				
			||||||
 | 
					            Type = hookType.ToString();
 | 
				
			||||||
 | 
					            Payload = JsonConvert.SerializeObject(data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Model
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhookSubscription
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public int Id { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public WebhookType Type { get; set; }
 | 
				
			||||||
 | 
					        public DateTime Date { get; set; }
 | 
				
			||||||
 | 
					        public string DestUrl { get; set; }
 | 
				
			||||||
 | 
					        public string Token { get; set; }
 | 
				
			||||||
 | 
					        public string UserId { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								src/Services/Webhooks/Webhooks.API/Model/WebhookType.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/Services/Webhooks/Webhooks.API/Model/WebhookType.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Model
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public enum WebhookType
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        CatalogItemPriceChange = 1,
 | 
				
			||||||
 | 
					        OrderShipped = 2,
 | 
				
			||||||
 | 
					        OrderPaid = 3
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/Services/Webhooks/Webhooks.API/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/Services/Webhooks/Webhooks.API/Program.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					using Webhooks.API.Infrastructure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class Program
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static void Main(string[] args)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            CreateWebHostBuilder(args).Build()
 | 
				
			||||||
 | 
					                .MigrateDbContext<WebhooksContext>((_,__) => { })
 | 
				
			||||||
 | 
					                .Run();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
 | 
				
			||||||
 | 
					            WebHost.CreateDefaultBuilder(args)
 | 
				
			||||||
 | 
					                .UseStartup<Startup>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "iisSettings": {
 | 
				
			||||||
 | 
					    "windowsAuthentication": false,
 | 
				
			||||||
 | 
					    "anonymousAuthentication": true,
 | 
				
			||||||
 | 
					    "iisExpress": {
 | 
				
			||||||
 | 
					      "applicationUrl": "http://localhost:62486",
 | 
				
			||||||
 | 
					      "sslPort": 0
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "profiles": {
 | 
				
			||||||
 | 
					    "IIS Express": {
 | 
				
			||||||
 | 
					      "commandName": "IISExpress",
 | 
				
			||||||
 | 
					      "launchBrowser": true,
 | 
				
			||||||
 | 
					      "environmentVariables": {
 | 
				
			||||||
 | 
					        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "Webhooks.API": {
 | 
				
			||||||
 | 
					      "commandName": "Project",
 | 
				
			||||||
 | 
					      "launchBrowser": true,
 | 
				
			||||||
 | 
					      "environmentVariables": {
 | 
				
			||||||
 | 
					        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "applicationUrl": "http://localhost:5000"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "Docker": {
 | 
				
			||||||
 | 
					      "commandName": "Docker",
 | 
				
			||||||
 | 
					      "launchBrowser": true,
 | 
				
			||||||
 | 
					      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    class GrantUrlTesterService : IGrantUrlTesterService
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IHttpClientFactory _clientFactory;
 | 
				
			||||||
 | 
					        private readonly ILogger _logger;
 | 
				
			||||||
 | 
					        public GrantUrlTesterService(IHttpClientFactory factory, ILogger<IGrantUrlTesterService> logger)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _clientFactory = factory;
 | 
				
			||||||
 | 
					            _logger = logger;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task<bool> TestGrantUrl(string urlHook, string url, string token)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!CheckSameOrigin(urlHook, url))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _logger.LogWarning($"Url of the hook ({urlHook} and the grant url ({url} do not belong to same origin)");
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var client = _clientFactory.CreateClient("GrantClient");
 | 
				
			||||||
 | 
					            var msg = new HttpRequestMessage(HttpMethod.Options, url);
 | 
				
			||||||
 | 
					            msg.Headers.Add("X-eshop-whtoken", token);
 | 
				
			||||||
 | 
					            _logger.LogInformation($"Sending the OPTIONS message to {url} with token {token ?? string.Empty}");
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var response = await client.SendAsync(msg);
 | 
				
			||||||
 | 
					                var tokenReceived = response.Headers.TryGetValues("X-eshop-whtoken", out var tokenValues) ? tokenValues.FirstOrDefault() : null;
 | 
				
			||||||
 | 
					                var tokenExpected = string.IsNullOrWhiteSpace(token) ? null : token;
 | 
				
			||||||
 | 
					                _logger.LogInformation($"Response code is {response.StatusCode} for url {url} and token in header was {tokenReceived} (expected token was {tokenExpected})");
 | 
				
			||||||
 | 
					                return response.IsSuccessStatusCode && tokenReceived == tokenExpected;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (Exception ex)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _logger.LogWarning($"Exception {ex.GetType().Name} when sending OPTIONS request. Url can't be granted.");
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private bool CheckSameOrigin(string urlHook, string url)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var firstUrl = new Uri(urlHook, UriKind.Absolute);
 | 
				
			||||||
 | 
					            var secondUrl = new Uri(url, UriKind.Absolute);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return firstUrl.Scheme == secondUrl.Scheme &&
 | 
				
			||||||
 | 
					                firstUrl.Port == secondUrl.Port &&
 | 
				
			||||||
 | 
					                firstUrl.Host == firstUrl.Host;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public interface IGrantUrlTesterService
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Task<bool> TestGrantUrl(string urlHook, string url, string token);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					namespace Webhooks.API.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public interface IIdentityService
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        string GetUserIdentity();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Webhooks.API.Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public interface IWebhooksRetriever
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Task<IEnumerable<WebhookSubscription>> GetSubscriptionsOfType(WebhookType type);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Webhooks.API.Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public interface IWebhooksSender
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Task SendAll(IEnumerable<WebhookSubscription> receivers, WebhookData data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class IdentityService : IIdentityService
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private IHttpContextAccessor _context; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IdentityService(IHttpContextAccessor context)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _context = context ?? throw new ArgumentNullException(nameof(context));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public string GetUserIdentity()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return _context.HttpContext.User.FindFirst("sub").Value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					using Microsoft.EntityFrameworkCore;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Webhooks.API.Infrastructure;
 | 
				
			||||||
 | 
					using Webhooks.API.Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhooksRetriever : IWebhooksRetriever
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly WebhooksContext _db;
 | 
				
			||||||
 | 
					        public WebhooksRetriever(WebhooksContext db)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _db = db;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        public async Task<IEnumerable<WebhookSubscription>> GetSubscriptionsOfType(WebhookType type)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var data = await _db.Subscriptions.Where(s => s.Type == type).ToListAsync();
 | 
				
			||||||
 | 
					            return data;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Webhooks.API.Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhooksSender : IWebhooksSender
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IHttpClientFactory _httpClientFactory;
 | 
				
			||||||
 | 
					        private readonly ILogger _logger;
 | 
				
			||||||
 | 
					        public WebhooksSender(IHttpClientFactory httpClientFactory, ILogger<WebhooksSender> logger)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _httpClientFactory = httpClientFactory;
 | 
				
			||||||
 | 
					            _logger = logger;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task SendAll(IEnumerable<WebhookSubscription> receivers, WebhookData data)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var client = _httpClientFactory.CreateClient();
 | 
				
			||||||
 | 
					            var json = JsonConvert.SerializeObject(data);
 | 
				
			||||||
 | 
					            var tasks = receivers.Select(r => OnSendData(r, json, client));
 | 
				
			||||||
 | 
					            await Task.WhenAll(tasks.ToArray());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private Task OnSendData(WebhookSubscription subs, string jsonData, HttpClient client)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var request = new HttpRequestMessage()
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                RequestUri = new Uri(subs.DestUrl, UriKind.Absolute),
 | 
				
			||||||
 | 
					                Method = HttpMethod.Post,
 | 
				
			||||||
 | 
					                Content = new StringContent(jsonData, Encoding.UTF8, "application/json")
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!string.IsNullOrWhiteSpace(subs.Token))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                request.Headers.Add("X-eshop-whtoken", subs.Token);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _logger.LogDebug($"Sending hook to {subs.DestUrl} of type {subs.Type.ToString()}");
 | 
				
			||||||
 | 
					            return client.SendAsync(request);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										372
									
								
								src/Services/Webhooks/Webhooks.API/Startup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										372
									
								
								src/Services/Webhooks/Webhooks.API/Startup.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,372 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Data.Common;
 | 
				
			||||||
 | 
					using System.IdentityModel.Tokens.Jwt;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Autofac;
 | 
				
			||||||
 | 
					using Autofac.Extensions.DependencyInjection;
 | 
				
			||||||
 | 
					using HealthChecks.UI.Client;
 | 
				
			||||||
 | 
					using Microsoft.ApplicationInsights.Extensibility;
 | 
				
			||||||
 | 
					using Microsoft.ApplicationInsights.ServiceFabric;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Authentication.JwtBearer;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Builder;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Diagnostics.HealthChecks;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.Azure.ServiceBus;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore;
 | 
				
			||||||
 | 
					using Microsoft.EntityFrameworkCore.Diagnostics;
 | 
				
			||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
 | 
				
			||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
 | 
				
			||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
 | 
				
			||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus;
 | 
				
			||||||
 | 
					using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.DependencyInjection;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Diagnostics.HealthChecks;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					using RabbitMQ.Client;
 | 
				
			||||||
 | 
					using Swashbuckle.AspNetCore.Swagger;
 | 
				
			||||||
 | 
					using Webhooks.API.Infrastructure;
 | 
				
			||||||
 | 
					using Webhooks.API.IntegrationEvents;
 | 
				
			||||||
 | 
					using Webhooks.API.Services;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Webhooks.API
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class Startup
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public IConfiguration Configuration { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Startup(IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Configuration = configuration;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IServiceProvider ConfigureServices(IServiceCollection services)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services
 | 
				
			||||||
 | 
					                .AddAppInsight(Configuration)
 | 
				
			||||||
 | 
					                .AddCustomMVC(Configuration)
 | 
				
			||||||
 | 
					                .AddCustomDbContext(Configuration)
 | 
				
			||||||
 | 
					                .AddSwagger(Configuration)
 | 
				
			||||||
 | 
					                .AddCustomHealthCheck(Configuration)
 | 
				
			||||||
 | 
					                .AddHttpClientServices(Configuration)
 | 
				
			||||||
 | 
					                .AddIntegrationServices(Configuration)
 | 
				
			||||||
 | 
					                .AddEventBus(Configuration)
 | 
				
			||||||
 | 
					                .AddCustomAuthentication(Configuration)
 | 
				
			||||||
 | 
					                .AddSingleton<IHttpContextAccessor, HttpContextAccessor>()
 | 
				
			||||||
 | 
					                .AddTransient<IIdentityService, IdentityService>()
 | 
				
			||||||
 | 
					                .AddTransient<IGrantUrlTesterService, GrantUrlTesterService>()
 | 
				
			||||||
 | 
					                .AddTransient<IWebhooksRetriever, WebhooksRetriever>()
 | 
				
			||||||
 | 
					                .AddTransient<IWebhooksSender, WebhooksSender>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var container = new ContainerBuilder();
 | 
				
			||||||
 | 
					            container.Populate(services);
 | 
				
			||||||
 | 
					            return new AutofacServiceProvider(container.Build());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            loggerFactory.AddAzureWebAppDiagnostics();
 | 
				
			||||||
 | 
					            loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var pathBase = Configuration["PATH_BASE"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!string.IsNullOrEmpty(pathBase))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
 | 
				
			||||||
 | 
					                app.UsePathBase(pathBase);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            app.UseHealthChecks("/hc", new HealthCheckOptions()
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Predicate = _ => true,
 | 
				
			||||||
 | 
					                ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            app.UseHealthChecks("/liveness", new HealthCheckOptions
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Predicate = r => r.Name.Contains("self")
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            app.UseCors("CorsPolicy");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ConfigureAuth(app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            app.UseMvcWithDefaultRoute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            app.UseSwagger()
 | 
				
			||||||
 | 
					              .UseSwaggerUI(c =>
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                  c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Webhooks.API V1");
 | 
				
			||||||
 | 
					                  c.OAuthClientId("webhooksswaggerui");
 | 
				
			||||||
 | 
					                  c.OAuthAppName("WebHooks Service Swagger UI");
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ConfigureEventBus(app);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected virtual void ConfigureAuth(IApplicationBuilder app)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					            if (Configuration.GetValue<bool>("UseLoadTest"))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                app.UseMiddleware<ByPassAuthMiddleware>();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            app.UseAuthentication();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected virtual void ConfigureEventBus(IApplicationBuilder app)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
 | 
				
			||||||
 | 
					            eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();
 | 
				
			||||||
 | 
					            eventBus.Subscribe<OrderStatusChangedToShippedIntegrationEvent, OrderStatusChangedToShippedIntegrationEventHandler>();
 | 
				
			||||||
 | 
					            eventBus.Subscribe<OrderStatusChangedToPaidIntegrationEvent, OrderStatusChangedToPaidIntegrationEventHandler>();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static class CustomExtensionMethods
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services.AddApplicationInsightsTelemetry(configuration);
 | 
				
			||||||
 | 
					            var orchestratorType = configuration.GetValue<string>("OrchestratorType");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (orchestratorType?.ToUpper() == "K8S")
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // Enable K8s telemetry initializer
 | 
				
			||||||
 | 
					                services.EnableKubernetes();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (orchestratorType?.ToUpper() == "SF")
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // Enable SF telemetry initializer
 | 
				
			||||||
 | 
					                services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
 | 
				
			||||||
 | 
					                    new FabricTelemetryInitializer());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services.AddMvc(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.Filters.Add(typeof(HttpGlobalExceptionFilter));
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
 | 
				
			||||||
 | 
					                .AddControllersAsServices();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            services.AddCors(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.AddPolicy("CorsPolicy",
 | 
				
			||||||
 | 
					                    builder => builder
 | 
				
			||||||
 | 
					                    .SetIsOriginAllowed((host) => true)
 | 
				
			||||||
 | 
					                    .AllowAnyMethod()
 | 
				
			||||||
 | 
					                    .AllowAnyHeader()
 | 
				
			||||||
 | 
					                    .AllowCredentials());
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services.AddDbContext<WebhooksContext>(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.UseSqlServer(configuration["ConnectionString"],
 | 
				
			||||||
 | 
					                                     sqlServerOptionsAction: sqlOptions =>
 | 
				
			||||||
 | 
					                                     {
 | 
				
			||||||
 | 
					                                         sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
 | 
				
			||||||
 | 
					                                         //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency 
 | 
				
			||||||
 | 
					                                         sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
 | 
				
			||||||
 | 
					                                     });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Changing default behavior when client evaluation occurs to throw. 
 | 
				
			||||||
 | 
					                // Default in EF Core would be to log a warning when client evaluation is performed.
 | 
				
			||||||
 | 
					                options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
 | 
				
			||||||
 | 
					                //Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IServiceCollection AddSwagger(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services.AddSwaggerGen(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.DescribeAllEnumsAsStrings();
 | 
				
			||||||
 | 
					                options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Title = "eShopOnContainers - Webhooks HTTP API",
 | 
				
			||||||
 | 
					                    Version = "v1",
 | 
				
			||||||
 | 
					                    Description = "The Webhooks Microservice HTTP API. This is a simple webhooks CRUD registration entrypoint",
 | 
				
			||||||
 | 
					                    TermsOfService = "Terms Of Service"
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                options.AddSecurityDefinition("oauth2", new OAuth2Scheme
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Type = "oauth2",
 | 
				
			||||||
 | 
					                    Flow = "implicit",
 | 
				
			||||||
 | 
					                    AuthorizationUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize",
 | 
				
			||||||
 | 
					                    TokenUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token",
 | 
				
			||||||
 | 
					                    Scopes = new Dictionary<string, string>()
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        { "webhooks", "Webhooks API" }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                options.OperationFilter<AuthorizeCheckOperationFilter>();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var subscriptionClientName = configuration["SubscriptionClientName"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                services.AddSingleton<IEventBus, EventBusServiceBus>(sp =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();
 | 
				
			||||||
 | 
					                    var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
 | 
				
			||||||
 | 
					                    var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>();
 | 
				
			||||||
 | 
					                    var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return new EventBusServiceBus(serviceBusPersisterConnection, logger,
 | 
				
			||||||
 | 
					                        eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
 | 
				
			||||||
 | 
					                    var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
 | 
				
			||||||
 | 
					                    var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
 | 
				
			||||||
 | 
					                    var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    var retryCount = 5;
 | 
				
			||||||
 | 
					                    if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        retryCount = int.Parse(configuration["EventBusRetryCount"]);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
 | 
				
			||||||
 | 
					            services.AddTransient<ProductPriceChangedIntegrationEventHandler>();
 | 
				
			||||||
 | 
					            services.AddTransient<OrderStatusChangedToShippedIntegrationEventHandler>();
 | 
				
			||||||
 | 
					            services.AddTransient<OrderStatusChangedToPaidIntegrationEventHandler>();
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var accountName = configuration.GetValue<string>("AzureStorageAccountName");
 | 
				
			||||||
 | 
					            var accountKey = configuration.GetValue<string>("AzureStorageAccountKey");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var hcBuilder = services.AddHealthChecks();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            hcBuilder
 | 
				
			||||||
 | 
					                .AddCheck("self", () => HealthCheckResult.Healthy())
 | 
				
			||||||
 | 
					                .AddSqlServer(
 | 
				
			||||||
 | 
					                    configuration["ConnectionString"],
 | 
				
			||||||
 | 
					                    name: "WebhooksApiDb-check",
 | 
				
			||||||
 | 
					                    tags: new string[] { "webhooksdb" });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
 | 
				
			||||||
 | 
					            services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan);
 | 
				
			||||||
 | 
					            //add http client services
 | 
				
			||||||
 | 
					            services.AddHttpClient("GrantClient")
 | 
				
			||||||
 | 
					                   .SetHandlerLifetime(TimeSpan.FromMinutes(5));
 | 
				
			||||||
 | 
					                   //.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>(
 | 
				
			||||||
 | 
					                sp => (DbConnection c) => new IntegrationEventLogService(c));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                services.AddSingleton<IServiceBusPersisterConnection>(sp =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    var logger = sp.GetRequiredService<ILogger<DefaultServiceBusPersisterConnection>>();
 | 
				
			||||||
 | 
					                    var serviceBusConnection = new ServiceBusConnectionStringBuilder(configuration["EventBusConnection"]);
 | 
				
			||||||
 | 
					                    return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    var factory = new ConnectionFactory()
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        HostName = configuration["EventBusConnection"]
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (!string.IsNullOrEmpty(configuration["EventBusUserName"]))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        factory.UserName = configuration["EventBusUserName"];
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (!string.IsNullOrEmpty(configuration["EventBusPassword"]))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        factory.Password = configuration["EventBusPassword"];
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    var retryCount = 5;
 | 
				
			||||||
 | 
					                    if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        retryCount = int.Parse(configuration["EventBusRetryCount"]);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // prevent from mapping "sub" claim to nameidentifier.
 | 
				
			||||||
 | 
					            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var identityUrl = configuration.GetValue<string>("IdentityUrl");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            services.AddAuthentication(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
 | 
				
			||||||
 | 
					                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }).AddJwtBearer(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.Authority = identityUrl;
 | 
				
			||||||
 | 
					                options.RequireHttpsMetadata = false;
 | 
				
			||||||
 | 
					                options.Audience = "webhooks";
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					<Project Sdk="Microsoft.NET.Sdk.Web">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <PropertyGroup>
 | 
				
			||||||
 | 
					    <TargetFramework>netcoreapp2.2</TargetFramework>
 | 
				
			||||||
 | 
					    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
 | 
				
			||||||
 | 
					    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.AspNetCore.App" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.0.2105168" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.2.0" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
 | 
				
			||||||
 | 
					    <PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.0" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
 | 
				
			||||||
 | 
					    <PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="2.2.0" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||
@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "Logging": {
 | 
				
			||||||
 | 
					    "LogLevel": {
 | 
				
			||||||
 | 
					      "Default": "Debug",
 | 
				
			||||||
 | 
					      "System": "Information",
 | 
				
			||||||
 | 
					      "Microsoft": "Information"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/Services/Webhooks/Webhooks.API/appsettings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/Services/Webhooks/Webhooks.API/appsettings.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "Logging": {
 | 
				
			||||||
 | 
					    "LogLevel": {
 | 
				
			||||||
 | 
					      "Default": "Warning"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "AllowedHosts": "*",
 | 
				
			||||||
 | 
					  "SubscriptionClientName": "Webhooks",
 | 
				
			||||||
 | 
					  "EventBusRetryCount": 5
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								src/Web/WebhookClient/.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/Web/WebhookClient/.dockerignore
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					!wwwroot
 | 
				
			||||||
							
								
								
									
										1
									
								
								src/Web/WebhookClient/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/Web/WebhookClient/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					!wwwroot/lib
 | 
				
			||||||
							
								
								
									
										40
									
								
								src/Web/WebhookClient/Controllers/AccountController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/Web/WebhookClient/Controllers/AccountController.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Authentication;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Authentication.Cookies;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Authentication.OpenIdConnect;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Security.Claims;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Controllers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [Authorize]
 | 
				
			||||||
 | 
					    public class AccountController : Controller
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public async Task<IActionResult> SignIn(string returnUrl)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var user = User as ClaimsPrincipal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var token = await HttpContext.GetTokenAsync("access_token");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (token != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ViewData["access_token"] = token;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return RedirectToPage("/Index");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task<IActionResult> Signout()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
 | 
				
			||||||
 | 
					            await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
 | 
				
			||||||
 | 
					            var homeUrl = Url.Page("/Index");
 | 
				
			||||||
 | 
					            return new SignOutResult(OpenIdConnectDefaults.AuthenticationScheme,
 | 
				
			||||||
 | 
					                new AuthenticationProperties { RedirectUri = homeUrl });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Options;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using WebhookClient.Models;
 | 
				
			||||||
 | 
					using WebhookClient.Services;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Controllers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [ApiController]
 | 
				
			||||||
 | 
					    [Route("webhook-received")]
 | 
				
			||||||
 | 
					    public class WebhooksReceivedController : Controller
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private readonly Settings _settings;
 | 
				
			||||||
 | 
					        private readonly ILogger _logger;
 | 
				
			||||||
 | 
					        private readonly IHooksRepository _hooksRepository;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        public WebhooksReceivedController(IOptions<Settings> settings, ILogger<WebhooksReceivedController> logger, IHooksRepository hooksRepository)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _settings = settings.Value;
 | 
				
			||||||
 | 
					            _logger = logger;
 | 
				
			||||||
 | 
					            _hooksRepository = hooksRepository;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [HttpPost]
 | 
				
			||||||
 | 
					        public async Task<IActionResult> NewWebhook(WebhookData hook)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var header = Request.Headers[HeaderNames.WebHookCheckHeader];
 | 
				
			||||||
 | 
					            var token = header.FirstOrDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _logger.LogInformation($"Received hook with token {token}. My token is {_settings.Token}. Token validation is set to {_settings.ValidateToken}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!_settings.ValidateToken || _settings.Token == token)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _logger.LogInformation($"Received hook is going to be processed");
 | 
				
			||||||
 | 
					                var newHook = new WebHookReceived()
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Data = hook.Payload,
 | 
				
			||||||
 | 
					                    When = hook.When,
 | 
				
			||||||
 | 
					                    Token = token
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                await _hooksRepository.AddNew(newHook);
 | 
				
			||||||
 | 
					                _logger.LogInformation($"Received hook was processed.");
 | 
				
			||||||
 | 
					                return Ok(newHook);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _logger.LogInformation($"Received hook is NOT processed - Bad Request returned.");
 | 
				
			||||||
 | 
					            return BadRequest();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/Web/WebhookClient/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/Web/WebhookClient/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
 | 
				
			||||||
 | 
					WORKDIR /app
 | 
				
			||||||
 | 
					EXPOSE 80
 | 
				
			||||||
 | 
					EXPOSE 443
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM microsoft/dotnet:2.2-sdk AS build
 | 
				
			||||||
 | 
					WORKDIR /src
 | 
				
			||||||
 | 
					COPY ["src/Web/WebhookClient/WebhookClient.csproj", "src/Web/WebhookClient/"]
 | 
				
			||||||
 | 
					RUN dotnet restore "src/Web/WebhookClient/WebhookClient.csproj"
 | 
				
			||||||
 | 
					COPY . .
 | 
				
			||||||
 | 
					WORKDIR "/src/src/Web/WebhookClient"
 | 
				
			||||||
 | 
					RUN dotnet build "WebhookClient.csproj" -c Release -o /app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM build AS publish
 | 
				
			||||||
 | 
					RUN dotnet publish "WebhookClient.csproj" -c Release -o /app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM base AS final
 | 
				
			||||||
 | 
					WORKDIR /app
 | 
				
			||||||
 | 
					COPY --from=publish /app .
 | 
				
			||||||
 | 
					ENTRYPOINT ["dotnet", "WebhookClient.dll"]
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/Web/WebhookClient/HeaderNames.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Web/WebhookClient/HeaderNames.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static class HeaderNames
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public const string WebHookCheckHeader = "X-eshop-whtoken";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Authentication;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Net.Http.Headers;
 | 
				
			||||||
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class HttpClientAuthorizationDelegatingHandler
 | 
				
			||||||
 | 
					            : DelegatingHandler
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IHttpContextAccessor _httpContextAccesor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _httpContextAccesor = httpContextAccesor;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var authorizationHeader = _httpContextAccesor.HttpContext
 | 
				
			||||||
 | 
					                .Request.Headers["Authorization"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!string.IsNullOrEmpty(authorizationHeader))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                request.Headers.Add("Authorization", new List<string>() { authorizationHeader });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var token = await GetToken();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (token != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return await base.SendAsync(request, cancellationToken);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        async Task<string> GetToken()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const string ACCESS_TOKEN = "access_token";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return await _httpContextAccesor.HttpContext
 | 
				
			||||||
 | 
					                .GetTokenAsync(ACCESS_TOKEN);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/Web/WebhookClient/Models/WebHookReceived.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/Web/WebhookClient/Models/WebHookReceived.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Models
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebHookReceived
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public DateTime When { get; set; }
 | 
				
			||||||
 | 
					        public string Data { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public string Token { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/Web/WebhookClient/Models/WebhookData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/Web/WebhookClient/Models/WebhookData.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Models
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhookData
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public DateTime When { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public string Payload { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public string Type { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								src/Web/WebhookClient/Models/WebhookResponse.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/Web/WebhookClient/Models/WebhookResponse.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Models
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhookResponse
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public DateTime Date { get; set; }
 | 
				
			||||||
 | 
					        public string DestUrl { get; set; }
 | 
				
			||||||
 | 
					        public string Token { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/Web/WebhookClient/Models/WebhookSubscriptionRequest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/Web/WebhookClient/Models/WebhookSubscriptionRequest.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Models
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhookSubscriptionRequest
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public string Url { get; set; }
 | 
				
			||||||
 | 
					        public string Token { get; set; }
 | 
				
			||||||
 | 
					        public string Event { get; set; }
 | 
				
			||||||
 | 
					        public string GrantUrl { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								src/Web/WebhookClient/Pages/Error.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Web/WebhookClient/Pages/Error.cshtml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					@page
 | 
				
			||||||
 | 
					@model ErrorModel
 | 
				
			||||||
 | 
					@{
 | 
				
			||||||
 | 
					    ViewData["Title"] = "Error";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h1 class="text-danger">Error.</h1>
 | 
				
			||||||
 | 
					<h2 class="text-danger">An error occurred while processing your request.</h2>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@if (Model.ShowRequestId)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    <p>
 | 
				
			||||||
 | 
					        <strong>Request ID:</strong> <code>@Model.RequestId</code>
 | 
				
			||||||
 | 
					    </p>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h3>Development Mode</h3>
 | 
				
			||||||
 | 
					<p>
 | 
				
			||||||
 | 
					    Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
 | 
				
			||||||
 | 
					</p>
 | 
				
			||||||
 | 
					<p>
 | 
				
			||||||
 | 
					    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
 | 
				
			||||||
 | 
					    It can result in displaying sensitive information from exceptions to end users.
 | 
				
			||||||
 | 
					    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
 | 
				
			||||||
 | 
					    and restarting the app.
 | 
				
			||||||
 | 
					</p>
 | 
				
			||||||
							
								
								
									
										23
									
								
								src/Web/WebhookClient/Pages/Error.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Web/WebhookClient/Pages/Error.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Diagnostics;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc.RazorPages;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Pages
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
 | 
				
			||||||
 | 
					    public class ErrorModel : PageModel
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public string RequestId { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void OnGet()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								src/Web/WebhookClient/Pages/Index.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/Web/WebhookClient/Pages/Index.cshtml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					@page
 | 
				
			||||||
 | 
					@model IndexModel
 | 
				
			||||||
 | 
					@{
 | 
				
			||||||
 | 
					    ViewData["Title"] = "Home page";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="text-center">
 | 
				
			||||||
 | 
					    <h1 class="display-4">Welcome</h1>
 | 
				
			||||||
 | 
					    <p>eShopOnContainers - Webhook client</p>
 | 
				
			||||||
 | 
					    @if (!User.Identity.IsAuthenticated)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        <a class="btn-primary btn" href="@Url.Action("SignIn", "Account")">Login</a>
 | 
				
			||||||
 | 
					        <p>Why I need to login? You only need to login <bold>to setup a new webhook</bold>.</p>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="table">
 | 
				
			||||||
 | 
					    <h3>Current webhooks received</h3>
 | 
				
			||||||
 | 
					    <p>(Data since last time web started up)<p>
 | 
				
			||||||
 | 
					    <table class="table">
 | 
				
			||||||
 | 
					        @foreach (var webhook in Model.WebHooksReceived)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            <tr>
 | 
				
			||||||
 | 
					                <td>@webhook.When</td>
 | 
				
			||||||
 | 
					                <td><pre>@webhook.Data</pre></td>
 | 
				
			||||||
 | 
					                <td>@(webhook.Token ?? "--None--")</td>
 | 
				
			||||||
 | 
					            </tr>
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    </table>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										30
									
								
								src/Web/WebhookClient/Pages/Index.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/Web/WebhookClient/Pages/Index.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc.RazorPages;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using WebhookClient.Models;
 | 
				
			||||||
 | 
					using WebhookClient.Services;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Pages
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class IndexModel : PageModel
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IHooksRepository _hooksRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IndexModel(IHooksRepository hooksRepository)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _hooksRepository = hooksRepository;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IEnumerable<WebHookReceived> WebHooksReceived { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task OnGet()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            WebHooksReceived = await _hooksRepository.GetAll();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								src/Web/WebhookClient/Pages/Privacy.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/Web/WebhookClient/Pages/Privacy.cshtml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					@page
 | 
				
			||||||
 | 
					@model PrivacyModel
 | 
				
			||||||
 | 
					@{
 | 
				
			||||||
 | 
					    ViewData["Title"] = "Privacy Policy";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					<h1>@ViewData["Title"]</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>Use this page to detail your site's privacy policy.</p>
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/Web/WebhookClient/Pages/Privacy.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/Web/WebhookClient/Pages/Privacy.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc.RazorPages;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Pages
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class PrivacyModel : PageModel
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public void OnGet()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/Web/WebhookClient/Pages/RegisterWebhook.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/Web/WebhookClient/Pages/RegisterWebhook.cshtml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					@page
 | 
				
			||||||
 | 
					@model WebhookClient.Pages.RegisterWebhookModel
 | 
				
			||||||
 | 
					@{
 | 
				
			||||||
 | 
					    ViewData["Title"] = "RegisterWebhook";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h3>Register webhook</h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>This page registers the "OrderPaid" Webhook by sending a POST to webhooks.</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<form method="post">
 | 
				
			||||||
 | 
					    <p>Token: <input type="text" asp-for="Token" /></p>
 | 
				
			||||||
 | 
					    <input type="submit" value="send" />
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@if (Model.ResponseCode != (int)System.Net.HttpStatusCode.OK)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    <p>Error @Model.ResponseCode (@Model.ResponseMessage) when calling the Webhooks API (@Model.RequestUrl) with GrantUrl: @Model.GrantUrl):(</p>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										81
									
								
								src/Web/WebhookClient/Pages/RegisterWebhook.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/Web/WebhookClient/Pages/RegisterWebhook.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Net;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Net.Http.Formatting;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc.RazorPages;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Options;
 | 
				
			||||||
 | 
					using WebhookClient.Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Pages
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [Authorize]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class RegisterWebhookModel : PageModel
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly Settings _settings;
 | 
				
			||||||
 | 
					        private readonly IHttpClientFactory _httpClientFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [BindProperty] public string Token { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int ResponseCode { get; set; }
 | 
				
			||||||
 | 
					        public string RequestUrl { get; set; }
 | 
				
			||||||
 | 
					        public string GrantUrl { get; set; }
 | 
				
			||||||
 | 
					        public string ResponseMessage { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public RegisterWebhookModel(IOptions<Settings> settings, IHttpClientFactory httpClientFactory)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _settings = settings.Value;
 | 
				
			||||||
 | 
					            _httpClientFactory = httpClientFactory;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void OnGet()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ResponseCode = (int)HttpStatusCode.OK;
 | 
				
			||||||
 | 
					            Token = _settings.Token;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task<IActionResult> OnPost()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ResponseCode = (int)HttpStatusCode.OK;
 | 
				
			||||||
 | 
					            var protocol = Request.IsHttps ? "https" : "http";
 | 
				
			||||||
 | 
					            var selfurl = !string.IsNullOrEmpty(_settings.SelfUrl) ? _settings.SelfUrl : $"{protocol}://{Request.Host}/{Request.PathBase}";
 | 
				
			||||||
 | 
					            if (!selfurl.EndsWith("/"))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                selfurl = selfurl + "/";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            var granturl = $"{selfurl}check";
 | 
				
			||||||
 | 
					            var url = $"{selfurl}webhook-received";
 | 
				
			||||||
 | 
					            var client = _httpClientFactory.CreateClient("GrantClient");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var payload = new WebhookSubscriptionRequest()
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Event = "OrderPaid",
 | 
				
			||||||
 | 
					                GrantUrl = granturl,
 | 
				
			||||||
 | 
					                Url = url,
 | 
				
			||||||
 | 
					                Token = Token
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            var response = await client.PostAsync<WebhookSubscriptionRequest>(_settings.WebhooksUrl + "/api/v1/webhooks", payload, new JsonMediaTypeFormatter());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (response.IsSuccessStatusCode)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return RedirectToPage("WebhooksList");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ResponseCode = (int)response.StatusCode;
 | 
				
			||||||
 | 
					                ResponseMessage = response.ReasonPhrase;
 | 
				
			||||||
 | 
					                GrantUrl = granturl;
 | 
				
			||||||
 | 
					                RequestUrl = $"{response.RequestMessage.Method} {response.RequestMessage.RequestUri}";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return Page();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										79
									
								
								src/Web/WebhookClient/Pages/Shared/_Layout.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/Web/WebhookClient/Pages/Shared/_Layout.cshtml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="utf-8" />
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
				
			||||||
 | 
					    <title>@ViewData["Title"] - WebhookClient</title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <environment include="Development">
 | 
				
			||||||
 | 
					        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
 | 
				
			||||||
 | 
					    </environment>
 | 
				
			||||||
 | 
					    <environment exclude="Development">
 | 
				
			||||||
 | 
					        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"
 | 
				
			||||||
 | 
					              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
 | 
				
			||||||
 | 
					              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
 | 
				
			||||||
 | 
					              crossorigin="anonymous"
 | 
				
			||||||
 | 
					              integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE="/>
 | 
				
			||||||
 | 
					    </environment>
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="~/css/site.css" />
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    <header>
 | 
				
			||||||
 | 
					        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
 | 
				
			||||||
 | 
					            <div class="container">
 | 
				
			||||||
 | 
					                <a class="navbar-brand" asp-area="" asp-page="/Index">WebhookClient</a>
 | 
				
			||||||
 | 
					                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
 | 
				
			||||||
 | 
					                        aria-expanded="false" aria-label="Toggle navigation">
 | 
				
			||||||
 | 
					                    <span class="navbar-toggler-icon"></span>
 | 
				
			||||||
 | 
					                </button>
 | 
				
			||||||
 | 
					                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
 | 
				
			||||||
 | 
					                    <ul class="navbar-nav flex-grow-1">
 | 
				
			||||||
 | 
					                        <li class="nav-item">
 | 
				
			||||||
 | 
					                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
 | 
				
			||||||
 | 
					                        </li>
 | 
				
			||||||
 | 
					                        <li class="nav-item">
 | 
				
			||||||
 | 
					                            <a class="nav-link text-dark" asp-area="" asp-page="/RegisterWebhook">Register webhook</a>
 | 
				
			||||||
 | 
					                        </li>
 | 
				
			||||||
 | 
					                        <li class="nav-item">
 | 
				
			||||||
 | 
					                            <a class="nav-link text-dark" asp-area="" asp-page="/WebhooksList">Webhooks registered (in API)</a>
 | 
				
			||||||
 | 
					                        </li>
 | 
				
			||||||
 | 
					                    </ul>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </nav>
 | 
				
			||||||
 | 
					    </header>
 | 
				
			||||||
 | 
					    <div class="container">
 | 
				
			||||||
 | 
					        <main role="main" class="pb-3">
 | 
				
			||||||
 | 
					            @RenderBody()
 | 
				
			||||||
 | 
					        </main>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <footer class="border-top footer text-muted">
 | 
				
			||||||
 | 
					        <div class="container">
 | 
				
			||||||
 | 
					            © 2019 - WebhookClient - <a asp-area="" asp-page="/RegisterWebhook">Register Webhook</a> | <a asp-area="" asp-page="/WebhooksList">Webhooks registered in API</a>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </footer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <environment include="Development">
 | 
				
			||||||
 | 
					        <script src="~/lib/jquery/dist/jquery.js"></script>
 | 
				
			||||||
 | 
					        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
 | 
				
			||||||
 | 
					    </environment>
 | 
				
			||||||
 | 
					    <environment exclude="Development">
 | 
				
			||||||
 | 
					        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
 | 
				
			||||||
 | 
					                asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
 | 
				
			||||||
 | 
					                asp-fallback-test="window.jQuery"
 | 
				
			||||||
 | 
					                crossorigin="anonymous"
 | 
				
			||||||
 | 
					                integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
 | 
				
			||||||
 | 
					        </script>
 | 
				
			||||||
 | 
					        <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"
 | 
				
			||||||
 | 
					                asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
 | 
				
			||||||
 | 
					                asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
 | 
				
			||||||
 | 
					                crossorigin="anonymous"
 | 
				
			||||||
 | 
					                integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
 | 
				
			||||||
 | 
					        </script>
 | 
				
			||||||
 | 
					    </environment>
 | 
				
			||||||
 | 
					    <script src="~/js/site.js" asp-append-version="true"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @RenderSection("Scripts", required: false)
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					<environment include="Development">
 | 
				
			||||||
 | 
					    <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
 | 
				
			||||||
 | 
					    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
 | 
				
			||||||
 | 
					</environment>
 | 
				
			||||||
 | 
					<environment exclude="Development">
 | 
				
			||||||
 | 
					    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
 | 
				
			||||||
 | 
					            asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
 | 
				
			||||||
 | 
					            asp-fallback-test="window.jQuery && window.jQuery.validator"
 | 
				
			||||||
 | 
					            crossorigin="anonymous"
 | 
				
			||||||
 | 
					            integrity="sha256-F6h55Qw6sweK+t7SiOJX+2bpSAa3b/fnlrVCJvmEj1A=">
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
 | 
				
			||||||
 | 
					            asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
 | 
				
			||||||
 | 
					            asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
 | 
				
			||||||
 | 
					            crossorigin="anonymous"
 | 
				
			||||||
 | 
					            integrity="sha256-9GycpJnliUjJDVDqP0UEu/bsm9U+3dnQUH8+3W10vkY=">
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					</environment>
 | 
				
			||||||
							
								
								
									
										28
									
								
								src/Web/WebhookClient/Pages/WebhooksList.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/Web/WebhookClient/Pages/WebhooksList.cshtml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					@page
 | 
				
			||||||
 | 
					@model WebhookClient.Pages.WebhooksListModel
 | 
				
			||||||
 | 
					@{
 | 
				
			||||||
 | 
					    ViewData["Title"] = "WebhooksList";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h1>List of Webhooks registered by user @User.Identity.Name</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<table class="table">
 | 
				
			||||||
 | 
					    <thead class="thead-light">
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            <th scope="col">Date</th>
 | 
				
			||||||
 | 
					            <th scope="col">Destination Url</th>
 | 
				
			||||||
 | 
					            <th scope="col">Validation token</th>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					    </thead>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @foreach (var whr in Model.Webhooks)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            <td>@whr.Date</td>
 | 
				
			||||||
 | 
					            <td>@whr.DestUrl</td>
 | 
				
			||||||
 | 
					            <td>@whr.Token</td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										28
									
								
								src/Web/WebhookClient/Pages/WebhooksList.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/Web/WebhookClient/Pages/WebhooksList.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc.RazorPages;
 | 
				
			||||||
 | 
					using WebhookClient.Models;
 | 
				
			||||||
 | 
					using WebhookClient.Services;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Pages
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhooksListModel : PageModel
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IWebhooksClient _webhooksClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IEnumerable<WebhookResponse> Webhooks { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public WebhooksListModel(IWebhooksClient webhooksClient)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _webhooksClient = webhooksClient;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task OnGet()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Webhooks = await _webhooksClient.LoadWebhooks();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/Web/WebhookClient/Pages/_ViewImports.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/Web/WebhookClient/Pages/_ViewImports.cshtml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					@using WebhookClient
 | 
				
			||||||
 | 
					@namespace WebhookClient.Pages
 | 
				
			||||||
 | 
					@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/Web/WebhookClient/Pages/_ViewStart.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/Web/WebhookClient/Pages/_ViewStart.cshtml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					@{
 | 
				
			||||||
 | 
					    Layout = "_Layout";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								src/Web/WebhookClient/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/Web/WebhookClient/Program.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class Program
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static void Main(string[] args)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            CreateWebHostBuilder(args).Build().Run();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
 | 
				
			||||||
 | 
					            WebHost.CreateDefaultBuilder(args)
 | 
				
			||||||
 | 
					                .UseStartup<Startup>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								src/Web/WebhookClient/Properties/launchSettings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/Web/WebhookClient/Properties/launchSettings.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "iisSettings": {
 | 
				
			||||||
 | 
					    "windowsAuthentication": false,
 | 
				
			||||||
 | 
					    "anonymousAuthentication": true,
 | 
				
			||||||
 | 
					    "iisExpress": {
 | 
				
			||||||
 | 
					      "applicationUrl": "http://localhost:51921",
 | 
				
			||||||
 | 
					      "sslPort": 44398
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "profiles": {
 | 
				
			||||||
 | 
					    "IIS Express": {
 | 
				
			||||||
 | 
					      "commandName": "IISExpress",
 | 
				
			||||||
 | 
					      "launchBrowser": true,
 | 
				
			||||||
 | 
					      "environmentVariables": {
 | 
				
			||||||
 | 
					        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "WebhookClient": {
 | 
				
			||||||
 | 
					      "commandName": "Project",
 | 
				
			||||||
 | 
					      "launchBrowser": true,
 | 
				
			||||||
 | 
					      "environmentVariables": {
 | 
				
			||||||
 | 
					        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "applicationUrl": "https://localhost:5001;http://localhost:5000"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "Docker": {
 | 
				
			||||||
 | 
					      "commandName": "Docker",
 | 
				
			||||||
 | 
					      "launchBrowser": true,
 | 
				
			||||||
 | 
					      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								src/Web/WebhookClient/Services/IHooksRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/Web/WebhookClient/Services/IHooksRepository.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using WebhookClient.Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public interface IHooksRepository
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Task<IEnumerable<WebHookReceived>> GetAll();
 | 
				
			||||||
 | 
					        Task AddNew(WebHookReceived hook);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								src/Web/WebhookClient/Services/IWebhooksClient.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/Web/WebhookClient/Services/IWebhooksClient.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using WebhookClient.Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public interface IWebhooksClient
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Task<IEnumerable<WebhookResponse>> LoadWebhooks();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								src/Web/WebhookClient/Services/InMemoryHooksRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Web/WebhookClient/Services/InMemoryHooksRepository.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using WebhookClient.Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class InMemoryHooksRepository : IHooksRepository
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly List<WebHookReceived> _data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public InMemoryHooksRepository() => _data = new List<WebHookReceived>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Task AddNew(WebHookReceived hook)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _data.Add(hook);
 | 
				
			||||||
 | 
					            return Task.CompletedTask;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Task<IEnumerable<WebHookReceived>> GetAll()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return Task.FromResult(_data.AsEnumerable());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								src/Web/WebhookClient/Services/WebhooksClient.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/Web/WebhookClient/Services/WebhooksClient.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					using Microsoft.Extensions.Options;
 | 
				
			||||||
 | 
					using Newtonsoft.Json;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using WebhookClient.Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class WebhooksClient : IWebhooksClient
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private readonly IHttpClientFactory _httpClientFactory;
 | 
				
			||||||
 | 
					        private readonly Settings _settings;
 | 
				
			||||||
 | 
					        public WebhooksClient(IHttpClientFactory httpClientFactory, IOptions<Settings> settings)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _httpClientFactory = httpClientFactory;
 | 
				
			||||||
 | 
					            _settings = settings.Value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        public async Task<IEnumerable<WebhookResponse>> LoadWebhooks()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var client = _httpClientFactory.CreateClient("GrantClient");
 | 
				
			||||||
 | 
					            var response = await client.GetAsync(_settings.WebhooksUrl + "/api/v1/webhooks");
 | 
				
			||||||
 | 
					            var json = await response.Content.ReadAsStringAsync();
 | 
				
			||||||
 | 
					            var subscriptions = JsonConvert.DeserializeObject<IEnumerable<WebhookResponse>>(json);
 | 
				
			||||||
 | 
					            return subscriptions;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/Web/WebhookClient/Settings.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/Web/WebhookClient/Settings.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class Settings
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public string Token { get; set; }
 | 
				
			||||||
 | 
					        public string IdentityUrl { get; set; }
 | 
				
			||||||
 | 
					        public string CallBackUrl { get; set; }
 | 
				
			||||||
 | 
					        public string WebhooksUrl { get; set; }
 | 
				
			||||||
 | 
					        public string SelfUrl { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool ValidateToken { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										151
									
								
								src/Web/WebhookClient/Startup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								src/Web/WebhookClient/Startup.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Authentication.Cookies;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Authentication.OpenIdConnect;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Builder;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.DependencyInjection;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Net;
 | 
				
			||||||
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					using WebhookClient.Services;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace WebhookClient
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class Startup
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public Startup(IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Configuration = configuration;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IConfiguration Configuration { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // This method gets called by the runtime. Use this method to add services to the container.
 | 
				
			||||||
 | 
					        public void ConfigureServices(IServiceCollection services)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services
 | 
				
			||||||
 | 
					                .AddSession(opt =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    opt.Cookie.Name = ".eShopWebhooks.Session";
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .AddConfiguration(Configuration)
 | 
				
			||||||
 | 
					                .AddHttpClientServices(Configuration)
 | 
				
			||||||
 | 
					                .AddCustomAuthentication(Configuration)
 | 
				
			||||||
 | 
					                .AddTransient<IWebhooksClient, WebhooksClient>()
 | 
				
			||||||
 | 
					                .AddSingleton<IHooksRepository, InMemoryHooksRepository>()
 | 
				
			||||||
 | 
					                .AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
 | 
				
			||||||
 | 
					        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var pathBase = Configuration["PATH_BASE"];
 | 
				
			||||||
 | 
					            if (!string.IsNullOrEmpty(pathBase))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                app.UsePathBase(pathBase);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (env.IsDevelopment())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                app.UseDeveloperExceptionPage();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                app.UseExceptionHandler("/Error");
 | 
				
			||||||
 | 
					                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            app.UseAuthentication();
 | 
				
			||||||
 | 
					            app.Map("/check", capp =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                capp.Run(async (context) =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if ("OPTIONS".Equals(context.Request.Method, StringComparison.InvariantCultureIgnoreCase))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        var validateToken = bool.TrueString.Equals(Configuration["ValidateToken"], StringComparison.InvariantCultureIgnoreCase);
 | 
				
			||||||
 | 
					                        var header = context.Request.Headers[HeaderNames.WebHookCheckHeader];
 | 
				
			||||||
 | 
					                        var value = header.FirstOrDefault();
 | 
				
			||||||
 | 
					                        var tokenToValidate = Configuration["Token"];
 | 
				
			||||||
 | 
					                        if (!validateToken ||  value == tokenToValidate)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            if (!string.IsNullOrWhiteSpace(tokenToValidate))
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                context.Response.Headers.Add(HeaderNames.WebHookCheckHeader, tokenToValidate);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            context.Response.StatusCode = (int)HttpStatusCode.OK;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        else
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            await context.Response.WriteAsync("Invalid token");
 | 
				
			||||||
 | 
					                            context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            app.UseStaticFiles();
 | 
				
			||||||
 | 
					            app.UseSession();
 | 
				
			||||||
 | 
					            app.UseMvcWithDefaultRoute();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static class ServiceExtensions
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddConfiguration(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services.AddOptions();
 | 
				
			||||||
 | 
					            services.Configure<Settings>(configuration);
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var identityUrl = configuration.GetValue<string>("IdentityUrl");
 | 
				
			||||||
 | 
					            var callBackUrl = configuration.GetValue<string>("CallBackUrl");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Add Authentication services          
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            services.AddAuthentication(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
 | 
				
			||||||
 | 
					                options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromHours(2))
 | 
				
			||||||
 | 
					            .AddOpenIdConnect(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
 | 
				
			||||||
 | 
					                options.Authority = identityUrl.ToString();
 | 
				
			||||||
 | 
					                options.SignedOutRedirectUri = callBackUrl.ToString();
 | 
				
			||||||
 | 
					                options.ClientId = "webhooksclient";
 | 
				
			||||||
 | 
					                options.ClientSecret = "secret";
 | 
				
			||||||
 | 
					                options.ResponseType = "code id_token";
 | 
				
			||||||
 | 
					                options.SaveTokens = true;
 | 
				
			||||||
 | 
					                options.GetClaimsFromUserInfoEndpoint = true;
 | 
				
			||||||
 | 
					                options.RequireHttpsMetadata = false;
 | 
				
			||||||
 | 
					                options.Scope.Add("openid");
 | 
				
			||||||
 | 
					                options.Scope.Add("webhooks");
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
 | 
				
			||||||
 | 
					            services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
 | 
				
			||||||
 | 
					            services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //add http client services
 | 
				
			||||||
 | 
					            services.AddHttpClient("GrantClient")
 | 
				
			||||||
 | 
					                   .SetHandlerLifetime(TimeSpan.FromMinutes(5))
 | 
				
			||||||
 | 
					                   .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return services;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user