diff options
Diffstat (limited to 'src/server/Startup.cs')
| -rw-r--r-- | src/server/Startup.cs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/server/Startup.cs b/src/server/Startup.cs new file mode 100644 index 0000000..8fd6955 --- /dev/null +++ b/src/server/Startup.cs @@ -0,0 +1,131 @@ +using System.Reflection; + +namespace IOL.BookmarkThing.Server; + +public class Startup +{ + public Startup(IConfiguration configuration, IWebHostEnvironment webHostEnvironment) { + Configuration = configuration; + WebHostEnvironment = webHostEnvironment; + } + + private IWebHostEnvironment WebHostEnvironment { get; } + private IConfiguration Configuration { get; } + + private string AppDatabaseConnectionString() { + var host = Configuration.GetValue<string>("DB_HOST"); + var port = Configuration.GetValue<string>("DB_PORT"); + var database = Configuration.GetValue<string>("DB_NAME"); + var user = Configuration.GetValue<string>("DB_USER"); + var password = Configuration.GetValue<string>("DB_PASSWORD"); + return $"Server={host};Port={port};Database={database};User Id={user};Password={password}"; + } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) { + services.AddDataProtection() + .PersistKeysToFileSystem(new(AppPaths.DataProtectionKeys.HostPath)); + + if (WebHostEnvironment.IsDevelopment()) { + services.AddCors(); + } + + services.Configure(AppJsonSettings.Default); + + services.AddDbContext<AppDbContext>(options => { + options.UseNpgsql(AppDatabaseConnectionString(), + builder => { + builder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); + builder.EnableRetryOnFailure(5, TimeSpan.FromSeconds(10), default); + }) + .UseSnakeCaseNamingConvention(); + if (WebHostEnvironment.IsDevelopment()) { + options.EnableSensitiveDataLogging(); + } + }); + + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie(options => { + options.Cookie.Name = "bookmarkthing_session"; + options.Cookie.SameSite = SameSiteMode.Strict; + options.Cookie.HttpOnly = true; + options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; + options.Cookie.IsEssential = true; + options.SlidingExpiration = true; + options.Events.OnRedirectToAccessDenied = + options.Events.OnRedirectToLogin = c => { + c.Response.StatusCode = StatusCodes.Status401Unauthorized; + return Task.FromResult<object>(null); + }; + }) + .AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>(Constants.BASIC_AUTH_SCHEME, default); + + services.AddLogging(); + services.AddHttpClient(); + services.AddControllers() + .AddJsonOptions(AppJsonSettings.Default); + + services.AddApiVersioning(options => { + options.ApiVersionReader = new UrlSegmentApiVersionReader(); + options.ReportApiVersions = true; + options.AssumeDefaultVersionWhenUnspecified = false; + }); + services.AddVersionedApiExplorer(options => { + options.SubstituteApiVersionInUrl = true; + }); + services.AddSwaggerGen(options => { + options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, Assembly.GetExecutingAssembly().GetName().Name + ".xml")); + options.UseApiEndpoints(); + options.OperationFilter<SwaggerDefaultValues>(); + options.SwaggerDoc(ApiSpecV1.Document.VersionName, ApiSpecV1.Document.OpenApiInfo); + options.AddSecurityDefinition("Basic", + new OpenApiSecurityScheme { + Name = "Authorization", + Type = SecuritySchemeType.ApiKey, + Scheme = "Basic", + BearerFormat = "Custom", + In = ParameterLocation.Header, + Description = + "Enter your token in the text input below.\r\n\r\nExample: \"12345abcdef\"", + }); + + options.AddSecurityRequirement(new OpenApiSecurityRequirement { + { + new OpenApiSecurityScheme { + Reference = new OpenApiReference { + Type = ReferenceType.SecurityScheme, + Id = "Basic" + } + }, + Array.Empty<string>() + } + }); + }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app) { + if (WebHostEnvironment.IsDevelopment()) { + app.UseDeveloperExceptionPage(); + app.UseCors(x => x + .AllowAnyMethod() + .AllowAnyHeader() + .SetIsOriginAllowed(_ => true) // allow any origin + .AllowCredentials()); // allow credentials + } + + app.UseRouting(); + app.UseSerilogRequestLogging(); + app.UseStatusCodePages(); + app.UseAuthentication(); + app.UseAuthorization(); + app.UseEndpoints(endpoints => { + endpoints.MapControllers(); + }); + app.UseSwagger(); + app.UseSwaggerUI(options => { + options.SwaggerEndpoint(ApiSpecV1.Document.SwaggerPath, ApiSpecV1.Document.VersionName); + options.DocumentTitle = Constants.API_NAME; + }); + } +} |
