using Microsoft.AspNetCore.Mvc;
using NewLife;
using Rainbow.Entity;
using Rainbow.Services;
namespace Rainbow.Web.Controllers;
/// <summary>DNS 规则管理 API</summary>
[ApiController]
[Route("api/dns")]
public class DnsController : ControllerBase
{
private readonly DnsmasqManager _dnsmasqManager;
/// <summary>构造 DNS 控制器</summary>
/// <param name="dnsmasqManager">Dnsmasq 配置管理器</param>
public DnsController(DnsmasqManager dnsmasqManager) => _dnsmasqManager = dnsmasqManager;
// ── DNS 规则 CRUD ──
[HttpGet("rules")] public ActionResult<IList<DnsRule>> GetRules() => Ok(DnsRule.FindAllWithCache());
[HttpPost("rules")]
public ActionResult AddRule([FromBody] DnsRule rule)
{
rule.Insert();
TryApplyDnsmasq();
return Ok(new { success = true, id = rule.Id });
}
[HttpPut("rules/{id}")]
public ActionResult UpdateRule(Int32 id, [FromBody] DnsRule rule)
{
var entity = DnsRule.FindById(id);
if (entity == null) return NotFound();
entity.Domain = rule.Domain; entity.TargetIp = rule.TargetIp; entity.RuleKind = rule.RuleKind; entity.Enable = rule.Enable;
entity.Update();
TryApplyDnsmasq();
return Ok(new { success = true });
}
[HttpDelete("rules/{id}")]
public ActionResult DeleteRule(Int32 id)
{
var r = DnsRule.FindById(id);
if (r == null) return NotFound();
r.Delete();
TryApplyDnsmasq();
return Ok(new { success = true });
}
// ── 儿童模式 DNS 白名单 ──
/// <summary>获取儿童模式状态。true=仅允许教育/学习域名</summary>
[HttpGet("children-mode")]
public ActionResult GetChildrenMode()
{
// 儿童模式通过检测白名单规则是否全部启用来判断
var rules = DnsRule.FindAll(DnsRule._.RuleKind == Rainbow.Entity.Models.RuleKinds.白名单 & DnsRule._.Enable == true);
var enabled = rules.Count > 0;
return Ok(new { enabled, whitelistRuleCount = rules.Count });
}
/// <summary>切换儿童模式</summary>
[HttpPost("children-mode")]
public ActionResult ToggleChildrenMode([FromBody] ChildrenModeDto dto)
{
var rules = DnsRule.FindAll(DnsRule._.RuleKind == Rainbow.Entity.Models.RuleKinds.白名单);
foreach (var rule in rules)
{
rule.Enable = dto.Enable;
rule.Update();
}
TryApplyDnsmasq();
return Ok(new { success = true, enabled = dto.Enable, affectedCount = rules.Count });
}
/// <summary>获取教育/学习域名白名单</summary>
[HttpGet("whitelist")]
public ActionResult<IList<DnsRule>> GetWhitelist()
{
var list = DnsRule.FindAll(DnsRule._.RuleKind == Rainbow.Entity.Models.RuleKinds.白名单);
return Ok(list);
}
/// <summary>添加白名单域名(教育/学习类)</summary>
[HttpPost("whitelist")]
public ActionResult AddWhitelist([FromBody] DnsRule rule)
{
rule.RuleKind = Rainbow.Entity.Models.RuleKinds.白名单;
rule.Enable = true;
rule.Insert();
TryApplyDnsmasq();
return Ok(new { success = true, id = rule.Id });
}
/// <summary>尝试应用 dnsmasq 配置(最佳努力,失败不影响 API 返回)</summary>
private void TryApplyDnsmasq()
{
_ = Task.Run(async () =>
{
try
{
await _dnsmasqManager.ApplyAsync();
}
catch { }
});
}
}
/// <summary>儿童模式开关 DTO</summary>
public class ChildrenModeDto
{
/// <summary>是否启用</summary>
public Boolean Enable { get; set; }
}
|