using System.Text.Json; using Gott.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; namespace Gott.Endpoints; public static class AuthEndpoint { public static void MapAuthEndpoints(this WebApplication app) { app.MapPost("/api/auth/login", HandleLogin); app.MapPost("/api/auth/logout", HandleLogout); app.MapGet("/api/auth/me", HandleMe); } private static async System.Threading.Tasks.Task HandleLogin(HttpContext ctx, DatabaseService db, AuthService auth) { var body = await JsonSerializer.DeserializeAsync(ctx.Request.Body); var username = body.TryGetProperty("username", out var u) ? u.GetString() : null; var password = body.TryGetProperty("password", out var p) ? p.GetString() : null; if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsJsonAsync(new { error = "Username and password required" }); return; } var user = await db.GetUserByUsername(username); if (user == null || !auth.VerifyPassword(password, user.PasswordHash)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsJsonAsync(new { error = "Invalid credentials" }); return; } var token = auth.CreateToken(user.UserId); ctx.Response.Cookies.Append("gott_token", token, new CookieOptions { HttpOnly = true, SameSite = SameSiteMode.Strict, Path = "/", MaxAge = System.TimeSpan.FromDays(365) }); await ctx.Response.WriteAsJsonAsync(new { userId = user.UserId, username = user.Username, displayName = user.DisplayName, isAdmin = user.IsAdmin }); } private static async System.Threading.Tasks.Task HandleLogout(HttpContext ctx, AuthService auth) { var token = ctx.Request.Cookies["gott_token"]; auth.RevokeToken(token); ctx.Response.Cookies.Delete("gott_token", new CookieOptions { Path = "/" }); await ctx.Response.WriteAsJsonAsync(new { ok = true }); } private static async System.Threading.Tasks.Task HandleMe(HttpContext ctx, DatabaseService db, AuthService auth) { var token = ctx.Request.Cookies["gott_token"]; var userId = auth.ValidateToken(token); if (userId == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsJsonAsync(new { error = "Not authenticated" }); return; } var user = await db.GetUser(userId); if (user == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsJsonAsync(new { error = "User not found" }); return; } await ctx.Response.WriteAsJsonAsync(new { userId = user.UserId, username = user.Username, displayName = user.DisplayName, isAdmin = user.IsAdmin }); } }