feat(权限): 收敛普通账号写权限至本人凭证
将调度时刻、采集参数等实例级配置收归管理员,普通账号仅可维护本人 Cookie 与 User-Agent。 新增 config.writable_by 作为唯一写权限入口,set_setting 强制全局键落到 user_id=0, 消除「管理员改了只有自己生效」的静默缺陷。新增 tools/check_docs.py 文档自检, smoke 断言扩至 215 项、check_live 扩至 122 项并支持普通账号越权验收, 忽略 backups/、data/*.bak* 与 legacy-v1/,版本升至 v1.3.0。
这个提交包含在:
@@ -61,6 +61,12 @@
|
||||
var out = {};
|
||||
Array.prototype.forEach.call(form.elements, function (el) {
|
||||
if (!el.name || el.type === "submit" || el.name === "_csrf") return;
|
||||
// 只读控件必须跳过:disabled 的 input 仍然出现在 form.elements 里,
|
||||
// 若被一起提交,服务端会因为「越权修改只读项」把**整单**拒掉 ——
|
||||
// 表现成「改了 A 却提示 A 不能改」,很难归因。
|
||||
// 注意:fieldset 被 disable 时子元素自身的 disabled 仍是 false,
|
||||
// 所以还要往上找祖先 fieldset。
|
||||
if (el.disabled || (el.closest && el.closest("fieldset[disabled]"))) return;
|
||||
if (el.type === "checkbox") { out[el.name] = el.checked ? "1" : "0"; return; }
|
||||
if (el.type === "radio") { if (el.checked) out[el.name] = el.value; return; }
|
||||
out[el.name] = el.value;
|
||||
@@ -72,7 +78,7 @@
|
||||
function hintOf(j) {
|
||||
if (!j) return "";
|
||||
if (j.error === "cookie_expired") return "\n请到「配置管理」更新 Cookie 与 User-Agent(两者须取自同一次浏览器请求)。";
|
||||
if (j.error === "busy") return "\n已有采集在进行,可稍后重试,或到「日志管理」查看进度。";
|
||||
if (j.error === "busy") return "\n已有采集在进行,可稍后重试;「任务管理」里能看到本次运行的状态。";
|
||||
if (j.errors && j.errors.length) return "\n" + j.errors.join("\n");
|
||||
return "";
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户