using System.Globalization; using Bit.Admin.IdentityServer; using Bit.Core.Context; using Bit.Core.Settings; using Bit.Core.Utilities; using Bit.SharedWeb.Utilities; using Microsoft.AspNetCore.Identity; using Stripe; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.Extensions.DependencyInjection.Extensions; using Bit.Admin.Services; using Bit.Core.Billing.Extensions; using Bit.Core.Billing.Migration; #if !OSS using Bit.Commercial.Core.Utilities; using Bit.Commercial.Infrastructure.EntityFramework.SecretsManager; #endif namespace Bit.Admin; public class Startup { public Startup(IWebHostEnvironment env, IConfiguration configuration) { CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); Configuration = configuration; Environment = env; } public IConfiguration Configuration { get; private set; } public IWebHostEnvironment Environment { get; set; } public void ConfigureServices(IServiceCollection services) { // Options services.AddOptions(); // Settings var globalSettings = services.AddGlobalSettingsServices(Configuration, Environment); services.Configure(Configuration.GetSection("AdminSettings")); // Data Protection services.AddCustomDataProtectionServices(Environment, globalSettings); // Stripe Billing StripeConfiguration.ApiKey = globalSettings.Stripe.ApiKey; StripeConfiguration.MaxNetworkRetries = globalSettings.Stripe.MaxNetworkRetries; // Repositories var databaseProvider = services.AddDatabaseRepositories(globalSettings); switch (databaseProvider) { case Core.Enums.SupportedDatabaseProviders.SqlServer: services.AddSingleton(); break; case Core.Enums.SupportedDatabaseProviders.MySql: services.AddSingleton(); break; case Core.Enums.SupportedDatabaseProviders.Postgres: services.AddSingleton(); break; case Core.Enums.SupportedDatabaseProviders.Sqlite: services.AddSingleton(); break; default: break; } // Context services.AddScoped(); services.TryAddSingleton(); // Identity services.AddPasswordlessIdentityServices(globalSettings); services.Configure(options => { options.ValidationInterval = TimeSpan.FromMinutes(5); }); if (globalSettings.SelfHosted) { services.ConfigureApplicationCookie(options => { options.Cookie.Path = "/admin"; }); } // Services services.AddBaseServices(globalSettings); services.AddDefaultServices(globalSettings); services.AddScoped(); services.AddDistributedCache(globalSettings); services.AddBillingOperations(); services.AddHttpClient(); services.AddProviderMigration(); #if OSS services.AddOosServices(); #else services.AddCommercialCoreServices(); services.AddSecretsManagerEfRepositories(); #endif // Mvc services.AddMvc(config => { config.Filters.Add(new LoggingExceptionHandlerFilterAttribute()); }); services.Configure(options => options.LowercaseUrls = true); services.Configure(o => { o.ViewLocationFormats.Add("/Auth/Views/{1}/{0}.cshtml"); o.ViewLocationFormats.Add("/AdminConsole/Views/{1}/{0}.cshtml"); o.ViewLocationFormats.Add("/Billing/Views/{1}/{0}.cshtml"); }); // Jobs service Jobs.JobsHostedService.AddJobsServices(services, globalSettings.SelfHosted); services.AddHostedService(); if (globalSettings.SelfHosted) { services.AddHostedService(); } else { if (CoreHelpers.SettingHasValue(globalSettings.Mail.ConnectionString)) { services.AddHostedService(); } } } public void Configure( IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime appLifetime, GlobalSettings globalSettings) { app.UseSerilog(env, appLifetime, globalSettings); // Add general security headers app.UseMiddleware(); if (globalSettings.SelfHosted) { app.UsePathBase("/admin"); app.UseForwardedHeaders(globalSettings); } if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/error"); } app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); } }