Add admin accounts and streamlined header UI

This commit is contained in:
2026-01-29 01:14:53 +01:00
parent 81f688cf88
commit 60191a1fe3
16 changed files with 311 additions and 110 deletions

View File

@@ -14,7 +14,7 @@ public static class AuthEndpoints
{
var group = app.MapGroup("/api/auth");
group.MapPost("/register", async ([FromBody] RegisterRequest request, HttpContext ctx, AppDbContext db) =>
group.MapPost("/register", async ([FromBody] RegisterRequest request, HttpContext ctx, AppDbContext db, IConfiguration config) =>
{
var username = request.Username?.Trim();
if (string.IsNullOrWhiteSpace(username) || username.Length > 64)
@@ -24,6 +24,8 @@ public static class AuthEndpoints
return Results.BadRequest(new { error = "Password is required." });
var displayName = EndpointHelpers.TrimTo(request.DisplayName, 64);
if (string.IsNullOrWhiteSpace(displayName))
return Results.BadRequest(new { error = "Display name is required." });
var normalized = username.ToLowerInvariant();
var exists = await db.Players.AnyAsync(p => p.NormalizedUsername == normalized);
@@ -31,6 +33,10 @@ public static class AuthEndpoints
return Results.Conflict(new { error = "Username already taken." });
var (hash, salt) = PasswordHasher.HashPassword(request.Password);
var adminKey = EndpointHelpers.TrimTo(request.AdminKey, 128);
var expectedAdminKey = config["ADMIN_PASSWORD"];
var isAdmin = !string.IsNullOrWhiteSpace(expectedAdminKey) && adminKey == expectedAdminKey;
var player = new Player
{
Id = Guid.NewGuid(),
@@ -39,6 +45,7 @@ public static class AuthEndpoints
PasswordHash = hash,
PasswordSalt = salt,
DisplayName = displayName,
IsAdmin = isAdmin,
CreatedAt = DateTimeOffset.UtcNow,
LastLoginAt = DateTimeOffset.UtcNow
};
@@ -48,7 +55,7 @@ public static class AuthEndpoints
PlayerIdentityExtensions.IssuePlayerCookie(ctx, player.Id);
return Results.Ok(new { player.Id, player.Username, player.DisplayName });
return Results.Ok(new { player.Id, player.Username, player.DisplayName, player.IsAdmin });
});
group.MapPost("/login", async ([FromBody] LoginRequest request, HttpContext ctx, AppDbContext db) =>
@@ -62,12 +69,16 @@ public static class AuthEndpoints
if (player == null || !PasswordHasher.Verify(request.Password, player.PasswordHash, player.PasswordSalt))
return Results.Json(new { error = "Invalid username or password." }, statusCode: StatusCodes.Status401Unauthorized);
if (string.IsNullOrWhiteSpace(player.DisplayName))
{
player.DisplayName = player.Username;
}
player.LastLoginAt = DateTimeOffset.UtcNow;
await db.SaveChangesAsync();
PlayerIdentityExtensions.IssuePlayerCookie(ctx, player.Id);
return Results.Ok(new { player.Id, player.Username, player.DisplayName });
return Results.Ok(new { player.Id, player.Username, player.DisplayName, player.IsAdmin });
});
group.MapPost("/logout", (HttpContext ctx) =>