using System; using System.Collections.Generic; using System.IO; using System.Text.Json; using System.Text.Json.Nodes; using System.Threading.Tasks; using Gott.Extensions; using Gott.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; namespace Gott.Endpoints; public static class ServerSettingsEndpoint { public static void MapServerSettingsEndpoints(this WebApplication app) { app.MapGet("/api/admin/server-settings", HandleGet); app.MapPut("/api/admin/server-settings", HandleUpdate); } private static async Task HandleGet(HttpContext ctx, ServerSettingsService settings, IConfiguration config) { if (!ctx.IsAdmin()) { ctx.Response.StatusCode = 403; await ctx.Response.WriteAsJsonAsync(new { error = "Admin access required" }); return; } // Port aus appsettings (nicht DB) – als erstes Feld var port = config.GetValue("Port", 19000); var allSettings = new List { new { key = "Port", type = "int", value = (object)port, label = "Server-Port (erfordert Neustart)", inputType = "number", } }; allSettings.AddRange(settings.GetAll()); await ctx.Response.WriteAsJsonAsync(new { settings = allSettings }); } private static async Task HandleUpdate(HttpContext ctx, ServerSettingsService settings, IConfiguration config) { if (!ctx.IsAdmin()) { ctx.Response.StatusCode = 403; await ctx.Response.WriteAsJsonAsync(new { error = "Admin access required" }); return; } var body = await JsonSerializer.DeserializeAsync(ctx.Request.Body); var hint = ""; // Port separat behandeln – in appsettings.Production.json speichern if (body.TryGetProperty("Port", out var portProp) && portProp.TryGetInt32(out var newPort)) { var currentPort = config.GetValue("Port", 19000); if (newPort != currentPort && newPort > 0 && newPort <= 65535) { SavePortToAppSettings(ctx, newPort); hint = "Port geändert – Neustart erforderlich!"; } } // Alle anderen Settings in DB speichern foreach (var def in ServerSettingsService.Definitions) { if (!body.TryGetProperty(def.Key, out var prop)) continue; switch (def.Type) { case "string": settings.Set(def.Key, prop.GetString() ?? ""); break; case "int": settings.SetInt(def.Key, prop.TryGetInt32(out var i) ? i : 0); break; case "bool": settings.SetBool(def.Key, prop.ValueKind == JsonValueKind.True); break; } } await ctx.Response.WriteAsJsonAsync(new { ok = true, hint = string.IsNullOrEmpty(hint) ? "Einstellungen gespeichert" : hint }); } private static void SavePortToAppSettings(HttpContext ctx, int port) { // appsettings.Production.json im ContentRootPath (= publish-Verzeichnis) var contentRoot = ctx.RequestServices.GetService(typeof(Microsoft.AspNetCore.Hosting.IWebHostEnvironment)) as Microsoft.AspNetCore.Hosting.IWebHostEnvironment; var path = Path.Combine(contentRoot?.ContentRootPath ?? AppContext.BaseDirectory, "appsettings.Production.json"); JsonObject obj; if (File.Exists(path)) { try { var existing = File.ReadAllText(path); obj = JsonNode.Parse(existing) as JsonObject ?? new JsonObject(); } catch { obj = new JsonObject(); } } else { obj = new JsonObject(); } obj["Port"] = port; var options = new JsonSerializerOptions { WriteIndented = true }; File.WriteAllText(path, obj.ToJsonString(options)); } }