Files
chapter-organizer/WebApp/Program.cs
T

108 lines
3.2 KiB
C#

using Data;
using Microsoft.EntityFrameworkCore;
using MudBlazor.Services;
using WebApp;
using WebApp.Authentication;
using WebApp.Components;
var builder = WebApplication.CreateBuilder(args);
// Configure authentication secrets for production (Docker, etc.)
if (builder.Environment.IsProduction())
{
// Option 1: Load from volume-mounted secrets file
var secretsPath = "/app/secrets/auth-secrets.json";
if (File.Exists(secretsPath))
{
builder.Configuration.AddJsonFile(secretsPath, optional: false, reloadOnChange: true);
}
// Option 2: Environment variables with prefix
builder.Configuration.AddEnvironmentVariables(prefix: "TSA_");
}
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.AddMudServices();
// Configure SQLite
var connectionString = builder.Configuration.GetConnectionString("SQLiteDefault");
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlite(connectionString));
builder.Services.AddQuickGridEntityFrameworkAdapter();
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddScoped<ClipboardService>();
builder.Services.AddScoped<StateContainer>(); // Server-side
builder.Services.AddSingleton<StateContainer>();//Client-side
// Add authentication services
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<AuthenticationService>();
builder.Services.AddSingleton<LoginRateLimitService>();
builder.Services.AddHostedService<LoginRateLimitService>(sp => sp.GetRequiredService<LoginRateLimitService>());
// Add authentication options
builder.Services.AddAuthentication("Auth")
.AddCookie("Auth", options =>
{
options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
options.SlidingExpiration = true;
options.LoginPath = "/login";
// Enhanced security settings
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.Name = "TSA.Auth";
});
builder.Services.AddCascadingAuthenticationState();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
app.UseMigrationsEndPoint();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseStaticFiles();
app.UseAntiforgery();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
// Used for AuthController
app.MapControllerRoute("default", "{controller}/{action}");
// Development-only password hash generator endpoint
if (app.Environment.IsDevelopment())
{
app.MapGet("/dev/hash-password", (string password) =>
{
var hash = PasswordHashGenerator.GenerateHash(password);
return Results.Ok(new
{
password,
hash,
message = "Copy the hash value to your User Secrets configuration"
});
}).WithName("GeneratePasswordHash");
}
app.Run();