使用者表單(User Form)¶
功能群:系統管理|三層 RBAC 模型與租戶/部門組織模型先讀 功能群總覽 §2、§3|上層導航頁見 使用者管理
事實基準:2026-07-05 從 FE
src/views/user-manage/UserMTRBACForm.vue+ BEapi/auth/routes/user_route.py/change_password_route.py+ jedi-authuser_service.py/user_domain_service.py+ routes.json / db_schema.json 掃出;角色區塊、守門與user_roles寫入語意 2026-10-08 依 FEsrc/components/user-manage/UserRoleSummary.vue、UserInitialRolePicker.vue、UserMembershipEditor.vue+ jedi-iamapi/routes/user_route.py、app/service/user_service.py、role_assignment_service.py重掃。
變更紀錄¶
| 日期 | FR | 變更 |
|---|---|---|
| 2026-07-06 | FR-047 | 自 user-manage.md 拆出:帳號新增/編輯表單頁(含授權組合指派)獨立成子頁 |
| 2026-10-08 | FR-132 | 角色區塊改為指派表(就地編輯期間/移除、新增角色),存帳號不再動指派;所屬租戶與部門另成一區;寫入端點掛權限守門;不顯示「主要權限」 |
1. 功能描述¶
使用者表單是 使用者管理 列表「建立」/「編輯」導向的獨立表單頁(route user-form,實掛 /auth/user-form-mtrbac → UserMTRBACForm.vue)。新增與編輯共用同一表單:上半填帳號基本欄位(登入名稱 / 姓名 / Email / 職稱 / 電話 / 生效到期日 /(編輯限定)代改密碼),中段是所屬租戶與部門,下段是角色。
角色區塊依模式不同:
- 新增帳號:角色列(每列=角色+期間,可加可刪),隨「建立」一起送出;角色選項跟著第一個所屬租戶,換租戶時不屬於新租戶的列會被清掉並提示。
- 編輯帳號:一張指派表(租戶/角色/部門/生效/到期/狀態),與 指派 頁同一支 API、同一套欄位與狀態標籤;每列可就地「編輯期間」「移除角色」,表頭「新增角色」開同一個指派對話框(人已選好)。這些動作各自存檔,不經帳號的「儲存」;帳號存檔不送角色,後端也就不動指派。
「主要權限」(user_roles.is_default)不顯示:權限判定、側欄、登入都不讀它。
主要使用者:系統 / 租戶管理員。角色本身有哪些權限在 角色明細 設定;跨使用者看指派在 指派。
角色速覽(完整定義見 _overview §2、§3):
| 角色 | 一句話 |
|---|---|
持 iam.user.create/iam.user.update |
新增/編輯帳號基本資料、所屬租戶與部門 |
另持 iam.user.assign |
角色區塊的新增、編輯期間、移除 |
is_admin(超級管理員 JWT 旗標) |
額外可在編輯他人帳號時代改密碼;admin 帳號本身的生效/到期日與所屬鎖死 |
沒有 iam.user.read |
無此選單 |
⚠️ route 命名陷阱:FE
views/user-manage/UserForm.vue(463 行)是死碼——router 中對應的/auth/user-formroute 已整段註解掉(config/router/index.js:138-145)。目前user-form(name)這個路由名實際指向/auth/user-form-mtrbac→UserMTRBACForm.vue(641 行,multi-tenant RBAC 版表單),本 spec 全部以此為準,不描述UserForm.vue的行為。
1.1 功能總覽(本頁全部功能)¶
| # | 功能 | 說明 | 位置 | 詳述 |
|---|---|---|---|---|
| 1 | 帳號基本欄位 | 登入名稱*(新增後不可改)/ 姓名* / Email* / 職稱 / 電話 | 表單頁上半 | §6.2 |
| 2 | 帳號生效 / 到期日 | 日期選擇器;admin 帳號固定禁用 |
表單頁上半 | §4 |
| 3 | 變更密碼(管理員代改) | 僅登入者本身 is_admin 時顯示開關;開啟後顯示密碼 / 確認密碼欄 |
表單頁上半(編輯模式限定) | §4 |
| 4 | 所屬租戶與部門 | 帳號屬於哪些租戶、部門;隨「儲存」整批替換 | 表單頁中段 | §6.2 |
| 5 | 角色列(新增帳號) | 角色+期間,可多列;隨「建立」送出 | 表單頁下段 | UC-USER-02 |
| 6 | 角色指派表(編輯帳號) | 租戶/角色/部門/生效/到期/狀態;每列「編輯期間」「移除角色」,各自存檔 | 表單頁下段 | UC-USER-02 |
| 7 | 新增角色(編輯帳號) | 開指派對話框(人已選好):角色、期間、可見選單預覽 | 角色區塊表頭 | UC-USER-02 |
| 8 | 儲存帳號 | 送基本欄位+所屬租戶與部門;編輯時不送角色 | 表單頁 | UC-USER-01 |
| 9 | 取消編輯 | 二次確認後返回列表 | 表單頁 | — |
展開成 UC:UC-USER-01(建立 / 編輯帳號主流程)、UC-USER-02(帳號頁的角色)。停用 / 刪除 / 列表操作屬 使用者管理 hub。
2. Use Case¶
角色速覽(完整定義見 _overview §2、§3):
| 角色 | 一句話 |
|---|---|
持 iam.user.create/iam.user.update |
新增/編輯帳號基本資料、所屬租戶與部門 |
另持 iam.user.assign |
角色區塊的新增、編輯期間、移除 |
is_admin(超級管理員 JWT 旗標) |
額外可在編輯他人帳號時代改密碼;admin 帳號本身的生效/到期日與所屬鎖死 |
沒有 iam.user.read |
無此選單 |
流程圖視覺慣例:菱形 = 判斷、橘底 = 例外/擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點。
UC-USER-01 建立 / 編輯帳號¶
| 項目 | 內容 |
|---|---|
| 角色 | 具本頁可見性的管理員 |
| 前置條件 | 新增:login_name / email 未被使用;編輯:帳號存在 |
| 產出 / 後置條件 | public.users 新增 / 更新一列 + user_tenants / user_org_units 整批替換;新增時另建 user_roles,編輯時 user_roles 不動 |
UC-USER-02 帳號頁的角色¶
| 項目 | 內容 |
|---|---|
| 角色 | 持 iam.user.assign |
| 前置條件 | 新增:先選所屬租戶才能挑角色;編輯:帳號已存在 |
| 產出 / 後置條件 | 新增:隨建立帳號寫入 user_roles(scope=tenant);編輯:各動作立即寫入 user_roles,不經帳號儲存 |
flowchart TD
A{"新增或編輯?"} -- 新增 --> B["角色列:角色+期間<br/>選項限第一個所屬租戶"]
B --> C["按 建立:POST /user 帶 user_roles"]
A -- 編輯 --> D["指派表:POST /role-assignments(filters.user_uid)"]
D --> E["新增角色/編輯期間/移除<br/>POST・PUT・DELETE /role-assignment"]
E --> F["只刷新角色表,不覆蓋表單上未存的欄位"]
D --> G{"能讀指派列表?"}
G -- 否 --> H["退回帳號 API 的摘要:只列角色與租戶,沒有期間"]
規則與錯誤碼同 指派(期間不可顛倒、同角色期間不可重疊、須是租戶成員、原廠管理員至少留一筆有效指派)。
3. 權限矩陣¶
專案層 RBAC 基調見 _overview §5。本頁的實際檢查點:
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 進入(新增) | user-form 綁 iam.user.create(ALL) |
— | — |
| 進入(編輯) | user-form 綁 iam.user.update(ANY) |
讀他人明細需 iam.user.read;讀自己放行 |
jedi-iam api/routes/user_route.py(UserRoute.get) |
| 建立帳號 | 儲存鈕 v-can iam.user.create/update |
iam.user.create;帶 user_roles 另需 iam.user.assign |
user_route.py(UserCreateRoute.post)、role_assignment_service.py(assert_can_change_user_roles) |
| 編輯帳號 | 同上 | iam.user.update;user_roles 與現況不同才另要 iam.user.assign;原廠管理員帳號另有保護 |
user_route.py(UserRoute.put) |
| 角色區塊新增/編輯/移除 | v-can iam.user.assign |
iam.user.assign |
role_assignment_route.py |
| 代改他人密碼 | 僅登入者 userInfo.is_admin 時顯示開關 |
有:非超級管理員改他人密碼會被 can_change_password 擋下 |
jedi-iam user_service.py(update_user) |
| 改自己密碼 | 個人資料頁另一條路徑(見 個人資料),非本頁 | — | — |
缺權限回 403 GRC_403022,畫面顯示「使用者不具備此操作所需的權限(需要權限:<權限名>)」。只有 iam.user.update 的人改暱稱、電話不會被要求 iam.user.assign——存帳號不送角色,送了且與現況相同也不檢查。
4. 狀態機與前置條件¶
帳號本身狀態(users.status)與列表操作 gate 見 使用者管理 §4。本表單頁 gate:
| 條件 | 效果 | 出處 |
|---|---|---|
login_name === 'admin'(表單內) |
生效日 / 到期日 Calendar 禁用;所屬租戶與部門禁用 | UserMTRBACForm.vue(isTargetAdmin) |
mode === 'EDIT' |
登入名稱欄位鎖死(不可改) | UserMTRBACForm.vue:434 |
userInfo.is_admin && mode === 'EDIT' |
顯示「變更密碼」開關;非 admin 登入者看不到此區塊(僅能改自己密碼,走 user-profile 頁) | UserMTRBACForm.vue:502 |
canEdit(currUser) = mode==ADD \|\| userInfo.is_admin \|\| userInfo.uid===currUser.uid |
姓名 / Email 欄位可編輯性 | UserMTRBACForm.vue:299-310 |
| 新增帳號尚未選所屬租戶 | 角色列無法加(提示「先選所屬租戶,才能挑角色」) | UserInitialRolePicker.vue |
| 新增帳號換第一個所屬租戶 | 不屬於新租戶的角色列被移除並提示名稱 | UserInitialRolePicker.vue |
| 編輯帳號、沒有讀指派的權限 | 角色表退回帳號 API 的摘要(只有角色與租戶,沒有期間) | UserRoleSummary.vue |
| 授權到期唯讀 | 寫入鈕停用 | useLicenseReadonly |
| BE 寫入無狀態前置檢查 | add_user / update_user 本身不檢查 status,任何狀態的帳號都可被改(唯一狀態轉換在 update_user_status 專職) |
jedi-auth user_service.py |
5. UI 設計¶
由上而下:基本欄位(編輯限定另有「變更密碼」開關)→ 所屬租戶與部門 → 角色(新增:角色列;編輯:指派表+「新增角色」)→ 取消/儲存。角色的新增與編輯期間是對話框。
📸 版面圖與實機截圖待補(亮色模式):新增帳號(含角色列)、編輯帳號(含角色指派表)、新增角色對話框、admin 帳號鎖死狀態。
狀態呈現:表單頁儲存 / 讀取中蓋一層全螢幕遮罩 + ProgressSpinner(submitted / loading 兩個獨立旗標,避免進頁誤顯示「儲存中」)。
6. API 規格¶
Envelope:成功 {"code": 1, "data": …}、失敗 {"code": 0, "msg": "…"}。
6.1 總清單(本頁呼叫的全部 endpoint)¶
| 分類 | Method + Path | 說明 | 完整規格 |
|---|---|---|---|
| 明細 | GET /api/1.0/user/<uid> |
單一使用者(含 auth_providers,排除 salt/password) | §6.2 |
| 建立 | POST /api/1.0/user |
建立使用者(可帶角色列) | §6.2 |
| 更新 | PUT /api/1.0/user/<uid> |
更新使用者、所屬租戶與部門(可選帶密碼);不帶 user_roles |
§6.2 |
| 角色 | POST /role-assignments・POST /role-assignment・PUT/DELETE /role-assignment/<id> |
編輯帳號的角色指派表 | 指派 §6 |
| 下拉資料 | GET /tenants/menu・/org-units/menu・/roles/menu |
所屬租戶與部門、角色下拉 | GAI-SD-02 |
列表 / 狀態變更 / 刪除 / Excel 匯入端點見 使用者管理 §6 與 Excel 批次匯入 §6。
6.2 使用者 CRUD(request / response)¶
[GET] /api/1.0/user/¶
Response:UserResponse(exclude salt/password),額外含 auth_providers[](UserAuthProviderResponse)。欄位卡見 使用者管理 §6.2 列表回傳。出處:user_route.py:57-73。
[POST] /api/1.0/user(建立)/ [PUT] /api/1.0/user/(更新)¶
Request(UserRequest,api/auth/serializers/user.py:5-19):
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
login_name |
string | 是 | 登入代碼(建立後不可改,FE 鎖死) |
email |
string | 是 | Email(重複會 409) |
nickname |
string | 否(FE 端 required) | 顯示名稱 |
job_title / tel |
string | 否 | 職稱 / 電話 |
password |
string | 否 | 有值才觸發改密碼流程 |
effective_date / expire_date |
datetime YYYY-MM-DD HH:MM:SS |
否 | 帳號生效 / 到期日 |
user_roles |
list[UserRoleRequest] |
否 | 新增時才送:{role_uid, tenant_id, scope:'tenant', starts_at, ends_at, is_default}。沒送=不動指派;送空清單=清空全部指派 |
tenants |
list[int] | 是(一定要送) | 所屬租戶,整批替換 user_tenants;漏送=把人移出所有租戶 |
org_units |
list[int] | 是(一定要送) | 所屬部門,整批替換 user_org_units |
status |
int | 否(僅編輯回填顯示,非本頁編輯欄位) |
Response:同 GET(exclude salt/password/last_login_success_time/last_login_failed_time)。
BE 鏈路:jedi-iam UserCreateRoute.post/UserRoute.put(api/routes/user_route.py)→ jedi-iam UserService.add_user / update_user(app/service/user_service.py)。關鍵行為:
- 新增時第一個所屬租戶為使用者的預設租戶(
user_entity.tenant_id) tenants/org_units在update_user時整批替換;user_roles以「鍵在不在」決定:沒送不動,有送才同步(sync_user_roles)- 新增時若
password未帶,generate_complex_password(12)自動產生亂碼密碼,寄送帳號建立通知信(含明碼密碼,僅信件內、不落 log;user_service.py:102-104明確禁止把含密碼的 kwargs 整包 dump 進 log) - 編輯改密碼:非
is_admin呼叫者會先過can_change_password(curr_user.uid, uid)(只能改自己),並寫入user_change_pwd_logs - 檢核順序:
login_name重複 →email重複 → 租戶存在 → 部門存在 → 角色存在(uid 清單)
出處:jedi-iam app/service/user_service.py(add_user、update_user)。
7. 前端檔案地圖(compliance-manager-fe/)¶
| 檔案 | 角色 |
|---|---|
src/views/user-manage/UserMTRBACForm.vue |
route user-form(實際掛在 /auth/user-form-mtrbac):建立 / 編輯共用表單 |
src/components/user-manage/UserMembershipEditor.vue |
所屬租戶與部門 |
src/components/user-manage/UserInitialRolePicker.vue、UserInitialRoleDialog.vue |
新增帳號的角色列 |
src/components/user-manage/UserRoleSummary.vue |
編輯帳號的角色指派表(用 指派 的 API 與 AssignmentDialog.vue) |
src/views/user-manage/UserForm.vue |
⚠️ 死碼:無任何 route 指向,router 對應項已整段註解(見 §1) |
src/config/router/index.js |
/auth 群組:user-manage / user-form(→UserMTRBACForm.vue);舊 role-manage / role-form 轉址到存取管理 |
src/stores/menuStore.js |
fetchRoleMenu() / tenantMenu / orgUnitMenu(下拉來源) |
src/utils/userUtil.js |
userInfo(含 is_admin / uid / login_name,供本頁多處權限判斷) |
src/config/api/api.js:32-42 |
USER / ROLE_MENU 等端點常數 |
8. 後端檔案地圖¶
| 鏈路 | Route | App Service | 底層 |
|---|---|---|---|
| 使用者 CRUD | jedi-iam api/routes/user_route.py(UserCreateRoute、UserRoute) |
jedi-iam user_service.py;守門前置 role_assignment_service.assert_can_change_user_roles、宿主 user_app_service(原廠管理員保護) |
jedi-iam user_domain_service.py → repo |
| 忘記密碼 / 改密請求 | api/auth/routes/change_password_route.py |
直接委派 | jedi-auth user_change_password_service.py |
DDD 提醒:使用者 CRUD 的 route 與 service 在 jedi-iam 套件(~/Projects/Jedicogy/module/jedi-python-package/jedi-iam/),改行為要分清邊界(CLAUDE.md 外部套件異動規範)。
9. DB¶
9.1 資料表總清單(本頁讀寫的全部表)¶
| 表 | 讀/寫 | 說明 | 詳述 |
|---|---|---|---|
public.users |
讀 / 寫 | 帳號本體(含 salt/password,敏感欄位僅描述不列值) | §9.3 |
public.user_roles |
讀 / 寫(新增帳號時建;編輯帳號時由角色指派表逐筆寫) | 使用者 ↔ 角色指派 | §9.3 |
public.user_tenants |
讀 / 寫(整批替換) | 使用者 ↔ 租戶(is_default) |
_overview §3 |
public.user_org_units |
讀 / 寫(整批替換) | 使用者 ↔ 部門(is_primary) |
_overview §3 |
public.user_change_password_request |
寫 | 新增帳號時建立首次註冊改密請求(type=FIRST_REGISTER) |
§9.3 |
public.user_change_pwd_logs |
寫 | 管理員代改密碼時寫入歷史 | §9.3 |
public.user_auth_providers |
讀 | 使用者第三方登入綁定(GET 明細帶出,本頁不維護寫入) | §9.3 |
public.roles |
讀 | 角色下拉、verify_role_exist_by_uids 檢核 |
角色明細 §9 |
public.tenants |
讀 | 租戶下拉、verify_tenant_exist_by_id 檢核 |
_overview §6 |
public.org_units |
讀 | 部門下拉、verify_org_unit_exist_by_id 檢核 |
_overview §6 |
9.2 ER 圖¶
9.3 核心表欄位(取自 DEV DB dump,含 DB comment)¶
public.users — 帳號本體¶
| 欄位 | 型別 | 說明 |
|---|---|---|
| id / uid | integer / varchar(36) | 內部序號 / 對外識別碼 |
| login_name | varchar(255) | 登入名稱(唯一,建立後不可改) |
| nickname | varchar(255) | 顯示名稱 |
| salt / password | varchar(250) | 密碼鹽值 / 加密密碼(敏感欄位,僅描述存在,不列值;API response 一律 exclude=["salt","password"]) |
| varchar(100) | 電子郵件(唯一) | |
| job_title / tel | varchar(100) / varchar(50) | 職稱 / 電話(皆選填) |
| effective_date / expire_date | timestamp | 帳號生效 / 到期日 |
| status | integer | 0 未啟用 / 1 啟用 / -1 停用 / -2 刪除 |
| last_login_success_time / last_login_failed_time / login_failed_count | timestamp / timestamp / integer | 登入軌跡(列表可排序顯示) |
| mfa_type | varchar(50) | 多因素驗證類型(TOTP 設定見 個人資料) |
| topt_secret | text | TOTP 密鑰(敏感欄位;命名沿用套件既有拼法,非本頁 typo) |
| is_super_admin | boolean | 超級管理員旗標(DB 欄位;JWT context 的 is_admin 由此衍生) |
| tenant_id / org_unit_id | integer | 使用者的預設租戶 / 部門 |
| employee_id | varchar(20) | 員工編號(選填,表單無對應輸入欄,僅 API 層可帶) |
| created_user / created_at / updated_user / updated_at | varchar(50) / timestamp | 審計欄 |
public.user_roles — 角色指派¶
| 欄位 | 型別 | 說明 |
|---|---|---|
| id | bigint | 主鍵 |
| user_id / role_id | integer | → users / roles |
| scope | varchar | tenant/org_unit;畫面一律建 tenant(部門範圍判定上與整租戶相同) |
| tenant_id / org_unit_id | integer(nullable) | 範圍 |
| starts_at / ends_at | timestamptz | 有效期間;ends_at 空=永久 |
| is_default | boolean | 保留欄位,畫面不顯示、判定不讀 |
public.user_tenants / public.user_org_units — 租戶 / 部門歸屬¶
user_tenants:user_id / tenant_id / is_default / starts_at / ends_at;user_org_units:user_id / org_unit_id / is_primary / starts_at / ends_at。兩表在 update_user 時依送來的 tenants/org_units 整批替換(非差異更新);指派頁只接受已是成員的租戶(AUTH_400014),加入新租戶只能從本頁。
public.user_change_password_request / public.user_change_pwd_logs¶
user_change_password_request:uid / user_id / type(0 首次註冊 / 1 密碼重設 / 2 忘記密碼 / 3 密碼過期 / 9 自行變更)/ status(0 未使用 / 1 已使用)/ expired;新增使用者時固定建一筆 type=FIRST_REGISTER、7 天後過期。user_change_pwd_logs:user_id / type / password(加密後);僅管理員代改密碼成功時寫入一筆。
public.user_auth_providers(唯讀)¶
uid / user_id / provider / provider_user_id:第三方登入綁定,本頁 GET 明細會回傳但無編輯 UI。
10. 頁面邏輯與資料對應¶
表單載入時序:
onMounted → 載入租戶、部門、角色下拉 → 有 uid 則 GET /user/<uid>(tenants/org_units/user_roles 為 null 時補成空陣列)→ 編輯模式角色表另打 POST /role-assignments(filters.user_uid、含已到期)。
關鍵欄位對應(API ↔ 畫面):
| 畫面元素 | FE state | API 欄位 |
|---|---|---|
| 登入名稱 / 姓名 / Email / 職稱 / 電話 | currUser.login_name/nickname/email/job_title/tel |
UserRequest 同名欄位 |
| 生效日 / 到期日 | currUser.effective_date/expire_date(Calendar,自訂格式化) |
同名,送出前補 00:00:00 |
| 所屬租戶與部門 | currUser.tenants[] / currUser.org_units[] |
payload.tenants / payload.org_units(id 陣列) |
| 角色列(新增) | initialRoleRows[] |
payload.user_roles[]({role_uid, tenant_id, scope:'tenant', starts_at, ends_at, is_default},第一列 is_default=true) |
| 角色指派表(編輯) | UserRoleSummary 自己的列表 |
指派 API,不進帳號 payload |
| 變更密碼開關 + 密碼欄 | currSecret.secret/confirm_secret |
payload.password(僅有值才附帶) |
儲存流程:表單整包送出(非逐欄位獨立儲存,不同於專案規劃頁);onSaveClick 先跑 vuelidate(基本欄位必填 + 密碼強度規則:≥12 碼、含大小寫與數字),通過才組 payload 呼叫 POST /user(新增)或 PUT /user/<uid>(編輯);成功後導回列表(router.push({name:'user-manage'}))。
錯誤對應:BE error envelope → toast 顯示;常見碼:AUTH_409001(login_name 已存在)、AUTH_409002(email 已存在)、AUTH_404005(租戶不存在)、AUTH_404004(部門不存在)、AUTH_404003(角色不存在)、GRC_403022(缺權限,附缺的權限名)。
11. 背景行為與外部依賴¶
| 類型 | 內容 |
|---|---|
| 通知 | 新增帳號成功 → 寄送帳號建立信(含登入名稱 + 明碼密碼,僅信件內容,不落 log);notification_service 為 optional 注入,未設定時靜默跳過 |
| Job / 排程 | 無 |
| Socket | 無 |
| jedi-* 套件 | jedi-iam 擁有使用者 / 角色 / 指派 / 租戶 / 部門的 service / domain / repo / ORM |
| 密碼規則 | 新增未帶密碼 → generate_complex_password(12) 產生亂碼;FE 端管理員代改密碼強制 ≥12 碼 + 大小寫 + 數字(vuelidate secretRules),BE 本身無獨立密碼強度檢查(僅 hash 儲存) |
12. 邊界情況與已知坑¶
UserForm.vue是死碼:463 行完整表單元件,但 router 對應/auth/user-formroute 整段被註解、無任何 import 引用;實際生效的是UserMTRBACForm.vue(multi-tenant RBAC 版)。維護時勿誤改死碼。user_roles以「鍵在不在」判斷:沒送=不動指派;送空清單=清空全部指派。後端不可改成kwargs.get("user_roles") or []——那會把「改電話」也當成清空角色,存一次帳號指派的到期日就被洗掉。tenants/org_units一定要送:後端整批替換,漏送=把人移出所有租戶與部門。- 帳號頁的角色動作不經「儲存」:新增角色、編輯期間、移除各自立即寫入;按「取消」不會撤回這些動作。
- Excel 批次匯入帳號維持每人一個角色、整個租戶、永久;要多角色或期限,匯入後到本頁或 指派 補。
- 敏感欄位(
salt/password/topt_secret)一律 exclude:GET/POST/PUT response 都手動UserResponse(exclude=["salt","password", ...]),新增回傳欄位或改 serializer 務必保留這個 exclude list,避免意外外洩雜湊密碼。 nickname在 BE serializer 非 required,但 FE vuelidate 端強制必填:兩端必填集合不完全對稱(BEUserRequest.nickname無required=True),直打 API 可送出無nickname的使用者。admin帳號的鎖死規則:畫面以login_name==='admin'禁用生效/到期日與所屬;後端另以原廠管理員保護擋「改完後沒有有效的原廠管理員指派」與刪除。
13. 開發與驗證¶
- 跑起來:BE
python main.py(port 8000,log 在log/app.log);FE 在compliance-manager-fe/起 Vite dev server。BE 改 service code 後必須重啟(無 hot reload)。 - 測試帳號:管理員帳號見 memory
reference_dev_login/.env(憑證不寫入本文件)。 - 導航路徑:登入 → 側選單「系統管理」→「使用者管理」(
/auth/user-manage)→ 建立 / 點某列「編輯」進表單頁。 - 前置資料:至少一個租戶與一個該租戶的角色,才能在新增帳號時加角色列。
- E2E:
compliance-manager-test/repo(Cucumber + Playwright);本頁相關 feature 檔以使用者管理/user-form搜尋。 - 相關文件:上層導航 使用者管理;Excel 批次匯入;指派;角色明細;功能群總覽。