using System; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Gott.Extensions; using Gott.Models; using Gott.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; namespace Gott.Endpoints; public static class ApiKeysEndpoint { public static void MapApiKeysEndpoints(this WebApplication app) { app.MapGet("/api/admin/api-keys", HandleGetAll); app.MapPost("/api/admin/api-keys", HandleCreate); app.MapPut("/api/admin/api-keys/{keyId}", HandleUpdate); app.MapPut("/api/admin/api-keys/{keyId}/activate", HandleActivate); app.MapPut("/api/admin/api-keys/{keyId}/deactivate", HandleDeactivate); app.MapDelete("/api/admin/api-keys/{keyId}", HandleDelete); } private static async Task HandleGetAll(HttpContext ctx, DatabaseService db) { if (!ctx.IsAdmin()) { ctx.Response.StatusCode = 403; return; } var keys = await db.GetApiKeys(); var result = keys.Select(k => new { k.KeyId, k.Provider, k.Name, k.ApiKey, k.IsActive, k.CreatedAt, k.UpdatedAt }); await ctx.Response.WriteAsJsonAsync(result); } private static async Task HandleCreate(HttpContext ctx, DatabaseService db) { if (!ctx.IsAdmin()) { ctx.Response.StatusCode = 403; return; } var body = await JsonSerializer.DeserializeAsync(ctx.Request.Body); var provider = body.GetProperty("provider").GetString()?.Trim().ToLower() ?? ""; var name = body.GetProperty("name").GetString()?.Trim() ?? ""; var apiKey = body.GetProperty("apiKey").GetString()?.Trim() ?? ""; if (string.IsNullOrWhiteSpace(provider) || string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(apiKey)) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsJsonAsync(new { error = "Provider, Name und API-Key sind erforderlich" }); return; } var now = DateTime.UtcNow.ToString("o"); var record = new ApiKeyRecord { KeyId = Guid.NewGuid().ToString("N"), Provider = provider, Name = name, ApiKey = apiKey, IsActive = false, CreatedAt = now, UpdatedAt = now }; await db.CreateApiKey(record); await ctx.Response.WriteAsJsonAsync(new { record.KeyId, record.Provider, record.Name, record.ApiKey, record.IsActive, record.CreatedAt }); } private static async Task HandleUpdate(HttpContext ctx, DatabaseService db, AnthropicService anthropic, string keyId) { if (!ctx.IsAdmin()) { ctx.Response.StatusCode = 403; return; } var existing = await db.GetApiKey(keyId); if (existing == null) { ctx.Response.StatusCode = 404; await ctx.Response.WriteAsJsonAsync(new { error = "Key nicht gefunden" }); return; } var body = await JsonSerializer.DeserializeAsync(ctx.Request.Body); var name = body.TryGetProperty("name", out var n) ? n.GetString()?.Trim() : null; var apiKey = body.TryGetProperty("apiKey", out var k) ? k.GetString()?.Trim() : null; if (string.IsNullOrWhiteSpace(name)) name = existing.Name; await db.UpdateApiKey(keyId, name, apiKey); // Wenn aktiver Key geändert wird → Token im Service aktualisieren if (existing.IsActive && existing.Provider == "anthropic" && !string.IsNullOrWhiteSpace(apiKey)) anthropic.UpdateToken(apiKey); await ctx.Response.WriteAsJsonAsync(new { ok = true }); } private static async Task HandleActivate(HttpContext ctx, DatabaseService db, AnthropicService anthropic, string keyId) { if (!ctx.IsAdmin()) { ctx.Response.StatusCode = 403; return; } var existing = await db.GetApiKey(keyId); if (existing == null) { ctx.Response.StatusCode = 404; await ctx.Response.WriteAsJsonAsync(new { error = "Key nicht gefunden" }); return; } await db.SetActiveApiKey(keyId, existing.Provider); // Token im laufenden Service aktualisieren if (existing.Provider == "anthropic") anthropic.UpdateToken(existing.ApiKey); await ctx.Response.WriteAsJsonAsync(new { ok = true }); } private static async Task HandleDeactivate(HttpContext ctx, DatabaseService db, AnthropicService anthropic, string keyId) { if (!ctx.IsAdmin()) { ctx.Response.StatusCode = 403; return; } var existing = await db.GetApiKey(keyId); if (existing == null) { ctx.Response.StatusCode = 404; await ctx.Response.WriteAsJsonAsync(new { error = "Key nicht gefunden" }); return; } await db.DeactivateApiKey(keyId); // Token im laufenden Service leeren if (existing.Provider == "anthropic") anthropic.UpdateToken(""); await ctx.Response.WriteAsJsonAsync(new { ok = true }); } private static async Task HandleDelete(HttpContext ctx, DatabaseService db, AnthropicService anthropic, string keyId) { if (!ctx.IsAdmin()) { ctx.Response.StatusCode = 403; return; } var existing = await db.GetApiKey(keyId); if (existing == null) { ctx.Response.StatusCode = 404; await ctx.Response.WriteAsJsonAsync(new { error = "Key nicht gefunden" }); return; } // Wenn aktiver Key gelöscht wird → Token leeren if (existing.IsActive && existing.Provider == "anthropic") anthropic.UpdateToken(""); await db.DeleteApiKey(keyId); await ctx.Response.WriteAsJsonAsync(new { ok = true }); } }