Repository navigation
feat(user-auth-api): 依 auth.md 實作使用者登入(email+密碼,BCrypt)、角色(VIEWER/EDITOR/ADMIN)、CSRF、登入限速與 /users 管理 API,取代 v0.1.0 的共用客服帳密 - #104
Conversation
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0134QMUz6NTfqU8Yrh3BJekj
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0134QMUz6NTfqU8Yrh3BJekj
|
QA:PASS(commit PASS 4dd7a44 user-auth-api 驗證(HEAD 4dd7a44,PR #104)實際執行
逐條檢查
判斷:auth.md §2「未列路徑已認證一律 403」vs FrameworkErrorFormatAcceptanceTest(ADMIN 打未知路徑 404)
其他觀察(不構成 FAIL)
問題數量:0(僅 1 項文件措辭建議) |
|
Code review(architect):CHANGES(commit REQUEST_CHANGES 4dd7a44 user-auth-api code review(PR #104,HEAD 4dd7a44)對照:派工單(含兩則追加)、 要改的問題(2 項)
建議(不擋合併,可同一輪順手處理)
逐項檢查(通過)
qa 提出的 §2「未列路徑」問題:改契約,不改實作
需要改的設計文件(併入設計文件更新單)
契約問題(不擋本單,供 manager 判斷是否列待決定)
|
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0134QMUz6NTfqU8Yrh3BJekj
|
QA:PASS(commit PASS b88b7e0 user-auth-api QA(PR #104,commit b88b7e0)測試指令: 結果摘要: 驗收測試目錄全綠(Failures 0、Errors 0):
輸出中的 Lint/前端指令: 驗收條件對照
review 修正(b88b7e0)確認
備註(非 FAIL)
|
|
Code review(architect):APPROVE(commit APPROVE b88b7e0 user-auth-api code review 第 2 輪(PR #104,HEAD b88b7e0)對照:派工單(範圍以「範圍修正」為準)、 上一輪問題的處理
本輪變更的其他檢查
不擋合併的觀察(併進設計文件更新單)
給下一張後端單:配合 D-071 要怎麼改
|
| 位置 | 現行 | 改成 |
|---|---|---|
§4 PATCH /api/v1/users/{user_id} 表格下方 |
沒有寫 | 新增一條:「請求帶 password 時,該使用者所有現有 session 立即失效,下一個請求回 401 UNAUTHENTICATED(D-071);管理金鑰呼叫時也一樣。只改 display_name/role/status 時 session 不失效(停用與改角色照 §1 在下一個請求生效)」 |
§3 POST /auth/password 的「成功」欄 |
204;其他 session 不登出 |
維持不變,在後面加註「(與 §4 管理員重設不同,見 D-071)」,避免被誤讀成兩者一致 |
| §1 最後一條(session 每個請求都以當下使用者資料判斷) | 停用、改角色 | 加上「管理員重設密碼 → 下一個請求 401(§4)」 |
| 待確認(屬安全政策,交 manager 判斷要不要問甲方) | — | 管理員用 PATCH 重設自己的密碼時,D-071 寫的是「該使用者所有 session 失效」,這樣呼叫者自己目前的 session 也會跟著失效(下一個請求就要重新登入)。建議照字面執行並寫進契約;前端只需要在 PATCH 自己的密碼成功後導向登入頁 |
實作提示(給下一張單的設計參考,非契約內容):session 存在 Tomcat 記憶體裡,沒辦法依使用者列出所有 session。最簡單的做法是在 app_user 加一個 session_epoch(或 password_changed_at)欄位(V7,expand 型的 migration)。登入時把這個值存進 session;SessionAuthenticationFilter.authenticate 本來就會在每個請求重新載入使用者,這時順便比對,值不一致就清掉 session 並回 401。管理員重設密碼時把這個值 +1,而且要跟密碼更新放在同一個交易裡。/auth/password 不動這個值。
|
併入最新 develop( |
Closes #103
派工單:
tasks/user-auth-api.md(負責:backend)Worker 自驗:
docker compose --env-file .env -f .worktrees/user-auth-api/compose.yaml run --rm test;另在 .worktrees/user-auth-api 跑 make check→ exit 0變更檔案:
.env.exampleapi/src/main/java/com/cdp/security/ (改寫 AuthController、SecurityConfig、AuthProperties、AuthPropertiesValidator、Role、LoginRequest、CurrentUserResponse、ApiKeyAuthenticationFilter;新增 AccessRule、Credential、LoginProperties、LoginRateLimiter、PasswordChangeRequest、SessionAuthenticationFilter、SessionCsrfTokenRepository、SessionUser)api/src/main/java/com/cdp/user/ (新:AppUser、AppUserStore、UserService、UserController、PasswordHasher、PasswordPolicy 與請求/回應 record)api/src/main/java/com/cdp/common/web/ErrorCode.java (超出負責檔案,見 open_questions)api/src/main/resources/db/migration/V6__app_user.sqlapi/src/main/resources/application.ymlapi/src/test/resources/application-test.ymltools/demo-seed/seed.pyapi/src/test/java/com/cdp/security/ (ApiKeyAuthenticationFilterTest、AuthControllerTest、AuthPropertiesValidatorTest 改寫;LoginRateLimiterTest、SessionCsrfTokenRepositoryTest 新增)api/src/test/java/com/cdp/user/ (新:PasswordPolicyTest、UserServiceTest)