订阅和规则组支持从文件导入,配置页与表单一批打磨
文件导入走两步:内容先经新端点 POST /api/provider-files 写进内核工作 目录的 providers/ 下(路径白名单校验,只认两个路径助手生成的形状), 成了再写 file 类型的声明——顺序反了内核重载会去读不存在的文件。 file 类型没有地址和自动更新(内核靠文件监视跟进),详情页照此展示, 编辑按钮禁用。ini 导入的取文件按钮换成同一个拖放模块。 订阅的更新间隔改成开关语义:内核只在 interval > 0 时才起定时拉取 (component/resource/fetcher.go:226-228),关掉开关就是不写这个键。 配置页加「更新所有订阅」,详情的「立刻更新」改叫「更新订阅」。 规则表从零开始写入时自动垫上内网直连——保留地址不直连的话第一条 代理规则一生效,访问局域网的流量就全进了代理;按钮改成「补全内网 直连」,只在有缺口时出现。 所有表单对话框点遮罩关闭;失败横幅右侧加关闭按钮。
This commit is contained in:
@@ -9,7 +9,9 @@
|
||||
* 透传只开放 GET。写操作(切换节点、关连接)属于运行时面板的功能,等做到那一步再单独开,
|
||||
* 现在不留一个「什么都能转发」的口子。
|
||||
*/
|
||||
import { resolve, sep } from 'node:path'
|
||||
import listenerFields from '../shared/listener-fields.json' with { type: 'json' }
|
||||
import { isProviderFilePath } from '../shared/provider-files.ts'
|
||||
import { applyConfig, listBackups, readConfig, restoreBackup } from './config-store.ts'
|
||||
import { hostInfo, probeExit } from './host.ts'
|
||||
import { kernelVersion, proxyGet, proxyWrite, restartKernel, selectProxy } from './kernel.ts'
|
||||
@@ -181,6 +183,26 @@ function makeRoute(env: Env, token: string) {
|
||||
return result.ok ? json(result) : json(result, applyFailureStatus(result.stage))
|
||||
}
|
||||
|
||||
// ── 清单文件 ────────────────────────────────────────
|
||||
// 从界面上传的订阅/规则清单,写进内核工作目录的 providers/ 下。
|
||||
// 路径白名单校验 + 解析后确认没出工作目录,两道都过才落盘
|
||||
if (path === '/api/provider-files' && req.method === 'POST') {
|
||||
const body = (await req.json()) as { path?: string; content?: string }
|
||||
if (typeof body.path !== 'string' || typeof body.content !== 'string') {
|
||||
return json({ message: '请求缺少 path 或 content 字段' }, 400)
|
||||
}
|
||||
if (!isProviderFilePath(body.path)) {
|
||||
return json({ message: `不允许写入该路径:${body.path}` }, 400)
|
||||
}
|
||||
const home = resolve(env.mihomoHome)
|
||||
const target = resolve(home, body.path)
|
||||
if (!target.startsWith(home + sep)) {
|
||||
return json({ message: `不允许写入该路径:${body.path}` }, 400)
|
||||
}
|
||||
await Bun.write(target, body.content)
|
||||
return json({ ok: true })
|
||||
}
|
||||
|
||||
// ── 主机 ────────────────────────────────────────────
|
||||
// 服务端和内核在同一台机器上,所以主机指标由 Patchbay 自己代答
|
||||
if (path === '/api/host' && req.method === 'GET') {
|
||||
|
||||
Reference in New Issue
Block a user