Webhooks API: WIP - Initial commit
This commit is contained in:
parent
81f2ed4769
commit
8677b8d240
@ -41,6 +41,7 @@ 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
|
||||||
- UseCustomizationData=True
|
- UseCustomizationData=True
|
||||||
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
|
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
|
||||||
- OrchestratorType=${ORCHESTRATOR_TYPE}
|
- OrchestratorType=${ORCHESTRATOR_TYPE}
|
||||||
@ -182,6 +183,15 @@ 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}
|
||||||
|
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 +390,10 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "5100:80"
|
- "5100:80"
|
||||||
|
|
||||||
|
webhooks.client:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:80
|
||||||
|
- Token=6168DB8D-DC58-4094-AF24-483278923590
|
||||||
|
ports:
|
||||||
|
- "5114:80"
|
@ -86,6 +86,14 @@ services:
|
|||||||
- nosql.data
|
- nosql.data
|
||||||
- rabbitmq
|
- rabbitmq
|
||||||
|
|
||||||
|
webhooks.api:
|
||||||
|
image: 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: eshop/ocelotapigw:${TAG:-latest}
|
||||||
build:
|
build:
|
||||||
@ -217,3 +225,10 @@ services:
|
|||||||
- webshoppingapigw
|
- webshoppingapigw
|
||||||
- webmarketingapigw
|
- webmarketingapigw
|
||||||
|
|
||||||
|
webhooks.client:
|
||||||
|
image: 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}
|
||||||
|
@ -274,7 +274,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
|||||||
services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>(
|
services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>(
|
||||||
sp => (DbConnection c) => new IntegrationEventLogService(c));
|
sp => (DbConnection c) => new IntegrationEventLogService(c));
|
||||||
|
|
||||||
services.AddTransient<ICatalogIntegrationEventService, CatalogIntegrationEventService>();
|
// services.AddTransient<ICatalogIntegrationEventService, CatalogIntegrationEventService>();
|
||||||
|
|
||||||
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||||
{
|
{
|
||||||
|
@ -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,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
|
|||||||
"locations",
|
"locations",
|
||||||
"marketing",
|
"marketing",
|
||||||
"webshoppingagg",
|
"webshoppingagg",
|
||||||
"orders.signalrhub"
|
"orders.signalrhub",
|
||||||
|
"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 +161,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
|
|||||||
"basket",
|
"basket",
|
||||||
"locations",
|
"locations",
|
||||||
"marketing",
|
"marketing",
|
||||||
"webshoppingagg"
|
"webshoppingagg",
|
||||||
|
"webhooks"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
new Client
|
new Client
|
||||||
@ -249,6 +254,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,7 @@ 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"));
|
||||||
|
|
||||||
if (!context.Clients.Any())
|
if (!context.Clients.Any())
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Webhooks.API.Model;
|
||||||
|
|
||||||
|
namespace Webhooks.API.Controller
|
||||||
|
{
|
||||||
|
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.Controller
|
||||||
|
{
|
||||||
|
[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}", Name = "Get")]
|
||||||
|
[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.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("Get", new { id = subscription.Id });
|
||||||
|
}
|
||||||
|
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,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,18 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
12
src/Services/Webhooks/Webhooks.API/Model/WebhookType.cs
Normal file
12
src/Services/Webhooks/Webhooks.API/Model/WebhookType.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Webhooks.API.Model
|
||||||
|
{
|
||||||
|
public enum WebhookType
|
||||||
|
{
|
||||||
|
CatalogItemPriceChange = 1
|
||||||
|
}
|
||||||
|
}
|
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,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Webhooks.API.Services
|
||||||
|
{
|
||||||
|
class GrantUrlTesterService : IGrantUrlTesterService
|
||||||
|
{
|
||||||
|
private readonly IHttpClientFactory _clientFactory;
|
||||||
|
public GrantUrlTesterService(IHttpClientFactory factory)
|
||||||
|
{
|
||||||
|
_clientFactory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> TestGrantUrl(string url, string token)
|
||||||
|
{
|
||||||
|
var client = _clientFactory.CreateClient("GrantClient");
|
||||||
|
|
||||||
|
var msg = new HttpRequestMessage(HttpMethod.Options, url);
|
||||||
|
msg.Headers.Add("X-eshop-whtoken", token);
|
||||||
|
var response = await client.SendAsync(msg);
|
||||||
|
return response.IsSuccessStatusCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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 url, string token);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace Webhooks.API.Services
|
||||||
|
{
|
||||||
|
public interface IIdentityService
|
||||||
|
{
|
||||||
|
string GetUserIdentity();
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
333
src/Services/Webhooks/Webhooks.API/Startup.cs
Normal file
333
src/Services/Webhooks/Webhooks.API/Startup.cs
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Common;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Autofac;
|
||||||
|
using HealthChecks.UI.Client;
|
||||||
|
using Microsoft.ApplicationInsights.Extensibility;
|
||||||
|
using Microsoft.ApplicationInsights.ServiceFabric;
|
||||||
|
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.Services;
|
||||||
|
|
||||||
|
namespace Webhooks.API
|
||||||
|
{
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
|
public Startup(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
Configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services
|
||||||
|
.AddAppInsight(Configuration)
|
||||||
|
.AddCustomMVC(Configuration)
|
||||||
|
.AddCustomDbContext(Configuration)
|
||||||
|
.AddSwagger(Configuration)
|
||||||
|
.AddCustomHealthCheck(Configuration)
|
||||||
|
.AddHttpClientServices(Configuration)
|
||||||
|
.AddIntegrationServices(Configuration)
|
||||||
|
.AddEventBus(Configuration)
|
||||||
|
.AddTransient<IIdentityService, IdentityService>()
|
||||||
|
.AddTransient<IGrantUrlTesterService, GrantUrlTesterService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
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 ConfigureEventBus(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
||||||
|
// eventBus.Subscribe<OrderStatusChangedToAwaitingValidationIntegrationEvent, OrderStatusChangedToAwaitingValidationIntegrationEventHandler>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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<OrderStatusChangedToAwaitingValidationIntegrationEventHandler>();
|
||||||
|
|
||||||
|
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>();
|
||||||
|
|
||||||
|
|
||||||
|
//register delegating handlers
|
||||||
|
//services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
|
||||||
|
|
||||||
|
//InfinteTimeSpan -> See: https://github.com/aspnet/HttpClientFactory/issues/194
|
||||||
|
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));
|
||||||
|
|
||||||
|
// services.AddTransient<ICatalogIntegrationEventService, CatalogIntegrationEventService>();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj
Normal file
31
src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<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="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,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Debug",
|
||||||
|
"System": "Information",
|
||||||
|
"Microsoft": "Information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/Services/Webhooks/Webhooks.API/appsettings.json
Normal file
8
src/Services/Webhooks/Webhooks.API/appsettings.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
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";
|
||||||
|
}
|
||||||
|
}
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/Web/WebhookClient/Pages/Index.cshtml
Normal file
10
src/Web/WebhookClient/Pages/Index.cshtml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
@page
|
||||||
|
@model IndexModel
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Home page";
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="display-4">Welcome</h1>
|
||||||
|
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
|
||||||
|
</div>
|
17
src/Web/WebhookClient/Pages/Index.cshtml.cs
Normal file
17
src/Web/WebhookClient/Pages/Index.cshtml.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
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 IndexModel : PageModel
|
||||||
|
{
|
||||||
|
public void OnGet()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
@using Microsoft.AspNetCore.Http.Features
|
||||||
|
|
||||||
|
@{
|
||||||
|
var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
|
||||||
|
var showBanner = !consentFeature?.CanTrack ?? false;
|
||||||
|
var cookieString = consentFeature?.CreateConsentCookie();
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (showBanner)
|
||||||
|
{
|
||||||
|
<div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
|
||||||
|
Use this space to summarize your privacy and cookie use policy. <a asp-page="/Privacy">Learn More</a>.
|
||||||
|
<button type="button" class="accept-policy close" data-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
|
||||||
|
<span aria-hidden="true">Accept</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var button = document.querySelector("#cookieConsent button[data-cookie-string]");
|
||||||
|
button.addEventListener("click", function (event) {
|
||||||
|
document.cookie = button.dataset.cookieString;
|
||||||
|
}, false);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
}
|
77
src/Web/WebhookClient/Pages/Shared/_Layout.cshtml
Normal file
77
src/Web/WebhookClient/Pages/Shared/_Layout.cshtml
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<!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="/Privacy">Privacy</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container">
|
||||||
|
<partial name="_CookieConsentPartial" />
|
||||||
|
<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="/Privacy">Privacy</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>
|
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}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
81
src/Web/WebhookClient/Startup.cs
Normal file
81
src/Web/WebhookClient/Startup.cs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
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.Configure<CookiePolicyOptions>(options =>
|
||||||
|
{
|
||||||
|
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
|
||||||
|
options.CheckConsentNeeded = context => true;
|
||||||
|
options.MinimumSameSitePolicy = SameSiteMode.None;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
services.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)
|
||||||
|
{
|
||||||
|
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.UseHsts();
|
||||||
|
}
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.Map("/check", capp =>
|
||||||
|
{
|
||||||
|
capp.Run(async (context) =>
|
||||||
|
{
|
||||||
|
if ("OPTIONS".Equals(context.Request.Method, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
var header = context.Request.Headers[HeaderNames.WebHookCheckHeader];
|
||||||
|
var value = header.FirstOrDefault();
|
||||||
|
if (value == Configuration["Token"])
|
||||||
|
{
|
||||||
|
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.UseCookiePolicy();
|
||||||
|
app.UseMvc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/Web/WebhookClient/WebhookClient.csproj
Normal file
17
src/Web/WebhookClient/WebhookClient.csproj
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
|
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<UserSecretsId>36215d41-f31a-4aa6-9929-bd67d650e7b5</UserSecretsId>
|
||||||
|
</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" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
10
src/Web/WebhookClient/appsettings.Development.json
Normal file
10
src/Web/WebhookClient/appsettings.Development.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Debug",
|
||||||
|
"System": "Information",
|
||||||
|
"Microsoft": "Information"
|
||||||
|
},
|
||||||
|
"Token": "6168DB8D-DC58-4094-AF24-483278923590"
|
||||||
|
}
|
||||||
|
}
|
8
src/Web/WebhookClient/appsettings.json
Normal file
8
src/Web/WebhookClient/appsettings.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user