2026-05-29 18:16:34 +08:00
|
|
|
|
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」漏洞。
|
2026-06-12 23:00:47 +08:00
|
|
|
|
// GET (List/Get) 只要登录就放;PUT 按 scope 收紧:Platform 任意节,RCSMonitor 仅 ops 白名单。
|
2026-05-29 18:16:34 +08:00
|
|
|
|
[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
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-12 23:00:47 +08:00
|
|
|
|
/// <summary>RCSMonitor scope 允许写入的 section 白名单(地图监控动作备份等运营自有配置)。</summary>
|
|
|
|
|
|
private static readonly string[] MonitorWritableSections = { "ops" };
|
|
|
|
|
|
|
|
|
|
|
|
// Platform scope 可写任意 section;RCSMonitor 仅允许写 ops(保留运营端
|
|
|
|
|
|
// 「地图监控动作 ops.monitor 备份」既有功能),其余 section(routing/auth/system 等)一律 403。
|
2026-05-29 18:16:34 +08:00
|
|
|
|
[HttpPut("{section}")]
|
|
|
|
|
|
public IActionResult Put(string section, [FromBody] JsonElement payload)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!ConfigStore.AllSections.Contains(section, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
|
return NotFound(new { message = $"未知 section: {section}" });
|
|
|
|
|
|
|
2026-06-12 23:00:47 +08:00
|
|
|
|
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 管理端权限)" });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-29 18:16:34 +08:00
|
|
|
|
var env = _store.Put(section, payload);
|
|
|
|
|
|
return Ok(new
|
|
|
|
|
|
{
|
|
|
|
|
|
section = env.Section,
|
|
|
|
|
|
version = env.Version,
|
|
|
|
|
|
updatedAt = env.UpdatedAt,
|
|
|
|
|
|
payload = env.Payload
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|