using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Nuuru.Server.Auth; using Nuuru.Server.DTOs.Settings; using Nuuru.Server.Models; using Nuuru.Server.Services; namespace Nuuru.Server.Controllers { [ApiController] [Route("api/settings")] public class SiteSettingsController : ControllerBase { private readonly ISiteSettingsService _settingsService; private readonly Services.BBCode.IBBCodeService _bbCodeService; public SiteSettingsController(ISiteSettingsService settingsService, Services.BBCode.IBBCodeService bbCodeService) { _settingsService = settingsService; _bbCodeService = bbCodeService; } [HttpGet] [AllowAnonymous] public async Task GetPublicSettings() { var captchaProvider = await _settingsService.GetCaptchaProviderAsync(); var blotterGallery = await _settingsService.GetAsync(SiteSettingKeys.BlotterGallery); var blotterForum = await _settingsService.GetAsync(SiteSettingKeys.BlotterForum); var dto = new PublicSiteSettingsDto { RegistrationEnabled = await _settingsService.IsRegistrationEnabledAsync(), AnonymousUploadsEnabled = await _settingsService.IsAnonymousUploadEnabledAsync(), AnonymousCommentsEnabled = await _settingsService.IsAnonymousCommentEnabledAsync(), CaptchaProvider = captchaProvider, CaptchaSiteKey = captchaProvider == "hcaptcha" ? await _settingsService.GetCaptchaSettingAsync(SiteSettingKeys.CaptchaHCaptchaSiteKey, "") : null, BlotterGalleryHtml = string.IsNullOrWhiteSpace(blotterGallery) ? null : _bbCodeService.Parse(blotterGallery), BlotterForumHtml = string.IsNullOrWhiteSpace(blotterForum) ? null : _bbCodeService.Parse(blotterForum) }; return Ok(dto); } [HttpGet("all")] [Authorize(Policy = Permissions.Admin.SystemSettings)] public async Task GetAllSettings() { var settings = await _settingsService.GetAllAsync(); return Ok(settings); } [HttpPut] [Authorize(Policy = Permissions.Admin.SystemSettings)] public async Task UpdateSettings([FromBody] UpdateSiteSettingsRequest request) { foreach (var (key, value) in request.Settings) { await _settingsService.SetAsync(key, value); } return Ok(new { message = "Settings updated" }); } [HttpPost("panic")] [Authorize(Policy = Permissions.Admin.Panic)] public async Task Panic([FromServices] IHostApplicationLifetime lifetime, [FromServices] ILogger logger) { logger.LogCritical("Emergency shutdown triggered by user {UserId}", User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value); // Persist the flag so Docker restarts keep dying await _settingsService.SetAsync(SiteSettingKeys.Panic, "true"); // Kill the process after the response flushes _ = Task.Run(async () => { await Task.Delay(500); lifetime.StopApplication(); // Hard kill fallback in case graceful shutdown hangs await Task.Delay(5000); Environment.Exit(1); }); return Ok(new { message = "Emergency shutdown activated — server is shutting down" }); } [HttpGet("integrity-dashboard-url")] [Authorize(Policy = Permissions.Moderation.ViewIntegrityAssessments)] public async Task GetIntegrityAdminDashboardUrl() { var url = await _settingsService.GetIntegrityAdminDashboardUrlAsync(); return Ok(new { url }); } } }