using GameList.Data; using GameList.Endpoints; using GameList.Infrastructure; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using System.Text.Json.Serialization; var builder = WebApplication.CreateBuilder(args); var dataDirectory = Path.Combine(builder.Environment.ContentRootPath, "App_Data"); Directory.CreateDirectory(dataDirectory); var dataProtectionDirectory = Path.Combine(dataDirectory, "keys"); Directory.CreateDirectory(dataProtectionDirectory); var configuredConnection = builder.Configuration.GetConnectionString("Default"); var dbPath = Path.Combine(dataDirectory, "gamelist.db"); var connectionBuilder = new SqliteConnectionStringBuilder(string.IsNullOrWhiteSpace(configuredConnection) ? $"Data Source={dbPath}" : configuredConnection); if (connectionBuilder.DataSource.Contains("App_Data", StringComparison.OrdinalIgnoreCase)) { var fileName = Path.GetFileName(connectionBuilder.DataSource); connectionBuilder.DataSource = Path.Combine(dataDirectory, fileName); } else if (!Path.IsPathRooted(connectionBuilder.DataSource)) { connectionBuilder.DataSource = Path.GetFullPath(connectionBuilder.DataSource, dataDirectory); } var connectionString = connectionBuilder.ToString(); builder.Services.AddDbContext(options => options.UseSqlite(connectionString)); builder.Services.ConfigureHttpJsonOptions(options => { options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); builder.Services.AddHttpClient(); builder.Services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(dataProtectionDirectory)); builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.Cookie.Name = PlayerIdentityExtensions.PlayerCookieName; options.Cookie.HttpOnly = true; options.Cookie.SameSite = SameSiteMode.Strict; options.Cookie.SecurePolicy = builder.Environment.IsDevelopment() ? CookieSecurePolicy.SameAsRequest : CookieSecurePolicy.Always; options.SlidingExpiration = true; options.ExpireTimeSpan = TimeSpan.FromDays(30); }); builder.Services.AddAuthorization(options => { options.AddPolicy(PlayerIdentityExtensions.AdminPolicy, policy => policy.RequireClaim(PlayerIdentityExtensions.AdminClaim, "true")); }); var app = builder.Build(); app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost }); var basePath = builder.Configuration["BasePath"]; if (!string.IsNullOrWhiteSpace(basePath)) { app.UsePathBase(basePath); } app.UseGlobalExceptionLogging(); app.UseAuthentication(); app.UseAuthorization(); // Ensure database and migrations are applied on startup using (var scope = app.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); db.Database.Migrate(); } app.UseDefaultFiles(); app.UseStaticFiles(); app.MapHealthChecks(); app.MapAuthEndpoints(); app.MapStateEndpoints(); app.MapSuggestEndpoints(); app.MapVoteEndpoints(); app.MapResultsEndpoints(); app.MapAdminEndpoints(); app.Run();