using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Sqlite; using Microsoft.IdentityModel.Tokens; using Watcher.Data; using Watcher.Models; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); // HttpContentAccessor builder.Services.AddHttpContextAccessor(); // ---------- Konfiguration ---------- DotNetEnv.Env.Load(); builder.Configuration .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddEnvironmentVariables(); // Konfiguration laden var configuration = builder.Configuration; // ---------- DB-Kontext ---------- var dbProvider = configuration["Database:Provider"] ?? "MySQL"; var connectionString = configuration["Database:ConnectionString"]; builder.Services.AddDbContext((serviceProvider, options) => { var config = serviceProvider.GetRequiredService(); var provider = dbProvider; if (provider == "MySql") { var connStr = config.GetConnectionString("MySql") ?? config["Database:ConnectionStrings:MySql"]; options.UseMySql(connStr, ServerVersion.AutoDetect(connStr)); } else if (provider == "Sqlite") { var connStr = config.GetConnectionString("Sqlite") ?? config["Database:ConnectionStrings:Sqlite"]; options.UseSqlite(connStr); } else { throw new Exception("Unsupported database provider configured."); } }); // ---------- Authentifizierung konfigurieren ---------- // PocketID nur konfigurieren, wenn aktiviert var pocketIdSection = builder.Configuration.GetSection("Authentication:PocketID"); var pocketIdEnabled = pocketIdSection.GetValue("Enabled"); var auth = builder.Services.AddAuthentication("Cookies"); auth.AddCookie("Cookies", options => { options.LoginPath = "/Auth/Login"; options.AccessDeniedPath = "/Auth/AccessDenied"; }); builder.Services.AddAuthentication() .AddOpenIdConnect("oidc", options => { options.Authority = pocketIdSection["Authority"]; options.ClientId = pocketIdSection["ClientId"]; options.ClientSecret = pocketIdSection["ClientSecret"]; options.ResponseType = "code"; options.CallbackPath = pocketIdSection["CallbackPath"]; options.SaveTokens = true; options.GetClaimsFromUserInfoEndpoint = true; options.Scope.Clear(); options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("email"); options.Events = new OpenIdConnectEvents { OnTokenValidated = async ctx => { var db = ctx.HttpContext.RequestServices.GetRequiredService(); var principal = ctx.Principal; var pocketId = principal.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value; var preferredUsername = principal.FindFirst("preferred_username")?.Value; var email = principal.FindFirst("email")?.Value; if (string.IsNullOrEmpty(pocketId)) return; var user = await db.Users.FirstOrDefaultAsync(u => u.OIDC_Id == pocketId); if (user == null) { user = new User { OIDC_Id = pocketId, Username = preferredUsername ?? "", Email = email, LastLogin = DateTime.UtcNow, IdentityProvider = "oidc", Password = string.Empty }; db.Users.Add(user); } else { user.LastLogin = DateTime.UtcNow; user.Username = preferredUsername ?? user.Username; user.Email = email ?? user.Email; db.Users.Update(user); } await db.SaveChangesAsync(); } }; }); var app = builder.Build(); // Migrationen anwenden (für SQLite oder andere DBs) using (var scope = app.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); db.Database.Migrate(); } // Standart-User in Datenbank schreiben using (var scope = app.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); Console.WriteLine("Checking for users..."); if (!db.Users.Any()) { Console.WriteLine("No users found, creating default user..."); var defaultUser = new User { OIDC_Id = string.Empty, Username = "admin", Email = string.Empty, LastLogin = DateTime.UtcNow, IdentityProvider = "local", Password = BCrypt.Net.BCrypt.HashPassword("changeme") }; db.Users.Add(defaultUser); db.SaveChanges(); Console.WriteLine("Default user created."); } else { Console.WriteLine("Users already exist."); } } // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); // 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.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseStaticFiles(); app.MapControllerRoute( name: "default", pattern: "{controller=Auth}/{action=Login}/" ); app.Run();