Files
budget/src/Budget.Api/Program.cs
T
Spencer Twaddle 45f921bb71 Phase 8: Polish and production readiness
- Add ErrorBoundary component wrapping the whole app
- Add ToastProvider with showError/showInfo; Income and Outgo pages use it for API errors
- Add LoadingSkeleton component with shimmer animation; Income and Outgo show it while loading
- Add confirm-on-delete dialogs for income and outgo rows
- Apply EF migrations automatically on startup via MigrateAsync()
- Add /healthz health check endpoint using DbContext check
- Add Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore package

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 08:03:05 -05:00

70 lines
2.2 KiB
C#

using Budget.Api.Data;
using Budget.Api.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
var connStr = builder.Configuration.GetConnectionString("DefaultConnection")
?? $"Host={builder.Configuration["POSTGRES_HOST"] ?? "localhost"};" +
$"Port={builder.Configuration["POSTGRES_PORT"] ?? "5432"};" +
$"Database={builder.Configuration["POSTGRES_DB"] ?? "budget"};" +
$"Username={builder.Configuration["POSTGRES_USER"] ?? "budget"};" +
$"Password={builder.Configuration["POSTGRES_PASSWORD"] ?? "changeme"}";
builder.Services.AddDbContext<AppDbContext>(opt => opt.UseNpgsql(connStr));
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = builder.Configuration["AUTH__AUTHORITY"];
options.Audience = builder.Configuration["AUTH__AUDIENCE"];
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
};
});
builder.Services.AddAuthorization();
builder.Services.AddScoped<BudgetAuthorizationService>();
builder.Services.AddControllers();
builder.Services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
var app = builder.Build();
// Apply EF migrations automatically on startup
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await db.Database.MigrateAsync();
}
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.UseMiddleware<KnownUserMiddleware>();
app.MapControllers();
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable,
}
});
app.MapFallbackToFile("index.html");
app.Run();