namespace Coupon.API.Extensions { using System; using System.Collections.Generic; using Autofac; using Coupon.API.Dtos; using Coupon.API.Filters; using Coupon.API.Infrastructure.Models; using Coupon.API.Infrastructure.Repositories; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.ServiceBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using RabbitMQ.Client; public static class IServiceCollectionExtensions { public static IServiceCollection AddCouponRegister(this IServiceCollection services, IConfiguration configuration) { services.AddTransient() .AddTransient(service => { var connection = new ServiceBusConnectionStringBuilder(configuration["EventBusConnection"]); return new DefaultServiceBusPersisterConnection(connection, service.GetService>()); }) .AddTransient(service => { var factory = new ConnectionFactory() { HostName = configuration["EventBusConnection"], DispatchConsumersAsync = true }; var retryCount = 5; if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) { retryCount = int.Parse(configuration["EventBusRetryCount"]); } return new DefaultRabbitMQPersistentConnection(factory, service.GetService>(), retryCount); }) .AddTransient() .AddTransient() .AddTransient, Mapper>(); return services; } public static IServiceCollection AddSwagger(this IServiceCollection services, IConfiguration configuration) { services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "eShopOnContainers - Coupon HTTP API", Version = "v1", Description = "The Coupon Service HTTP API" }); options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows() { Implicit = new OpenApiOAuthFlow() { AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"), Scopes = new Dictionary() { { "coupon", "Coupon API" } } } } }); options.OperationFilter(); }); return services; } public static IServiceCollection AddCustomSettings(this IServiceCollection services, IConfiguration configuration) { services.Configure(configuration); services.Configure(options => { options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState) { Instance = context.HttpContext.Request.Path, Status = StatusCodes.Status400BadRequest, Detail = "Please refer to the errors property for additional details." }; return new BadRequestObjectResult(problemDetails) { ContentTypes = { "application/problem+json", "application/problem+xml" } }; }; }); return services; } public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) { var subscriptionClientName = configuration["SubscriptionClientName"]; if (configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => { var serviceBusPersisterConnection = sp.GetRequiredService(); var iLifetimeScope = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); return new EventBusServiceBus(serviceBusPersisterConnection, logger, eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); }); } else { services.AddSingleton(sp => { var rabbitMQPersistentConnection = sp.GetRequiredService(); var iLifetimeScope = 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, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); }); } return services; } public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) { var accountName = configuration.GetValue("AzureStorageAccountName"); var accountKey = configuration.GetValue("AzureStorageAccountKey"); var hcBuilder = services.AddHealthChecks(); hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()) .AddMongoDb( configuration["ConnectionString"], name: "CouponCollection-check", tags: new string[] { "couponcollection" }); if (configuration.GetValue("AzureServiceBusEnabled")) { hcBuilder.AddAzureServiceBusTopic( configuration["EventBusConnection"], topicName: "eshop_event_bus", name: "coupon-servicebus-check", tags: new string[] { "servicebus" }); } else { hcBuilder.AddRabbitMQ( $"amqp://{configuration["EventBusConnection"]}", name: "coupon-rabbitmqbus-check", tags: new string[] { "rabbitmqbus" }); } return services; } public static IServiceCollection AddCustomPolicies(this IServiceCollection services) { services.AddCors(options => { options.AddPolicy("CorsPolicy", builder => builder.SetIsOriginAllowed((host) => true) .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials()); }); return services; } public static IServiceCollection AddAppInsights(this IServiceCollection services, IConfiguration configuration) { services.AddApplicationInsightsTelemetry(configuration); services.AddApplicationInsightsKubernetesEnricher(); return services; } public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) { return services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(options => { options.Authority = configuration["IdentityUrl"]; options.RequireHttpsMetadata = false; options.Audience = "coupon"; }).Services; } public static IServiceCollection AddCustomAuthorization(this IServiceCollection services) => services.AddAuthorization(); } }