系統管理 功能群總覽¶
本檔放「本功能群多個頁面共用的知識」:頁面地圖、三層 RBAC 權限模型、租戶/部門/使用者組織模型、
system_configskey-value 慣例、角色權限基調、核心資料模型。各頁面 spec 引用本檔,只寫自己頁面的差異——改共用邏輯時改這裡一份。
事實基準:2026-07-05 從 FE
src/config/router/index.js+ BE routes.json / db_schema.json +docs/system-design/permission/設計說明書掃出;§1 頁面地圖、§2 權限模型、§5 角色基調 2026-10-08 依 FR-132 實作(jedi-iam 判定層、本機 DEV DB)重掃。變更紀錄:2026-10-08 FR-132 —— 存取管理四頁取代角色權限管理;權限改三段式名稱、角色存萬用字元規則;208 項權限全部真擋
1. 頁面地圖¶
本功能群是產品的「後台設定層」,橫跨權限治理(存取管理 / 選單 / 使用者)、組織主檔(租戶 / 部門 / 設備 / 資訊系統)、系統參數(通知 / SMTP / LDAP / 議題整合 / 工具外掛)與稽核與個人(操作日誌 / 個人資料)四塊。
| 頁面 | FE route | 用途一句話 | spec |
|---|---|---|---|
| 存取管理:角色 | /access/roles |
角色列表、新增複製刪除、匯出匯入角色 JSON | ✅ 角色 |
| 存取管理:角色明細 | /access/roles/:uid(+ /access/roles/new) |
權限樹勾選、可見選單即時預覽 | ✅ 角色明細 |
| 存取管理:指派 | /access/assignments |
誰 × 角色 × 範圍 × 起訖日;到期自動失效 | ✅ 指派 |
| 存取管理:檢查存取 | 嵌在指派頁(?check=<uid>) |
某人每項權限的來源角色、到期日、可見選單 | ✅ 檢查存取 |
| 使用者管理 | /auth/user-manage(+ user-form) |
帳號 CRUD、所屬租戶與部門、帳號頁的角色、批次匯入、狀態切換 | ✅ 使用者管理 |
| 選單管理 | /system/system-menu-manage |
system_menus group/key 選單項維護 |
✅ 選單管理 |
| 部門管理 | /department/department-manage |
org_units 樹狀部門 CRUD |
✅ 部門管理 |
| 租戶管理 | /tenant/tenant-manage |
tenants 樹狀租戶 CRUD |
✅ 租戶管理 |
| 設備管理 | /device/device-manage |
devices 設備主檔 CRUD+Excel/CSV 匯入匯出;檢測線逐台型目標的授權來源 |
✅ 設備管理 |
| 授權掃描網段 | /system/scan-zone |
tenant_scan_zones 租戶授權網段(網段型掃描目標必須落在內;agent 心跳下發);只給租戶管理員改 |
✅ 授權掃描網段 |
| 資訊系統盤點 | /information-system/manage |
compliance.information_systems 稽核範圍系統主檔 |
✅ 資訊系統盤點 |
| 通知頻道設定 | /system/notify-config |
system_configs NOTIFY group(Telegram / Discord)+ 測試寄送 |
✅ 通知頻道設定 |
| SMTP 伺服器設定 | /system/smtp-config(-manage) |
system_configs SMTP group + 測試寄送 |
✅ SMTP 伺服器設定 |
| LDAP 設定 | /system/ldap-config |
system_configs LDAP group + 連線測試 |
✅ LDAP 設定 |
| Log 轉發設定 | /system/log-forwarding |
系統 log 轉發到客戶自有 log 平台(Syslog / GELF)+ 測試送出 | ✅ Log 轉發設定 |
| 議題整合設定 | /system/issue-integrate-config |
GitLab / GitHub 整合(餵回饋鏡像) | ✅ 議題整合設定 |
| 工具外掛管理 | /plugin/tool-plugin-manage |
外部檢測工具 / 外掛模組管理 | ✅ 工具外掛管理 |
| 掃描設定檔管理 | /plugin/detection-profile-manage |
檢測工具掃描設定檔(profile / content)庫——公用版+租戶自有雙軌 | ✅ 掃描設定檔管理 |
| 弱點資料庫 | /system/vulndb |
第三方元件風險掃描用的弱點資料:日期、上傳更新包、連網檢查更新、更新紀錄(全機共用) | ✅ 弱點資料庫 |
| 操作日誌 | /log/user-log |
api_logs 稽核軌跡查詢(不含 system_logs,見頁面 spec §1) |
✅ 操作日誌 |
| 個人資料 | /user/user-profile |
自身資料 / 改密 / MFA(TOTP)設定 | ✅ 個人資料 |
| License 授權管理 | /license/manage |
平台方對客戶租戶發照/換照/停權/查授權歷程(root 專屬) | ✅ License 授權管理 |
| 我的授權狀態 | /license/status |
租戶側唯讀:自己的模組集 / 到期日 / 現處階段 | ✅ 我的授權狀態 |
| 背景服務與排程 | —(無 UI) | 全系統背景 job / 排程 / socket / 心跳盤點 | ✅ 背景服務與排程 |
| 錯誤追蹤站 | —(產品外,/bugsink/ 子路徑) |
落地版內建錯誤追蹤站:三個專案、收件開關、遮罩、前端與 Agent 轉送 | ✅ 錯誤追蹤站 |
sitemap(/sitemap,「網站導覽」)已除名:router 有孤兒條目 +menu.json有 label,但public.ui_routes無對應列(非選單項)、FE 全域零 nav 進入點,屬 dead route(比照已除名的project-task-setup)。功能本身(SiteMap.vue)只是把permissions[0].items畫成 OrganizationChart,未獨立成頁。舊「角色權限管理」(
/auth/role-manage、/auth/role-form)已退役,舊網址轉到存取管理;舊規格 留作對照。
user-form-mtrbac(/auth/user-form)是使用者管理表單的 multi-tenant RBAC 變體,併入使用者管理 spec。smtp-config-manage是 SMTP 設定的列表 / 管理變體,併入通知 / SMTP spec。
2. 三層 RBAC 權限模型(全群樞紐,先讀)¶
Guidant AI 採 Role-Based Access Control:使用者經指派取得角色、角色以規則涵蓋一組權限、權限決定 API 能不能用與選單看不看得到。判定在 jedi-iam 套件。
flowchart LR
U["使用者"] -- "指派 user_roles<br/>範圍 × 起訖" --> R["角色 roles"]
R -- "規則 role_capability_patterns<br/>例 grc.project.*、*.*.read" --> C["權限 capabilities<br/>module.resource.action"]
C -- "API 守門" --> API["放行/403"]
C -- "route_capabilities ALL/ANY" --> M["側欄選單可見"]
| 層級 | 表 | 說明 |
|---|---|---|
| 使用者 | public.users |
帳號本體 |
| 指派 | public.user_roles |
使用者 × 角色 × 範圍(scope=tenant/org_unit、tenant_id、org_unit_id)× 起訖(starts_at/ends_at) |
| 角色 | public.roles |
屬於某租戶;is_system=內建系統管理員、is_template=出貨範例 |
| 角色規則 | public.role_capability_patterns |
角色 × 規則字串;判定唯一來源 |
| 權限 | public.capabilities |
三段名;is_platform、license_module、enforce_mode、home_route_name |
| 路由 ↔ 權限 | public.route_capabilities |
進頁門檻(ALL 全要/ANY 任一) |
| UI 路由 | public.ui_routes |
選單樹;is_menu=出現在側欄、tree_page=角色樹上的子頁 |
role_capabilities(角色 ↔ 權限 id)已退役、不再寫入。
2.1 權限名與萬用字元¶
- 三段式:
<模組>.<資源>.<動作>,三段小寫、資源名內用連字號,例grc.project.approve、system.ldap-config.update。共 208 項,12 個模組:grc、oscal、flow、detection、evidence、survey、system、iam、platform、asset、ai、workspace。 - 動作:每個資源固定 read/create/update/delete;另有 approve、close、publish、export、assign、import、execute——只給「給了 update 卻不想一起給」的動作。
- 萬用字元規則:
grc.*.*(某模組全部)、*.*.read(全部唯讀)、*.*.*(全部)。含星號的規則會自動涵蓋日後新增的權限;畫面勾選則存具體權限名,不自動合成星號。 - 內建系統管理員:規則固定
*.*.*,每租戶恰一個,不可改不可刪。出貨另附四個範例角色(稽核主管、稽核員、一般成員、唯讀),可改可刪可複製,見 角色 §4。 - 原廠層權限(
platform.*,is_platform=true):只有原廠(總部)租戶的角色可持有,且端點另要平台管理員身分,兩道都過。
2.2 判定規則¶
- 只採計有效指派:期間內、角色與帳號都啟用、屬當前租戶。到期的指派仍列在指派頁並標「已到期」,但判定與選單不再採計。
- 把有效指派的角色規則展開成權限集合(Redis 快取,鍵含權限目錄版本號)。
- 要的權限在集合內就放行,否則 403
GRC_403022,回應帶缺的權限名(data.required),畫面顯示「使用者不具備此操作所需的權限(需要權限:<權限名>)」。 - 208 項權限全部真擋(
enforce_mode=enforce)。 - 部門範圍目前只當屬性:指派可記部門,判定上與整個租戶相同;部門資料隔離本版不做。
任務情境通則:
| 通則 | 規則 |
|---|---|
| A 任務情境看任務權限 | 在任務/專案頁做的事看 grc.job.*/grc.project.*,不看功能模組自己的權限(任務頁開始掃描=grc.job.update,不是 detection)。例外:已結案問卷的內容與檢測工具執行紀錄,持 grc.job-evidence.read(檢視任務證據)亦可讀 |
| B 挑選名單看呼叫頁權限 | 下拉、挑選用名單看當下頁面的權限,被挑模組的 read 只管它自己的管理頁;挑人、挑部門豁免 |
| C 一支 API 服務多種資源 | 先解析資源歸屬,再判單一權限,不開「擇一放行」 |
升級時自動補授:權限改名時,角色上的勾選跟著改名;拆出的權限依「升級前由什麼把關」補給既有角色——升級前由某權限守的補給持有那項的角色;升級前只驗登入的補給既有角色;全新功能只補管理員角色。系統管理員與出貨範例不補(前者本來就涵蓋,後者照定稿)。
2.3 選單可見性(GET /user/web-menu)¶
BE 依使用者的有效權限集合,對每個 ui_routes 節點:
- 無需求(
route_capabilities無設定)→ 預設可見(「登入即可見」) - ANY 命中任一 → 可見
- ALL 全部擁有 → 可見
外加 ui_routes.enable=1 與授權照過濾。慣例:read 設 ALL(無讀權限看不到選單)、寫入類設 ANY。側欄、角色明細的可見選單預覽、檢查存取、前端路由守門都走同一條判定(/user/web-menu、/ui-routes/visible-by-capabilities、/users/me/capabilities)。頁內按鈕另依各自權限隱藏,沒有權限的按鈕不顯示。
新功能要進角色樹被勾選授權:在程式碼宣告
Capability(含home_route)→ui_routes→route_capabilities→ FE route 與v-can;守衛測試test/test_fr132_capability_home_route.py擋「沒綁頁又沒填歸屬頁」。
3. 租戶 / 部門 / 使用者 組織模型¶
系統是多租戶架構:租戶(tenants)為頂層、可樹狀階層;部門(org_units)隸屬租戶、亦可樹狀。使用者可屬多租戶、多部門。
| 關係 | 表 | 說明 |
|---|---|---|
| 使用者預設歸屬 | users.tenant_id / users.org_unit_id |
單一預設值(欄位) |
| 使用者 ↔ 租戶 | public.user_tenants |
N:M;is_default 標預設租戶 |
| 使用者 ↔ 部門 | public.user_org_units |
N:M;is_primary 標主要部門 |
| 租戶樹狀 | tenants.parent_id / tenants.path(/1/2/ 格式) |
多層租戶 |
| 部門樹狀 | org_units.parent_id / org_units.path |
部門內含子部門 |
RLS:DB 層以 PostgreSQL RLS 做租戶隔離,
session_scope()自動注入app.user_id/app.allowed_tenant_paths,Python 查詢不需另加 tenant filter(見專案 CLAUDE.md「RLS 注意事項」)。但功能定義表ui_routes/capabilities/route_capabilities不加 RLS(全租戶共用同一份功能定義),隔離改由user_roles.tenant_id處理。
4. system_configs key-value 設定慣例¶
多個設定頁(通知 / SMTP / LDAP / 議題整合)不各自建表,而是共用 public.system_configs 這張 group / key / value(jsonb) 的鍵值表:
| 欄位 | 說明 |
|---|---|
group |
設定群組(如 SMTP / NOTIFY / LDAP / ISSUE;實際 group 名以各設定頁 spec 查證為準) |
key |
設定鍵名 |
value |
jsonb 設定值 |
tenant_id / org_unit_id |
設定的歸屬範圍(可為租戶級或全域) |
主要 endpoint:GET/POST/PUT/DELETE /api/1.0/system/config、GET /api/1.0/system/configs/<group>、GET/PUT/DELETE /api/1.0/system/config/<group>/<key>。設定頁不寫 value 明文憑證進 spec(密碼 / token 只描述欄位)。
選單項另有
public.system_menus(group / key / value / sort / enable / public)——這是「選單管理」頁維護的下拉 / 分類選單資料(如國家、產業別等 code table),與ui_routes(權限選單樹)是兩回事,別混。
5. 角色權限基調¶
角色是誰:
- 平台 admin(root tenant)——治理全系統的角色、能力點、選單結構,是所有其他角色權限的源頭。「身為平台 admin,我要新增一個角色、勾選它能看到哪些選單與能做哪些操作。」
- 租戶 admin——管理自己租戶內的使用者、部門、設備、資訊系統盤點等主檔資料。「身為租戶 admin,我要新增一個部門、把新進使用者分派進去並指派角色。」
- 一般使用者——管理自己的個人資料、密碼、MFA 設定,不涉及他人資料。「身為一般使用者,我要改自己的密碼、設定雙因子驗證。」
系統管理群整體是管理員 / 平台層功能,理應鎖後台角色。實務上各頁 BE 強制程度不一:
| 面向 | 應由誰 | 常見 BE 現況 |
|---|---|---|
| 角色 / 指派 / 選單治理 | 平台 / 租戶 admin | iam.role.*、iam.user.assign 守門;原廠層另要平台管理員(GRC_403060) |
| 使用者 / 租戶 / 部門 / 設備 CRUD | 租戶 admin | 各資源 iam.*/asset.* 權限守門 |
| 個人資料 / 改密 / MFA | 使用者本人 | 僅 JWT(操作自身) |
重要:
route_capabilities控制的是選單是否顯示;API 是否放行由端點上的權限守門決定,兩者各自設定。各頁 §3 權限矩陣以 FE 判定 vs BE 強制分欄對照,發現不一致標 ⚠️ 收進該頁 §12。error code 前綴:權限 / 平台層多為
GRC_(如GRC_NOT_PLATFORM_ADMIN=403060),但各模組不保證同前綴——寫每頁 §6 前先 grep 該模組common/code/*_error_code.py查證,勿假設全GRC_。
6. 核心資料模型¶
| 表 | schema | 角色 |
|---|---|---|
users |
public | 帳號本體(login_name / nickname / status / 預設 tenant+org / mfa) |
roles |
public | 角色(tenant_id、is_system、is_template、is_admin、enable、is_delete) |
capabilities |
public | 權限(name 三段名 UNIQUE / module / is_platform / license_module / enforce_mode / home_route_name) |
role_capability_patterns |
public | 角色 ↔ 規則字串(判定唯一來源) |
route_capabilities |
public | 路由 ↔ 能力(複合 PK + requirement ALL/ANY) |
ui_routes |
public | 選單 / 路由樹(pid 自參考 / enable / sort / is_menu / tree_page;name=i18n key) |
user_roles |
public | 指派(scope / tenant_id / org_unit_id / starts_at / ends_at) |
tenants |
public | 租戶(parent_id / path 樹狀) |
org_units |
public | 部門(tenant_id / parent_id / path 樹狀) |
user_tenants |
public | 使用者 ↔ 租戶(is_default) |
user_org_units |
public | 使用者 ↔ 部門(is_primary) |
system_configs |
public | 系統設定 key-value(group / key / value jsonb / tenant_id) |
system_menus |
public | 下拉 / 分類選單 code table(group / key / value;≠ ui_routes) |
devices |
public | 設備主檔 |
information_systems |
compliance | 稽核範圍資訊系統主檔 |
api_logs / system_logs |
public | 操作日誌(api_logs vs event_code 事件日誌,見操作日誌頁) |
user_auth_providers |
public | 使用者第三方登入綁定 |
user_change_password_request / user_change_pwd_logs |
public | 改密請求 / 歷史 |
7. 本群共用的已知坑¶
ui_routesvssystem_menus別混:前者是權限選單樹(RBAC 可見性)、後者是下拉分類 code table(選單管理頁維護),兩張不同用途的表。ui_routes控可見性 ≠ BE 端點強制:route_capabilities只決定選單顯不顯示;API 放行看端點守門。新增端點兩邊都要設。ui_routes.name已加 UNIQUE(2026-07-08 FR-047 SCHEMA,DEV+STG 已套、POC 待部署):FE 功能樹強依賴 name 當 i18n key,原無 DB 約束、重名顯示錯亂;已加uq_ui_routes_name UNIQUE(name)(capabilities.name本就有 UNIQUE)。POC 未套前新增仍建議先 SELECT 確認沒重名(設計文件 §9.1)。- 跨環境 id 漂移:DEV / STG / POC 的
ui_routes.id/capabilities.id用 serial 各自編號、不一致,程式碼與 migration 一律用name查、勿 hardcode id(設計文件 §9.7)。 is_platform權限:原廠層權限(root tenant 專屬)在一般租戶角色樹不出現、寫入端擋(GRC_403060)。sort預留 gap:ui_routes.sort/system_menus.sort用 10/20/30 間隔,別連號(設計文件 §9.2)。- 設定頁共用
system_configs:通知 / SMTP / LDAP / 議題整合都是同一張 key-value 表的不同 group,非各自專表;改一個設定頁的讀寫慣例前,先確認沒影響同表其他 group。 - jedi-iam 套件擁有大半 RBAC 邏輯:
users/roles/ 指派 /ui_routes/ web-menu / 判定的 service / repo 在 jedi-iam 套件內(~/Projects/Jedicogy/module/jedi-python-package/jedi-iam/),不在主專案;改行為要分清邊界(見 CLAUDE.md「外部套件異動規範」)。