feat: complete mealplanner app (backend + frontend + deployment)
.NET 8 backend with Zitadel JWT auth, TheMealDB integration, weekly meal plan generation, shopping list aggregation. Vue 3 + Tailwind 4 frontend with dark emerald theme, manual OIDC PKCE auth, all views implemented. Multi-stage Dockerfile with nginx reverse proxy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
70
backend/Program.cs
Normal file
70
backend/Program.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MealPlanner.Data;
|
||||
using MealPlanner.Services;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddControllers()
|
||||
.AddJsonOptions(o =>
|
||||
{
|
||||
o.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles;
|
||||
o.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
|
||||
});
|
||||
|
||||
builder.Services.AddDbContext<AppDbContext>(options =>
|
||||
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
|
||||
|
||||
// Zitadel JWT Bearer Auth
|
||||
builder.Services.AddAuthentication("Bearer")
|
||||
.AddJwtBearer("Bearer", options =>
|
||||
{
|
||||
options.Authority = builder.Configuration["Zitadel:Issuer"] ?? "https://auth.kuns.dev";
|
||||
options.Audience = builder.Configuration["Zitadel:ClientId"] ?? "";
|
||||
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = true,
|
||||
ValidateAudience = false, // Zitadel uses client_id as audience in some configs
|
||||
ValidateLifetime = true,
|
||||
NameClaimType = "sub",
|
||||
};
|
||||
});
|
||||
builder.Services.AddAuthorization();
|
||||
|
||||
builder.Services.AddHttpClient<TheMealDbClient>();
|
||||
builder.Services.AddScoped<RecipeService>();
|
||||
builder.Services.AddScoped<MealPlanService>();
|
||||
builder.Services.AddScoped<ShoppingListService>();
|
||||
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
var allowedOrigin = builder.Configuration["AllowedOrigin"] ?? "https://essen.kuns.dev";
|
||||
builder.Services.AddCors(options =>
|
||||
options.AddDefaultPolicy(policy =>
|
||||
policy.WithOrigins(allowedOrigin, "http://localhost:5173")
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials()));
|
||||
|
||||
builder.Services.AddHealthChecks();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
db.Database.Migrate();
|
||||
}
|
||||
|
||||
app.UseCors();
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
app.MapControllers();
|
||||
app.MapHealthChecks("/health");
|
||||
app.UseStaticFiles();
|
||||
app.Run();
|
||||
Reference in New Issue
Block a user