diff --git a/src/Services/Ordering/Ordering.SignalrHub/CustomExtensionMethods.cs b/src/Services/Ordering/Ordering.SignalrHub/CustomExtensionMethods.cs new file mode 100644 index 000000000..dd6a3d442 --- /dev/null +++ b/src/Services/Ordering/Ordering.SignalrHub/CustomExtensionMethods.cs @@ -0,0 +1,42 @@ +using Microsoft.AspNetCore.Http; + +public static class CustomExtensionMethods +{ + public static IServiceCollection AddSignalR(this IServiceCollection services, IConfiguration configuration) + { + if (configuration.GetConnectionString("redis") is string redisConnection) + { + // Add a redis health check + services.AddSignalR().AddStackExchangeRedis(redisConnection); + } + else + { + services.AddSignalR(); + } + + // Configure hub auth (grab the token from the query string) + return services.Configure(JwtBearerDefaults.AuthenticationScheme, options => + { + options.Events = new JwtBearerEvents + { + OnMessageReceived = context => + { + var accessToken = context.Request.Query["access_token"]; + + var endpoint = context.HttpContext.GetEndpoint(); + + // Make sure this is a Hub endpoint. + if (endpoint?.Metadata.GetMetadata() is null) + { + return Task.CompletedTask; + } + + context.Token = accessToken; + + return Task.CompletedTask; + } + }; + }); + } + +} diff --git a/src/Services/Ordering/Ordering.SignalrHub/GlobalUsings.cs b/src/Services/Ordering/Ordering.SignalrHub/GlobalUsings.cs index 5d956ba77..df4552c08 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/GlobalUsings.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/GlobalUsings.cs @@ -1,29 +1,16 @@ -global using HealthChecks.UI.Client; -global using Microsoft.AspNetCore.Authentication.JwtBearer; +global using Microsoft.AspNetCore.Authentication.JwtBearer; global using Microsoft.AspNetCore.Authorization; global using Microsoft.AspNetCore.Builder; -global using Microsoft.AspNetCore.Diagnostics.HealthChecks; -global using Microsoft.AspNetCore.Hosting; global using Microsoft.AspNetCore.SignalR; -global using Microsoft.AspNetCore; global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; -global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents; global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.DependencyInjection; -global using Microsoft.Extensions.Diagnostics.HealthChecks; global using Microsoft.Extensions.Logging; global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub; -global using RabbitMQ.Client; global using System.Collections.Generic; -global using System.IdentityModel.Tokens.Jwt; -global using System.IO; -global using System.Reflection; global using System.Threading.Tasks; global using System; -global using Microsoft.Extensions.Hosting; diff --git a/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs b/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs index 9f545bba4..b22960096 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs @@ -3,7 +3,6 @@ [Authorize] public class NotificationsHub : Hub { - public override async Task OnConnectedAsync() { await Groups.AddToGroupAsync(Context.ConnectionId, Context.User.Identity.Name); diff --git a/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj b/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj index 0eab4e6cb..8013fc7b4 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj +++ b/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj @@ -28,6 +28,7 @@ + diff --git a/src/Services/Ordering/Ordering.SignalrHub/Program.cs b/src/Services/Ordering/Ordering.SignalrHub/Program.cs index 96fc26e0b..8ad09b8f6 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Program.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/Program.cs @@ -1,82 +1,21 @@ -var builder = WebApplication.CreateBuilder(new WebApplicationOptions -{ - Args = args, - ApplicationName = typeof(Program).Assembly.FullName, - ContentRootPath = Directory.GetCurrentDirectory() -}); -builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()); -builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); -builder.Configuration.AddEnvironmentVariables(); -builder.WebHost.CaptureStartupErrors(false); - -builder.Services - .AddCustomHealthCheck(builder.Configuration) - .AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder - .AllowAnyMethod() - .AllowAnyHeader() - .SetIsOriginAllowed((host) => true) - .AllowCredentials()); - }); -if (builder.Configuration.GetValue("IsClusterEnv") == bool.TrueString) -{ - builder.Services - .AddSignalR() - .AddStackExchangeRedis(builder.Configuration["SignalrStoreConnectionString"]); -} -else -{ - builder.Services.AddSignalR(); -} +using Services.Common; -if (builder.Configuration.GetValue("AzureServiceBusEnabled")) -{ - builder.Services.AddSingleton(sp => - { - var serviceBusConnectionString = builder.Configuration["EventBusConnection"]; +var builder = WebApplication.CreateBuilder(args); - var subscriptionClientName = builder.Configuration["SubscriptionClientName"]; +builder.AddServiceDefaults(); - return new DefaultServiceBusPersisterConnection(serviceBusConnectionString); - }); -} -else +builder.Services.AddCors(options => { - builder.Services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); - - - var factory = new ConnectionFactory() - { - HostName = builder.Configuration["EventBusConnection"], - DispatchConsumersAsync = true - }; - - if (!string.IsNullOrEmpty(builder.Configuration["EventBusUserName"])) - { - factory.UserName = builder.Configuration["EventBusUserName"]; - } - - if (!string.IsNullOrEmpty(builder.Configuration["EventBusPassword"])) - { - factory.Password = builder.Configuration["EventBusPassword"]; - } - - var retryCount = 5; - if (!string.IsNullOrEmpty(builder.Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(builder.Configuration["EventBusRetryCount"]); - } + options.AddPolicy("CorsPolicy", + builder => builder + .AllowAnyMethod() + .AllowAnyHeader() + .SetIsOriginAllowed((host) => true) + .AllowCredentials()); +}); - return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); - }); -} +builder.Services.AddSignalR(builder.Configuration); -ConfigureAuthService(builder.Services, builder.Configuration); -RegisterEventBus(builder.Services, builder.Configuration); builder.Services.AddSingleton, OrderStatusChangedToAwaitingValidationIntegrationEventHandler>(); builder.Services.AddSingleton, OrderStatusChangedToCancelledIntegrationEventHandler>(); builder.Services.AddSingleton, OrderStatusChangedToPaidIntegrationEventHandler>(); @@ -85,146 +24,27 @@ builder.Services.AddSingleton, OrderStatusChangedToSubmittedIntegrationEventHandler>(); var app = builder.Build(); -if (!app.Environment.IsDevelopment()) -{ - app.UseExceptionHandler("/Home/Error"); -} -var pathBase = builder.Configuration["PATH_BASE"]; -if (!string.IsNullOrEmpty(pathBase)) +if (!await app.CheckHealthAsync()) { - app.UsePathBase(pathBase); + return; } -app.UseRouting(); +app.UseServiceDefaults(); + app.UseCors("CorsPolicy"); app.UseAuthentication(); app.UseAuthorization(); -app.MapHealthChecks("/hc", new HealthCheckOptions() -{ - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse -}); -app.MapHealthChecks("/liveness", new HealthCheckOptions -{ - Predicate = r => r.Name.Contains("self") -}); -app.MapHub("/hub/notificationhub"); - -ConfigureEventBus(app); -await app.RunAsync(); - -void ConfigureEventBus(IApplicationBuilder app) -{ - var eventBus = app.ApplicationServices.GetRequiredService(); - - eventBus.Subscribe(); - eventBus.Subscribe(); - eventBus.Subscribe(); - eventBus.Subscribe(); - eventBus.Subscribe(); - eventBus.Subscribe(); -} - -void ConfigureAuthService(IServiceCollection services, IConfiguration configuration) -{ - // prevent from mapping "sub" claim to nameidentifier. - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); - - var identityUrl = configuration.GetValue("IdentityUrl"); - - services.AddAuthentication("Bearer").AddJwtBearer(options => - { - options.Authority = identityUrl; - options.RequireHttpsMetadata = false; - options.Audience = "orders.signalrhub"; - options.TokenValidationParameters.ValidateAudience = false; - options.Events = new JwtBearerEvents - { - OnMessageReceived = context => - { - var accessToken = context.Request.Query["access_token"]; - var path = context.HttpContext.Request.Path; - if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/hub/notificationhub"))) - { - context.Token = accessToken; - } - return Task.CompletedTask; - } - }; - }); - services.AddAuthorization(options => - { - options.AddPolicy("ApiScope", policy => - { - policy.RequireAuthenticatedUser(); - policy.RequireClaim("scope", "orders.signalrhub"); - }); - }); -} -void RegisterEventBus(IServiceCollection services, IConfiguration configuration) -{ - if (configuration.GetValue("AzureServiceBusEnabled")) - { - services.AddSingleton(sp => - { - var serviceBusPersisterConnection = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - string subscriptionName = configuration["SubscriptionClientName"]; - - return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, sp, subscriptionName); - }); - } - else - { - services.AddSingleton(sp => - { - var subscriptionClientName = configuration["SubscriptionClientName"]; - var rabbitMQPersistentConnection = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - var retryCount = 5; - if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(configuration["EventBusRetryCount"]); - } - - return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, sp, eventBusSubcriptionsManager, subscriptionClientName, retryCount); - }); - } - - services.AddSingleton(); -} -public static class CustomExtensionMethods -{ - public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) - { - var hcBuilder = services.AddHealthChecks(); +app.MapHub("/hub/notificationhub"); - hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); +var eventBus = app.Services.GetRequiredService(); - if (configuration.GetValue("AzureServiceBusEnabled")) - { - hcBuilder - .AddAzureServiceBusTopic( - configuration["EventBusConnection"], - topicName: "eshop_event_bus", - name: "signalr-servicebus-check", - tags: new string[] { "servicebus" }); - } - else - { - hcBuilder - .AddRabbitMQ( - $"amqp://{configuration["EventBusConnection"]}", - name: "signalr-rabbitmqbus-check", - tags: new string[] { "rabbitmqbus" }); - } +eventBus.Subscribe(); +eventBus.Subscribe(); +eventBus.Subscribe(); +eventBus.Subscribe(); +eventBus.Subscribe(); +eventBus.Subscribe(); - return services; - } -} +await app.RunAsync(); diff --git a/src/Services/Ordering/Ordering.SignalrHub/Properties/launchSettings.json b/src/Services/Ordering/Ordering.SignalrHub/Properties/launchSettings.json index 3ff683a08..9bcb7d2d3 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Properties/launchSettings.json +++ b/src/Services/Ordering/Ordering.SignalrHub/Properties/launchSettings.json @@ -1,27 +1,12 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:51311/", - "sslPort": 0 - } - }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, "Ordering.SignalrHub": { "commandName": "Project", "launchBrowser": true, + "applicationUrl": "http://localhost:5223/", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "http://localhost:51312/" + } } } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/appsettings.json b/src/Services/Ordering/Ordering.SignalrHub/appsettings.json index be528bb8b..bf7ffc1e2 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/appsettings.json +++ b/src/Services/Ordering/Ordering.SignalrHub/appsettings.json @@ -1,7 +1,19 @@ { - "IdentityUrl": "http://localhost:5105", - "AzureServiceBusEnabled": false, - "SubscriptionClientName": "Ordering.signalrhub", - "EventBusRetryCount": 5, - "EventBusConnection": "localhost" + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "Identity": { + "Audience": "orders.signalrhub", + "Url": "http://localhost:5105" + }, + "EventBus": { + "SubscriptionClientName": "Ordering.signalrhub", + "RetryCount": 5 + }, + "ConnectionStrings": { + "EventBus": "localhost" + } } \ No newline at end of file