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
|
||||
- MobileShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5120
|
||||
- WebShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5121
|
||||
- WebhooksApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5113
|
||||
- UseCustomizationData=True
|
||||
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
|
||||
- OrchestratorType=${ORCHESTRATOR_TYPE}
|
||||
@ -182,6 +183,15 @@ services:
|
||||
ports:
|
||||
- "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).
|
||||
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:
|
||||
environment:
|
||||
@ -380,3 +390,10 @@ services:
|
||||
ports:
|
||||
- "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
|
||||
- rabbitmq
|
||||
|
||||
webhooks.api:
|
||||
image: eshop/webhooks.api:${TAG:-latest}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: src/Services/Webhooks/Webhooks.API/Dockerfile
|
||||
depends_on:
|
||||
- sql.data
|
||||
|
||||
mobileshoppingapigw:
|
||||
image: eshop/ocelotapigw:${TAG:-latest}
|
||||
build:
|
||||
@ -217,3 +225,10 @@ services:
|
||||
- webshoppingapigw
|
||||
- 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
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Payment.API", "src\Services\Payment\Payment.API\Payment.API.csproj", "{0AB40131-8AD7-436F-9C6B-EDA59CFA3A84}"
|
||||
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
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
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|x86.ActiveCfg = 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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -1703,6 +1805,9 @@ Global
|
||||
{120CABB3-0FEA-4B40-B4B5-2D3041798C80} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B}
|
||||
{C61C5CFE-4876-4A46-A96E-5BBF596A984A} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
|
||||
{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
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9}
|
||||
|
@ -274,7 +274,7 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API
|
||||
services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>(
|
||||
sp => (DbConnection c) => new IntegrationEventLogService(c));
|
||||
|
||||
services.AddTransient<ICatalogIntegrationEventService, CatalogIntegrationEventService>();
|
||||
// services.AddTransient<ICatalogIntegrationEventService, CatalogIntegrationEventService>();
|
||||
|
||||
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
|
||||
{
|
||||
|
@ -17,7 +17,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
|
||||
new ApiResource("locations", "Locations Service"),
|
||||
new ApiResource("mobileshoppingagg", "Mobile 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",
|
||||
"marketing",
|
||||
"webshoppingagg",
|
||||
"orders.signalrhub"
|
||||
"orders.signalrhub",
|
||||
"webhooks"
|
||||
},
|
||||
},
|
||||
new Client
|
||||
@ -84,7 +86,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
|
||||
"basket",
|
||||
"locations",
|
||||
"marketing",
|
||||
"mobileshoppingagg"
|
||||
"mobileshoppingagg",
|
||||
"webhooks"
|
||||
},
|
||||
//Allow requesting refresh tokens for long lived API access
|
||||
AllowOfflineAccess = true,
|
||||
@ -122,7 +125,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
|
||||
"locations",
|
||||
"marketing",
|
||||
"webshoppingagg",
|
||||
"orders.signalrhub"
|
||||
"orders.signalrhub",
|
||||
"webhooks"
|
||||
},
|
||||
AccessTokenLifetime = 60*60*2, // 2 hours
|
||||
IdentityTokenLifetime= 60*60*2 // 2 hours
|
||||
@ -157,7 +161,8 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
|
||||
"basket",
|
||||
"locations",
|
||||
"marketing",
|
||||
"webshoppingagg"
|
||||
"webshoppingagg",
|
||||
"webhooks"
|
||||
},
|
||||
},
|
||||
new Client
|
||||
@ -249,6 +254,21 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
|
||||
{
|
||||
"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("MobileShoppingAgg", configuration.GetValue<string>("MobileShoppingAggClient"));
|
||||
clientUrls.Add("WebShoppingAgg", configuration.GetValue<string>("WebShoppingAggClient"));
|
||||
clientUrls.Add("WebhooksApi", configuration.GetValue<string>("WebhooksApiClient"));
|
||||
|
||||
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