using System.Text.Json; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using MiGu.Server.Configs; namespace MiGu.Server.Controllers; // AR-4: 全 class 加 [Authorize] —— 替代会话21 点名的「ConfigController 无鉴权 PUT 任意 section」漏洞。 // GET (List/Get) 只要登录就放;PUT 按 scope 收紧:Platform 任意节,RCSMonitor 仅 ops 白名单。 [ApiController] [Authorize] [Route("api/config")] public class ConfigController : ControllerBase { private readonly ConfigStore _store; public ConfigController(ConfigStore store) { _store = store; } [HttpGet] public IActionResult List() { var envs = _store.List().Select(e => new { section = e.Section, version = e.Version, updatedAt = e.UpdatedAt }); return Ok(envs); } [HttpGet("{section}")] public IActionResult Get(string section) { if (!ConfigStore.AllSections.Contains(section, StringComparer.OrdinalIgnoreCase)) return NotFound(new { message = $"未知 section: {section}" }); var env = _store.Get(section); return Ok(new { section = env.Section, version = env.Version, updatedAt = env.UpdatedAt, payload = env.Payload }); } /// RCSMonitor scope 允许写入的 section 白名单(地图监控动作备份等运营自有配置)。 private static readonly string[] MonitorWritableSections = { "ops" }; // Platform scope 可写任意 section;RCSMonitor 仅允许写 ops(保留运营端 // 「地图监控动作 ops.monitor 备份」既有功能),其余 section(routing/auth/system 等)一律 403。 [HttpPut("{section}")] public IActionResult Put(string section, [FromBody] JsonElement payload) { if (!ConfigStore.AllSections.Contains(section, StringComparer.OrdinalIgnoreCase)) return NotFound(new { message = $"未知 section: {section}" }); var scope = User.FindFirst("scope")?.Value; if (!string.Equals(scope, "Platform", StringComparison.OrdinalIgnoreCase) && !MonitorWritableSections.Contains(section, StringComparer.OrdinalIgnoreCase)) { return StatusCode(403, new { message = $"当前账号无权修改配置节 {section}(需要 Platform 管理端权限)" }); } var env = _store.Put(section, payload); return Ok(new { section = env.Section, version = env.Version, updatedAt = env.UpdatedAt, payload = env.Payload }); } }