using System.IO; using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.FeatureManagement; using Microsoft.OpenApi.Models; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json.Converters; using LCU.API.Internal.Operations.IncentiveApi.Configuration; using LCU.API.Internal.Operations.IncentiveApi.DataAccess; using LCU.API.Internal.Operations.IncentiveApiLib.Persistence; using LCU.API.Internal.Operations.IncentiveApi.Services; using LCU.API.Internal.Operations.IncentiveApi.Services.Action; using LCU.API.Internal.Operations.IncentiveApi.Services.Allied; using LCU.API.Internal.Operations.IncentiveApi.Authorization; using LCU.API.Internal.Operations.IncentiveApi.Consumers; using LCU.API.Internal.Operations.IncentiveApi.Services.AutoDecision; using LCU.API.Internal.Operations.IncentiveApi.Services.Dayforce; using LCU.API.Internal.Operations.IncentiveApi.Services.DispersalStrategy; using LCU.API.Internal.Operations.IncentiveApi.Services.DuplicateDetection; using LCU.API.Internal.Operations.IncentiveApi.Services.ExternalActivity; using LCU.API.Internal.Operations.IncentiveApi.Services.MicroApiServices; using LCU.API.Internal.Operations.IncentiveApi.Services.Payout; using LCU.API.Internal.Operations.IncentiveApi.Services.QueueServices; using LCU.API.Internal.Operations.IncentiveApi.Services.Rules; using LCU.API.Internal.Operations.IncentiveApi.Services.Temenos; using LCU.API.Internal.Operations.IncentiveApi.Services.Reporting; using LCU.API.Internal.Operations.IncentiveApi.Services.DnaActivityServices; using LCU.API.Internal.Operations.IncentiveApiLib.Services; using LCU.API.Internal.Operations.IncentiveApiLib.Repositories; using LCU.Library.Internal.LcuHttpClient; using IAuthorizationService = LCU.API.Internal.Operations.IncentiveApi.Services.IAuthorizationService; using LCU.Library.Internal.LcuMassTransit; using LCU.Library.Internal.LcuMassTransitModels; using LCU.Library.Internal.Logging.Models; using LCU.Library.Internal.Logging; using LCU.Library.Internal.Logging.Middleware; using LCU.Library.Internal.Status; using LCU.API.Internal.Operations.IncentiveApi.Services.IncentiveProcesses; using LCU.Library.Internal.LCUServiceFactory.Configurations; using LCU.Library.Internal.Configuration; using LCU.Library.Internal.LCUServiceFactory; using LCU.API.Internal.Operations.IncentiveApi.DnaActivityServices; using LCU.API.Internal.Operations.IncentiveApi.HostedServices; using LCU.API.Internal.Operations.IncentiveApi.Services.NightlyIncentiveProcesses; using LCU.API.Internal.Operations.IncentiveApi.Services.NightlyDecisionServices; using LCU.Library.Internal.Security; using MassTransit; string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; ApiConfiguration _apiConfiguration; var builder = BuildBuilder(args); BuildServicesAndConfigurations(builder); BuildAppAndRun(builder); WebApplicationBuilder BuildBuilder(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Configuration.AddJsonFile("/app/config/mapped-appsettings/primary.json", true, true); builder.Configuration.AddJsonFile("/vault/secrets/incentive-manager-api-mass-queue-password.json", optional: true, reloadOnChange: true); builder.Configuration.AddJsonFile("/vault/secrets/incentive-manager-api-mass-queue-username.json", optional: true, reloadOnChange: true); builder.Configuration.AddJsonFile("/vault/secrets/incentive-manager-api-dayforce-username.json", optional: true, reloadOnChange: true); builder.Configuration.AddJsonFile("/vault/secrets/incentive-manager-api-dayforce-password.json", optional: true, reloadOnChange: true); builder.Configuration.AddJsonFile("/vault/secrets/incentive-manager-api-seq-api-key.json", optional: true, reloadOnChange: true); builder.Configuration.AddJsonFile("/vault/secrets/incentive-manager-api-db-connection.json", optional: true, reloadOnChange: true); builder.Configuration.AddJsonFile("/vault/secrets/incentive-manager-api-azure-valid-audience.json", optional: true, reloadOnChange: true); builder.Configuration.AddJsonFile("/vault/secrets/incentive-manager-api-azure-client-id.json", optional: true, reloadOnChange: true); builder.Configuration.AddJsonFile("/vault/secrets/incentive-manager-api-azure-tenant-id.json", optional: true, reloadOnChange: true); builder.Host.UseSerilog(); return builder; } void BuildServicesAndConfigurations(WebApplicationBuilder builder) { var services = builder.Services; var configuration = builder.Configuration; _apiConfiguration = configuration.Bind(services, "Primary"); configuration.Bind(services); configuration.Bind(services); configuration.Bind(services); configuration.Bind(services); configuration.Bind(services); configuration.Bind(services); var servicesFactoryConfiguration = configuration.Bind(services); var loggerConfiguration = new LoggingConfiguration(_apiConfiguration.AppName, _apiConfiguration.SeqKey, _apiConfiguration.SeqUrl); var lcuLogging = new LcuLogging(loggerConfiguration); lcuLogging.UseLcuLogging(); services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddAzureAdBearer(options => configuration.Bind("AzureActiveDirectory", options)); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = _apiConfiguration.AppName, Version = "v1" }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, new List() } }); c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme.", Type = SecuritySchemeType.Http, Scheme = "bearer" }); var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); }); services.AddFeatureManagement(configuration.GetSection("Primary:FeatureGates")); services.AddScoped(); services.AddTransient(); services.AddSingleton(); services.AddScoped(); services.AddCors(options => { options.AddPolicy(MyAllowSpecificOrigins, builder => { builder.WithOrigins( _apiConfiguration.CorsAllowedOrigins ).AllowAnyHeader().AllowAnyMethod().AllowCredentials(); }); }); services.AddScoped(provider => provider.GetService()); var sqlConnectionConfiguration = configuration.Bind(services); services.AddDbContext(options => { options.UseSqlServer ( sqlConnectionConfiguration.ConnectionString, sql => sql.EnableRetryOnFailure(sqlConnectionConfiguration.MaxRetryCount, sqlConnectionConfiguration.MaxRetryDelay, null) ); }); var connectionConfiguration = MassTransitConfigurationSetUp.AddConnectionConfiguration(ref services, configuration); var receiveEndpointConfigurations = new ReceiveEndpointConfigurations { ImportCreditCardSalesEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "ImportCreditCardSalesEndpoint"), ImportIndirectVehicleSalesEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "ImportIndirectVehicleSalesEndpoint"), ReportingProcessEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "ReportingProcessEndpoint"), GoalDispersalProcessEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "GoalDispersalProcessEndpoint"), PayoutIncentiveProcessEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "PayoutIncentiveProcessEndpoint"), DayforceSyncProcessEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "DayforceSyncProcessEndpoint"), ActionCreditCardProcessEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "ActionCreditCardProcessEndpoint"), ActionVehicleProcessEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "ActionVehicleProcessEndpoint"), GapMbpProcessEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "GapMbpProcessEndpoint"), IncentiveProcessesEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "IncentiveProcessesEndpoint"), NightlyIncentiveProcessesEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "NightlyIncentiveProcessesEndpoint") }; services.AddSingleton(receiveEndpointConfigurations); AddMassTransitServices(ref services, connectionConfiguration, receiveEndpointConfigurations, _apiConfiguration); AddApiServices(services); AddDataAccess(services); AddApiRepositories(services); services.AddHttpContextAccessor(); services.AddLCUStatusServicesWithApiHealthCheck(configuration); services.AddLCUHttpServices(); services.AddLCUServiceFactoryAndValidateServiceRegistration(servicesFactoryConfiguration); services.AddLCUServiceFactoryAndValidateServiceRegistration(servicesFactoryConfiguration); services.Configure(options => { options.SuppressModelStateInvalidFilter = true; }); services.AddControllers().AddNewtonsoftJson(options => { options.SerializerSettings.Converters.Add(new StringEnumConverter()); options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; }); services.AddEndpointsApiExplorer(); } void AddMassTransitServices(ref IServiceCollection services, ConnectionConfiguration connectionConfiguration, ReceiveEndpointConfigurations receiveEndpointConfigurations, ApiConfiguration configuration) { services.AddMassTransit(x => { x.AddConsumer(); x.AddConsumer(); x.AddConsumer(); x.AddConsumer(); x.AddConsumer(); x.AddConsumer(); x.AddConsumer(); x.AddConsumer(); x.AddConsumer(); x.AddConsumer(); x.AddConsumer(); x.UsingRabbitMq((context, cfg) => { cfg.Host(connectionConfiguration.HostUrl, "/", host => { host.Username(connectionConfiguration.UserName); host.Password(connectionConfiguration.Password); }); if (configuration.FeatureFlags.RunImportCreditCardSalesConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.ImportCreditCardSalesEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.ImportCreditCardSalesEndpoint.PrefetchLimit; }); } if (configuration.FeatureFlags.RunImportIndirectVehicleSalesConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.ImportIndirectVehicleSalesEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.ImportIndirectVehicleSalesEndpoint.PrefetchLimit; }); } if (configuration.FeatureFlags.RunReportingProcessConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.ReportingProcessEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.ReportingProcessEndpoint.PrefetchLimit; }); } if (configuration.FeatureFlags.RunGoalDispersalProcessConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.GoalDispersalProcessEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.GoalDispersalProcessEndpoint.PrefetchLimit; }); } if (configuration.FeatureFlags.RunPayoutIncentiveProcessConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.PayoutIncentiveProcessEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.PayoutIncentiveProcessEndpoint.PrefetchLimit; }); } if (configuration.FeatureFlags.RunDayforceSyncProcessConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.DayforceSyncProcessEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.DayforceSyncProcessEndpoint.PrefetchLimit; }); } if (configuration.FeatureFlags.RunGapMbpProcessConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.GapMbpProcessEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.GapMbpProcessEndpoint.PrefetchLimit; }); } if (configuration.FeatureFlags.RunActionCreditCardProcessConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.ActionCreditCardProcessEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.ActionCreditCardProcessEndpoint.PrefetchLimit; }); } if (configuration.FeatureFlags.RunActionVehicleProcessConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.ActionVehicleProcessEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.ActionVehicleProcessEndpoint.PrefetchLimit; }); } if (configuration.FeatureFlags.RunIncentiveProcessesConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.IncentiveProcessesEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.IncentiveProcessesEndpoint.PrefetchLimit; }); } if (configuration.FeatureFlags.RunNightlyIncentiveProcessesConsumer) { cfg.ReceiveEndpoint(receiveEndpointConfigurations.NightlyIncentiveProcessesEndpoint.ReceiveEndpoint, e => { e.ConfigureConsumer(context); e.SetQuorumQueue(); e.PrefetchCount = receiveEndpointConfigurations.NightlyIncentiveProcessesEndpoint.PrefetchLimit; }); } }); }); services.AddMassTransitHostedService(); } void AddApiServices(IServiceCollection services) { services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); AddQueueServices(services); AddMicroServices(services); AddSyncServices(services); AddNightlyServices(services); AddStrategyServices(services); AddHostedServices(services); } void AddQueueServices(IServiceCollection services) { services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); } void AddSyncServices(IServiceCollection services) { services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); } void AddNightlyServices(IServiceCollection services) { services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); } void AddApiRepositories(IServiceCollection services) { services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); } void AddDataAccess(IServiceCollection services) { services.AddScoped(); services.AddScoped(); services.AddScoped(); } void AddMicroServices(IServiceCollection services) { services.AddScoped(); services.AddScoped(); services.AddScoped(); } void AddHostedServices(IServiceCollection services) { services.AddSingleton(); } void AddStrategyServices(IServiceCollection services) { services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); } void BuildAppAndRun(WebApplicationBuilder builder) { var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } if (_apiConfiguration.FeatureFlags.RunApplicationDbIntegrityHostedService) { var service = app.Services.GetRequiredService(); service.StartAsync().Wait(); } app.UseSwagger(c => { c.PreSerializeFilters.Add((swaggerDoc, request) => { const string prefixHeader = "X-Forwarded-Prefix"; if (!request.Headers.ContainsKey(prefixHeader)) return; var serverUrl = request.Headers[prefixHeader]; swaggerDoc.Servers = new List() { new() { Description = serverUrl, Url = serverUrl } }; }); }); app.UseSwaggerUI(c => { c.RoutePrefix = "swagger"; c.SwaggerEndpoint("v1/swagger.json", "LCU.API.Internal.Operations.IncentiveApi v1"); }); app.UseMiddleware(); app.UseSerilogRequestLogging(options => { options.EnrichDiagnosticContext = RequestResponseLoggingMiddleware.RequestDataParser.EnrichFromRequest; }); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseCors(MyAllowSpecificOrigins); app.UseHttpsRedirection(); app.MapControllers(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.Run(); }