diff --git a/doc/Linux生产流程测试记录.md b/doc/Linux生产流程测试记录.md index 4270184..ba48784 100644 --- a/doc/Linux生产流程测试记录.md +++ b/doc/Linux生产流程测试记录.md @@ -8,7 +8,9 @@ - [✓] 设置专项修复后在第一台通过,耗时 0.364 秒。 - [!] `scert-settings-scope-green-20261004-0340.service` 已失败,退出码一。设置专项通过,HTTP API 全量 49.447 秒后两项失败:旧可选邮箱测试仍要求普通管理员读取全局设置、旧中间件测试仍要求通用管理错误文案。未运行后续 vet 和竞态,不以专项替代全量。 - [x] 调整旧权限契约测试:可选邮箱会话继续验证普通管理员可读服务商目录,同时新增普通用户与普通管理员均不可读系统设置的断言;通用管理拒绝文案使用真正的普通管理路由,系统设置专属拒绝由新范围测试覆盖。没有放宽实际系统设置权限。 -- [~] 复跑单元 `scert-settings-scope-fixed-20261004-0343.service` 已启动;依次执行 HTTP API 全量、vet 和设置、DNS 范围、可选邮箱、管理中间件三轮竞态。日志同目录 `settings-scope-fixed.log`,最终状态待确认。 +- [✓] 复跑单元 `scert-settings-scope-fixed-20261004-0343.service` 已 inactive、Result=success、ExecMainStatus=0;HTTP API 全量 49.496 秒、vet 和设置、DNS 范围、可选邮箱、管理中间件三轮竞态 45.136 秒通过。日志同目录 `settings-scope-fixed.log`。 +- [x] 继续核对真实路由发现服务商目录仍要求全局管理员;前端普通用户或降权后的加载不再请求该目录,测试夹具模拟真实四百零三,避免无条件成功响应掩盖页面失败。 +- [~] 干净 `3ff59dd` 第一台后端全量及 vet 执行中,单元 `scert-settings-full-20261004-0346.service`,日志 `/var/tmp/scert-settings-clean-20261004-0344/full.log`;后续只有前端兼容增量,没有后端变更。旧候选包已构建但未安装,正式部署必须使用包含最终前端的重新构建产物。 - [ ] 全量 Linux 回归和正式新包部署待完成;线上第一台仍为 `9c26db0`。没有清理生产数据库、操作第二台、修改公共 DNS、增加辅助脚本或备份。 ## 2026年10月4日 真实 lego 客户端隔离协议回归 diff --git a/frontend/src/views/Dashboard/Dashboard.js b/frontend/src/views/Dashboard/Dashboard.js index 207e268..91f4914 100644 --- a/frontend/src/views/Dashboard/Dashboard.js +++ b/frontend/src/views/Dashboard/Dashboard.js @@ -1059,7 +1059,9 @@ export function useDashboard() { fetchAdmin("/api/v1/tasks?limit=20"), fetchAdmin("/api/v1/audit-logs?limit=20"), session.role === "super_admin" ? fetchAdmin("/api/v1/settings") : Promise.resolve(null), - fetchAdmin("/api/v1/dns/providers"), + ["super_admin", "admin"].includes(session.role) + ? fetchAdmin("/api/v1/dns/providers") + : Promise.resolve(null), ]); if (version !== loadDataVersion) return; const failedResponse = [ @@ -1083,7 +1085,7 @@ export function useDashboard() { taskResponse.json(), auditResponse.json(), settingsResponse ? settingsResponse.json() : Promise.resolve(null), - dnsProviderResponse.json(), + dnsProviderResponse ? dnsProviderResponse.json() : Promise.resolve({ items: [] }), ]); if (version !== loadDataVersion) return; status.value = nextStatus; diff --git a/frontend/src/views/Dashboard/SettingsAccess.test.js b/frontend/src/views/Dashboard/SettingsAccess.test.js index 9aceb3e..509ac73 100644 --- a/frontend/src/views/Dashboard/SettingsAccess.test.js +++ b/frontend/src/views/Dashboard/SettingsAccess.test.js @@ -9,6 +9,9 @@ for (const role of ["admin", "user", "super_admin"]) { const { state } = await mountComposable(t, useDashboard, async (path) => { requests.push(path); if (path.endsWith("/auth/session")) return Response.json({ role }); + if (path.endsWith("/dns/providers") && role === "user") { + return Response.json({ error: "没有管理权限" }, { status: 403 }); + } if (path.endsWith("/settings")) { if (role !== "super_admin") return Response.json({ error: "无系统权限" }, { status: 403 }); return Response.json({ notification: { smtp_username: "system-account" } }); @@ -17,6 +20,7 @@ for (const role of ["admin", "user", "super_admin"]) { }); assert.equal(state.error.value, ""); assert.equal(requests.includes("/api/v1/settings"), role === "super_admin"); + assert.equal(requests.includes("/api/v1/dns/providers"), role !== "user"); assert.equal(state.settings.value?.notification?.smtp_username || "", role === "super_admin" ? "system-account" : ""); }); }