# User Authentication & Authorization ## Purpose 使用者認證與授權系統,透過外部認證 API 進行身份驗證,提供細部權限控制。 ## Requirements ### Requirement: API-Based Authentication 系統 SHALL 限定使用外部認證 API (https://pj-auth-api.vercel.app) 進行登入認證,不支援其他認證方式。 #### Scenario: API 登入成功 - **GIVEN** 使用者擁有有效的企業帳號 - **WHEN** 使用者透過前端提交憑證 - **THEN** 系統呼叫 https://pj-auth-api.vercel.app 驗證憑證 - **AND** 驗證成功後建立 session 並回傳 JWT token #### Scenario: API 登入失敗 - **GIVEN** 使用者提供無效的憑證 - **WHEN** 使用者嘗試登入 - **THEN** 認證 API 回傳錯誤 - **AND** 系統拒絕登入並顯示錯誤訊息 - **AND** 記錄失敗的登入嘗試 #### Scenario: 認證 API 無法連線 - **GIVEN** 認證 API 服務無法連線 - **WHEN** 使用者嘗試登入 - **THEN** 系統顯示服務暫時無法使用的訊息 - **AND** 記錄連線失敗事件 ### Requirement: System Administrator 系統 SHALL 預設一個系統管理員帳號,擁有所有權限。系統管理員帳號必須存在於外部認證系統,且登入流程仍需透過外部認證 API;不允許本地繞過認證。 #### Scenario: 預設管理員帳號 - **GIVEN** 系統初始化完成 - **WHEN** 系統啟動 - **THEN** 存在預設管理員帳號 `ymirliu@panjit.com.tw` - **AND** 該帳號擁有 `super_admin` 角色 - **AND** 該帳號不可被刪除或降級 #### Scenario: 管理員登入流程 - **GIVEN** 管理員帳號 `ymirliu@panjit.com.tw` 需要登入 - **WHEN** 管理員提交憑證 - **THEN** 系統仍需呼叫 https://pj-auth-api.vercel.app 驗證 - **AND** 不存在任何本地繞過認證的機制 - **AND** 驗證成功後才授予 `super_admin` 權限 #### Scenario: 管理員全域權限 - **GIVEN** 管理員帳號 `ymirliu@panjit.com.tw` 已通過 API 認證並登入 - **WHEN** 管理員存取任何資源 - **THEN** 系統允許存取,無視部門隔離限制 ### Requirement: Role-Based Access Control 系統 SHALL 支援基於角色的存取控制 (RBAC)。 #### Scenario: 角色權限檢查 - **GIVEN** 使用者被指派特定角色 (如:工程師、主管、PMO) - **WHEN** 使用者嘗試存取受保護的資源 - **THEN** 系統根據角色權限決定是否允許存取 #### Scenario: 角色指派 - **GIVEN** 管理員擁有使用者管理權限 - **WHEN** 管理員為使用者指派角色 - **THEN** 系統更新使用者的角色設定 - **AND** 新權限立即生效 ### Requirement: Department Isolation 系統 SHALL 實施部門級別的資料隔離,確保跨部門資料安全。 #### Scenario: 部門資料隔離 - **GIVEN** 使用者屬於研發部門 - **WHEN** 使用者嘗試存取廠務部門的專案 - **THEN** 系統拒絕存取並顯示無權限訊息 #### Scenario: 跨部門專案存取 - **GIVEN** 專案被設定為跨部門可見 - **WHEN** 不同部門的使用者嘗試存取該專案 - **THEN** 系統根據專案的 Security_Level 設定決定是否允許存取 ### Requirement: Session Management 系統 SHALL 管理使用者 session,包含過期與登出機制。 #### Scenario: Session 過期 - **GIVEN** 使用者已登入系統 - **WHEN** Session 超過設定的有效期限 - **THEN** 系統自動使 session 失效 - **AND** 使用者需重新登入 #### Scenario: 主動登出 - **GIVEN** 使用者已登入系統 - **WHEN** 使用者執行登出操作 - **THEN** 系統銷毀 session 並清除 token ## Data Model ``` pjctrl_users ├── id: UUID (PK) ├── email: VARCHAR(200) UNIQUE ├── name: VARCHAR(200) ├── department_id: UUID (FK) ├── role_id: UUID (FK) ├── skills: JSON ├── capacity: DECIMAL (週工時上限) ├── is_active: BOOLEAN ├── is_system_admin: BOOLEAN DEFAULT false (不可修改的系統管理員標記) ├── created_at: TIMESTAMP └── updated_at: TIMESTAMP pjctrl_departments ├── id: UUID (PK) ├── name: VARCHAR(100) ├── parent_id: UUID (FK, self-reference) └── created_at: TIMESTAMP pjctrl_roles ├── id: UUID (PK) ├── name: VARCHAR(50) ├── permissions: JSON ├── is_system_role: BOOLEAN DEFAULT false └── created_at: TIMESTAMP ``` ## Default Data (Seed) ```sql -- 預設系統管理員角色 INSERT INTO pjctrl_roles (id, name, permissions, is_system_role) VALUES ('00000000-0000-0000-0000-000000000001', 'super_admin', '{"all": true}', true); -- 預設系統管理員帳號 INSERT INTO pjctrl_users (id, email, name, role_id, is_active, is_system_admin) VALUES ('00000000-0000-0000-0000-000000000001', 'ymirliu@panjit.com.tw', 'System Administrator', '00000000-0000-0000-0000-000000000001', true, true); ``` ## External Dependencies - **Authentication API**: https://pj-auth-api.vercel.app (唯一認證方式) ## Authentication Flow ``` ┌─────────┐ ┌─────────────┐ ┌──────────────────────────┐ │ User │────▶│ Frontend │────▶│ pj-auth-api.vercel.app │ └─────────┘ └─────────────┘ └──────────────────────────┘ │ │ │◀────── JWT Token ───────│ │ ▼ ┌─────────────┐ │ Backend │ (驗證 JWT, 建立 Session) └─────────────┘ ```