feat: Implement role-based access control (RBAC) with 3-tier authorization

- Add 3 user roles: user, admin, super_admin
- Restrict LLM config management to super_admin only
- Restrict audit logs and statistics to super_admin only
- Update AdminPage with role-based tab visibility
- Add complete 5 Why prompt from 5why-analyzer.jsx
- Add system documentation and authorization guide
- Add ErrorModal component and seed test users script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
donald
2025-12-08 19:29:28 +08:00
parent 957003bc7c
commit 66cdcacce9
11 changed files with 1791 additions and 158 deletions

279
分層授權.md Normal file
View File

@@ -0,0 +1,279 @@
# 5 Why 根因分析系統 - 分層授權設計
**版本**: 1.0.0
**更新日期**: 2025-12-08
---
## 1. 角色定義
系統定義三個權限層級:
| 層級 | 角色代碼 | 角色名稱 | 說明 |
|------|----------|----------|------|
| L1 | `user` | 一般使用者 | 僅能使用分析功能,管理自己的資料 |
| L2 | `admin` | 管理員 | 可管理使用者、查看所有分析、配置 LLM |
| L3 | `super_admin` | 超級管理員 | 擁有所有權限,包括刪除使用者、系統級操作 |
---
## 2. 權限矩陣
### 2.1 分析功能 (`/api/analyze`)
| 功能 | API 端點 | user | admin | super_admin |
|------|----------|:----:|:-----:|:-----------:|
| 建立分析 | `POST /` | ✅ | ✅ | ✅ |
| 翻譯分析 | `POST /translate` | ✅ | ✅ | ✅ |
| 查看自己的歷史 | `GET /history` | ✅ | ✅ | ✅ |
| 查看自己的分析 | `GET /:id` | ✅ | ✅ | ✅ |
| 查看他人的分析 | `GET /:id` | ❌ | ✅ | ✅ |
| 刪除自己的分析 | `DELETE /:id` | ✅ | ✅ | ✅ |
| 刪除他人的分析 | `DELETE /:id` | ❌ | ✅ | ✅ |
### 2.2 使用者管理 (`/api/admin/users`)
| 功能 | API 端點 | user | admin | super_admin |
|------|----------|:----:|:-----:|:-----------:|
| 查看使用者列表 | `GET /users` | ❌ | ✅ | ✅ |
| 建立使用者 | `POST /users` | ❌ | ✅ | ✅ |
| 編輯使用者 | `PUT /users/:id` | ❌ | ✅ | ✅ |
| 停用使用者 (軟刪除) | `PUT /users/:id` | ❌ | ✅ | ✅ |
| 刪除使用者 (硬刪除) | `DELETE /users/:id` | ❌ | ❌ | ✅ |
### 2.3 LLM 配置管理 (`/api/llm-config`)
| 功能 | API 端點 | user | admin | super_admin |
|------|----------|:----:|:-----:|:-----------:|
| 查看 LLM 配置列表 | `GET /` | ✅ | ✅ | ✅ |
| 查看啟用的配置 | `GET /active` | ✅ | ✅ | ✅ |
| 新增 LLM 配置 | `POST /` | ❌ | ❌ | ✅ |
| 編輯 LLM 配置 | `PUT /:id` | ❌ | ❌ | ✅ |
| 啟用 LLM 配置 | `PUT /:id/activate` | ❌ | ❌ | ✅ |
| 刪除 LLM 配置 | `DELETE /:id` | ❌ | ❌ | ✅ |
| 測試 LLM 連線 | `POST /test` | ❌ | ❌ | ✅ |
### 2.4 系統管理 (`/api/admin`)
| 功能 | API 端點 | user | admin | super_admin |
|------|----------|:----:|:-----:|:-----------:|
| 查看儀表板 | `GET /dashboard` | ❌ | ✅ | ✅ |
| 查看所有分析記錄 | `GET /analyses` | ❌ | ✅ | ✅ |
| 查看稽核日誌 | `GET /audit-logs` | ❌ | ❌ | ✅ |
| 查看系統統計 | `GET /statistics` | ❌ | ❌ | ✅ |
### 2.5 帳號功能 (`/api/auth`)
| 功能 | API 端點 | user | admin | super_admin |
|------|----------|:----:|:-----:|:-----------:|
| 登入 | `POST /login` | ✅ | ✅ | ✅ |
| 登出 | `POST /logout` | ✅ | ✅ | ✅ |
| 查看自己的資料 | `GET /me` | ✅ | ✅ | ✅ |
| 修改自己的密碼 | `POST /change-password` | ✅ | ✅ | ✅ |
---
## 3. 中介層實作
### 3.1 現有中介層 (`middleware/auth.js`)
```javascript
// L1: 一般使用者 - 僅需登入
export function requireAuth(req, res, next)
// L2: 管理員 - 需要 admin 或 super_admin 角色
export function requireAdmin(req, res, next)
// L3: 超級管理員 - 僅允許 super_admin 角色
export function requireSuperAdmin(req, res, next)
// 資源擁有權檢查 - 一般使用者只能存取自己的資源
export function requireOwnership(resourceUserIdParam)
```
### 3.2 權限檢查流程
```
請求進入
┌─────────────────┐
│ requireAuth │ ─── 未登入 ──→ 401 Unauthorized
└────────┬────────┘
│ 已登入
┌─────────────────┐
│ requireAdmin? │ ─── 角色不符 ──→ 403 Forbidden
│ requireSuper? │
└────────┬────────┘
│ 權限通過
┌─────────────────┐
│ requireOwnership│ ─── 非本人且非管理員 ──→ 403 Forbidden
└────────┬────────┘
│ 全部通過
執行業務邏輯
```
---
## 4. 測試帳號
| 角色 | Email | 密碼 | 工號 |
|------|-------|------|------|
| super_admin | admin@example.com | Admin@123456 | ADMIN001 |
| admin | manager@example.com | Manager@123456 | MGR001 |
| user | user001@example.com | User@123456 | EMP001 |
| user | user002@example.com | User@123456 | EMP002 |
---
## 5. 前端頁面權限控制
### 5.1 導航選單顯示
| 選單項目 | user | admin | super_admin |
|----------|:----:|:-----:|:-----------:|
| 5 Why 分析 | ✅ | ✅ | ✅ |
| 分析歷史 | ✅ | ✅ | ✅ |
| 管理員面板 | ❌ | ✅ | ✅ |
### 5.2 管理員面板標籤頁
| 標籤頁 | admin | super_admin |
|--------|:-----:|:-----------:|
| 儀表板 | ✅ | ✅ |
| 使用者管理 | ✅ | ✅ |
| 分析記錄 | ✅ | ✅ |
| LLM 配置 | ✅ | ✅ |
| LLM 測試台 | ✅ | ✅ |
| 稽核日誌 | ✅ | ✅ |
### 5.3 操作按鈕顯示
| 操作 | admin | super_admin |
|------|:-----:|:-----------:|
| 新增使用者 | ✅ | ✅ |
| 編輯使用者 | ✅ | ✅ |
| 停用使用者 | ✅ | ✅ |
| 刪除使用者 | ❌ | ✅ |
---
## 6. 資料庫角色欄位
### 6.1 users 表結構
```sql
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
employee_id VARCHAR(50) UNIQUE,
username VARCHAR(100),
email VARCHAR(255) UNIQUE,
password_hash VARCHAR(255),
role ENUM('user', 'admin', 'super_admin') DEFAULT 'user',
department VARCHAR(100),
position VARCHAR(100),
is_active TINYINT(1) DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login_at TIMESTAMP
);
```
### 6.2 角色值說明
| role 值 | 說明 |
|---------|------|
| `user` | 一般使用者,預設值 |
| `admin` | 管理員 |
| `super_admin` | 超級管理員 |
---
## 7. Session 結構
登入成功後Session 中儲存以下資訊:
```javascript
req.session = {
userId: 123, // 使用者 ID
userRole: 'admin', // 角色代碼
employeeId: 'EMP001', // 工號
username: '王小明' // 使用者名稱
}
```
---
## 8. 權限擴展建議
### 8.1 未來可考慮的權限細分
| 權限代碼 | 說明 | 建議角色 |
|----------|------|----------|
| `analysis.create` | 建立分析 | user, admin, super_admin |
| `analysis.view.own` | 查看自己的分析 | user, admin, super_admin |
| `analysis.view.all` | 查看所有分析 | admin, super_admin |
| `analysis.delete.own` | 刪除自己的分析 | user, admin, super_admin |
| `analysis.delete.all` | 刪除所有分析 | admin, super_admin |
| `user.manage` | 管理使用者 | admin, super_admin |
| `user.delete` | 刪除使用者 | super_admin |
| `llm.configure` | 配置 LLM | admin, super_admin |
| `system.audit` | 查看稽核日誌 | admin, super_admin |
### 8.2 實作 RBAC (Role-Based Access Control)
未來可擴展為更靈活的權限系統:
```
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Users │────▶│ Roles │────▶│Permissions│
└──────────┘ └──────────┘ └──────────┘
│ │ │
│ │ │
user_id role_id permission_id
```
---
## 9. 安全性考量
### 9.1 已實作
- [x] 密碼使用 bcrypt 加密 (cost factor: 10)
- [x] Session-based 認證
- [x] 前後端雙重權限檢查
- [x] 稽核日誌記錄所有敏感操作
- [x] 軟刪除保留資料完整性
### 9.2 建議加強
- [ ] 密碼複雜度驗證
- [ ] 登入失敗次數限制
- [ ] Session 過期時間設定
- [ ] IP 白名單 (管理功能)
- [ ] 雙因素認證 (2FA)
---
## 附錄:快速參考
### 檢查使用者權限的程式碼
```javascript
// 檢查是否為管理員
const isAdmin = ['admin', 'super_admin'].includes(req.session.userRole);
// 檢查是否為超級管理員
const isSuperAdmin = req.session.userRole === 'super_admin';
// 檢查是否為資源擁有者或管理員
const canAccess = resource.user_id === req.session.userId || isAdmin;
```
---
**文件版本**: 1.0.0
**編寫日期**: 2025-12-08
**編寫者**: Development Team