feat: Initial v0.9 release with API Key authentication
## v0.9.20260325_144654 ### Features - API Key Authentication System - Job Worker System - V2 Backup Versioning ### Bug Fixes - get_processor_results_by_job column mapping Co-authored-by: OpenCode
This commit is contained in:
425
docs/USER_MANAGEMENT_PLAN.md
Normal file
425
docs/USER_MANAGEMENT_PLAN.md
Normal file
@@ -0,0 +1,425 @@
|
||||
# 統一會員系統 + 影片歸屬追蹤實作計畫
|
||||
|
||||
| 項目 | 內容 |
|
||||
|------|------|
|
||||
| 建立者 | Warren |
|
||||
| 建立時間 | 2026-03-24 |
|
||||
| 文件版本 | V1.0 |
|
||||
| 狀態 | 待確認 |
|
||||
|
||||
---
|
||||
|
||||
## 版本歷史
|
||||
|
||||
| 版本 | 日期 | 目的 | 操作人 |
|
||||
|------|------|------|--------|
|
||||
| V1.0 | 2026-03-24 | 創建實作計畫 | OpenCode |
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景與目標
|
||||
|
||||
### 1.1 現有問題
|
||||
|
||||
目前 Momentry 生態系統中,各服務有獨立的用戶管理:
|
||||
|
||||
| 服務 | 用戶系統 | 問題 |
|
||||
|------|----------|------|
|
||||
| WordPress | wp_users (2 admin) | 無會員系統,無 API 認證 |
|
||||
| SFTPGo | users 表 (3 users) | 獨立管理 |
|
||||
| n8n | users 表 | 獨立管理 |
|
||||
| Gitea | `user` 表 | 獨立管理 |
|
||||
| Momentry Core | api_keys (未啟用) | 無 user 關聯 |
|
||||
|
||||
**問題**:
|
||||
1. 無法追蹤影片歸屬(誰上傳的影片)
|
||||
2. 無法實作 per-user 配額管理
|
||||
3. API 端點全部公開,無認證
|
||||
4. 用戶創建需要多處操作
|
||||
|
||||
### 1.2 目標
|
||||
|
||||
建立統一的會員系統,讓 WordPress 成為唯一登入入口:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 目標架構 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ WordPress (會員系統) │
|
||||
│ │ │
|
||||
│ ├─► SFTPGo (檔案上傳) │
|
||||
│ ├─► Momentry Core (影片處理) │
|
||||
│ └─► n8n (自動化流程) │
|
||||
│ │
|
||||
│ 統一的 user_id 追蹤 │
|
||||
│ │ │
|
||||
│ └─► videos 表關聯 user_id │
|
||||
│ └─► monitor_jobs 表關聯 user_id │
|
||||
│ └─► per-user 配額管理 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 現有系統分析
|
||||
|
||||
### 2.1 WordPress
|
||||
|
||||
| 項目 | 狀態 |
|
||||
|------|------|
|
||||
| 安裝插件 | Elementor, Akismet, Code Snippets, All-in-One WP Migration |
|
||||
| 用戶表 | wp_users (2 users: wp_user, sc_demo) |
|
||||
| 會員插件 | 無 |
|
||||
| REST API | 標準端點 (`/wp-json/wp/v2/users`) |
|
||||
| 認證方式 | Cookie / Application Passwords |
|
||||
| JWT | 無 |
|
||||
|
||||
### 2.2 SFTPGo
|
||||
|
||||
| 項目 | 值 |
|
||||
|------|-----|
|
||||
| 用戶數 | 3 (demo, warren, momentry) |
|
||||
| API | REST API v2 (`/api/v2/users`) |
|
||||
| Admin | admin:Test3200Test3200 |
|
||||
| Hook | `/Users/accusys/sftpgo_test/register_hook.sh` |
|
||||
|
||||
### 2.3 Momentry Core
|
||||
|
||||
| 項目 | 狀態 |
|
||||
|------|------|
|
||||
| api_keys 表 | 已存在 |
|
||||
| users 表 | 不存在 |
|
||||
| videos.user_id | 不存在 |
|
||||
| API 認證 | 未啟用(所有端點公開) |
|
||||
|
||||
---
|
||||
|
||||
## 3. 實作計畫
|
||||
|
||||
### Phase 1: WordPress 認證機制啟用
|
||||
|
||||
#### 1.1 啟用 Application Passwords
|
||||
|
||||
**WordPress 5.6+ 內建功能**,無需額外插件。
|
||||
|
||||
```php
|
||||
// wp-config.php (如需自訂設定)
|
||||
define('WP APPLICATION_PASSWORDS_ENABLED', true);
|
||||
```
|
||||
|
||||
**使用方式**:
|
||||
```bash
|
||||
# Basic Auth 格式
|
||||
curl -X POST "https://wp.momentry.ddns.net/wp-json/wp/v2/users" \
|
||||
-u "username:application_password" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": "newuser", "email": "user@example.com", "password": "password"}'
|
||||
```
|
||||
|
||||
#### 1.2 測試 WordPress REST API
|
||||
|
||||
```bash
|
||||
# 取得用戶列表(需要 admin 權限)
|
||||
curl -s -u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
|
||||
"https://wp.momentry.ddns.net/wp-json/wp/v2/users"
|
||||
|
||||
# 創建新用戶
|
||||
curl -X POST "https://wp.momentry.ddns.net/wp-json/wp/v2/users" \
|
||||
-u "wp_user:xxxx xxxx xxxx xxxx xxxx xxxx" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"username": "testuser",
|
||||
"email": "test@example.com",
|
||||
"password": "TestPass123!",
|
||||
"roles": ["subscriber"]
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: 資料庫結構調整
|
||||
|
||||
#### 2.1 新增 users 表(Momentry Core)
|
||||
|
||||
```sql
|
||||
-- migrations/002_user_management.sql
|
||||
|
||||
CREATE TABLE users (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
wordpress_id BIGINT UNIQUE NOT NULL,
|
||||
username VARCHAR(60) NOT NULL,
|
||||
email VARCHAR(100) NOT NULL,
|
||||
api_key_hash VARCHAR(64),
|
||||
quota_size BIGINT DEFAULT 10737418240, -- 10GB
|
||||
quota_used BIGINT DEFAULT 0,
|
||||
sftpgo_username VARCHAR(60),
|
||||
status VARCHAR(20) DEFAULT 'active', -- active, suspended, deleted
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_users_wordpress_id ON users(wordpress_id);
|
||||
CREATE INDEX idx_users_username ON users(username);
|
||||
|
||||
-- videos 表新增 user_id
|
||||
ALTER TABLE videos ADD COLUMN user_id BIGINT REFERENCES users(id);
|
||||
CREATE INDEX idx_videos_user_id ON videos(user_id);
|
||||
|
||||
-- monitor_jobs 表新增 user_id
|
||||
ALTER TABLE monitor_jobs ADD COLUMN user_id BIGINT REFERENCES users(id);
|
||||
CREATE INDEX idx_monitor_jobs_user_id ON monitor_jobs(user_id);
|
||||
|
||||
-- api_keys 表新增 user_id
|
||||
ALTER TABLE api_keys ADD COLUMN user_id BIGINT REFERENCES users(id);
|
||||
```
|
||||
|
||||
#### 2.2 更新 api_keys 表結構
|
||||
|
||||
```sql
|
||||
-- 新增欄位
|
||||
ALTER TABLE api_keys ADD COLUMN user_id BIGINT REFERENCES users(id);
|
||||
ALTER TABLE api_keys ADD COLUMN wordpress_id BIGINT;
|
||||
ALTER TABLE api_keys ADD COLUMN sftpgo_username VARCHAR(60);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: API 認證中介層
|
||||
|
||||
#### 3.1 中介層設計
|
||||
|
||||
```rust
|
||||
// src/api/middleware/auth.rs
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AuthState {
|
||||
pub db: Arc<PostgresDb>,
|
||||
pub cache: Arc<RedisCache>,
|
||||
}
|
||||
|
||||
pub async fn auth_middleware(
|
||||
req: Request,
|
||||
next: Next,
|
||||
state: AuthState,
|
||||
) -> Result<Response, StatusCode> {
|
||||
// 1. 從 Header 提取 API Key
|
||||
// Header: X-API-Key: muser_xxx
|
||||
// 或: Authorization: Bearer muser_xxx
|
||||
|
||||
// 2. 驗證並取得 user_id
|
||||
let user_id = validate_api_key(&req, &state).await?;
|
||||
|
||||
// 3. 附加到 request extensions
|
||||
req.extensions_mut().insert(UserContext { user_id });
|
||||
|
||||
// 4. 執行 handler
|
||||
next.call(req).await
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct UserContext {
|
||||
pub user_id: i64,
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2 API Key 格式更新
|
||||
|
||||
```
|
||||
新格式: muser_{uuid}_{timestamp}_{random}_{user_id_hash}
|
||||
```
|
||||
|
||||
| 欄位 | 說明 |
|
||||
|------|------|
|
||||
| 前綴 | `muser_` = User 類型 |
|
||||
| uuid | 唯一識別碼 |
|
||||
| timestamp | 創建時間戳 |
|
||||
| random | 隨機字串 |
|
||||
| user_id_hash | 壓縮的 user_id |
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: 更新 Register API
|
||||
|
||||
#### 4.1 修改 register 端點
|
||||
|
||||
```rust
|
||||
// POST /api/v1/register
|
||||
pub async fn register(
|
||||
State(state): State<ApiState>,
|
||||
Json(req): Json<RegisterRequest>,
|
||||
Extension(ctx): Extension<UserContext>, // 新增
|
||||
) -> Result<Json<RegisterResponse>, StatusCode> {
|
||||
// ... 現有邏輯 ...
|
||||
|
||||
// 驗證用戶配額
|
||||
let user = state.db.get_user(ctx.user_id).await?;
|
||||
if user.quota_used + file_size > user.quota_size {
|
||||
return Err(StatusCode::FORBIDDEN);
|
||||
}
|
||||
|
||||
// 關聯 user_id 到影片
|
||||
let video_uuid = state.db.create_video(req, Some(ctx.user_id)).await?;
|
||||
|
||||
// 建立 processing job(帶 user_id)
|
||||
state.db.create_monitor_job(
|
||||
job_type: "auto_ingestion",
|
||||
video_uuid,
|
||||
user_id: Some(ctx.user_id),
|
||||
processors: vec!["asr", "cut", "yolo", "ocr", "face", "pose"],
|
||||
).await?;
|
||||
|
||||
Ok(Json(RegisterResponse { uuid: video_uuid }))
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 5: n8n 自動化流程
|
||||
|
||||
#### 5.1 用戶註冊 Workflow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ WordPress 用戶註冊自動化流程 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Trigger: Webhook (或 WordPress Plugin) │
|
||||
│ │
|
||||
│ Step 1: 驗證管理員權限 │
|
||||
│ └─► 檢查 WordPress REST API 憑證 │
|
||||
│ │
|
||||
│ Step 2: 在 Momentry Core 建立用戶記錄 │
|
||||
│ └─► POST /api/v1/admin/users │
|
||||
│ └─► 產生 API Key │
|
||||
│ │
|
||||
│ Step 3: 在 SFTPGo 建立用戶 │
|
||||
│ └─► POST /api/v2/users (SFTPGo API) │
|
||||
│ └─► 設定 home_dir: /data/{username} │
|
||||
│ │
|
||||
│ Step 4: 更新用戶記錄 │
|
||||
│ └─► 關聯 sftpgo_username │
|
||||
│ │
|
||||
│ Step 5: 發送歡迎 email │
|
||||
│ └─► 包含 SFTP 登入資訊 │
|
||||
│ └─► 包含 API Key │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 5.2 SFTPGo Hook 更新
|
||||
|
||||
```bash
|
||||
# /Users/accusys/sftpgo_test/register_hook.sh
|
||||
|
||||
# 修改為傳遞 user_id
|
||||
curl -X POST "http://localhost:3002/api/v1/register" \
|
||||
-H "X-API-Key: ${SFTPGO_USER_API_KEY}" \
|
||||
-H "X-SFTPGo-User: ${SFTPGO_USERNAME}" \
|
||||
-d "{\"path\": \"${SFTPGO_FILE_PATH}\"}"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 實作優先順序
|
||||
|
||||
| Phase | 任務 | 複雜度 | 優先級 | 預估工時 |
|
||||
|-------|------|--------|--------|----------|
|
||||
| 1.1 | 測試 WordPress Application Passwords | 低 | P0 | 1h |
|
||||
| 1.2 | 為 WordPress 產生 Application Password | 低 | P0 | 0.5h |
|
||||
| 2.1 | 建立 users 表 migration | 中 | P0 | 2h |
|
||||
| 2.2 | 更新 videos, monitor_jobs 表 | 低 | P0 | 1h |
|
||||
| 3.1 | 實作 API auth middleware | 中 | P0 | 4h |
|
||||
| 3.2 | 更新 register API 接受 user_id | 低 | P0 | 2h |
|
||||
| 4 | 建立 admin users API | 中 | P1 | 4h |
|
||||
| 5.1 | 建立 n8n 用戶註冊 workflow | 中 | P1 | 6h |
|
||||
| 5.2 | 更新 SFTPGo hook | 低 | P1 | 2h |
|
||||
| 6 | 實作配額管理 | 中 | P2 | 4h |
|
||||
| 7 | 測試與驗證 | 中 | P2 | 4h |
|
||||
|
||||
**總預估工時**: ~30.5h
|
||||
|
||||
---
|
||||
|
||||
## 5. 待確認事項
|
||||
|
||||
### 5.1 WordPress 用戶建立方式
|
||||
|
||||
- [ ] 手動在 wp-admin 建立?還是透過 Elementor 表單?
|
||||
- [ ] 是否需要 email 驗證?
|
||||
- [ ] 初始角色設定(subscriber / contributor)?
|
||||
|
||||
### 5.2 API Key 格式
|
||||
|
||||
- [ ] 維持現有 `muser_` 前綴格式?
|
||||
- [ ] 還是建立新的用戶專用 key 格式?
|
||||
- [ ] 是否需要 JWT token?
|
||||
|
||||
### 5.3 SFTPGo 整合
|
||||
|
||||
- [ ] 每個 WordPress 用戶對應一個 SFTPGo 用戶?
|
||||
- [ ] home_dir 命名規則?(如 `data/{wordpress_username}`)
|
||||
- [ ] SFTPGo 配額是否同步?
|
||||
|
||||
### 5.4 配額管理
|
||||
|
||||
- [ ] 每人預設 10GB 空間?
|
||||
- [ ] 超出配額如何處理?(阻止上傳 / 警告)
|
||||
- [ ] 配額用完後是否暫停 SFTPGo 用戶?
|
||||
|
||||
### 5.5 資料同步
|
||||
|
||||
- [ ] WordPress 用戶刪除時是否同步刪除其他系統?
|
||||
- [ ] 用戶停權時的處理流程?
|
||||
|
||||
---
|
||||
|
||||
## 6. 參考文件
|
||||
|
||||
### 內部文件
|
||||
|
||||
| 文件 | 用途 |
|
||||
|------|------|
|
||||
| `docs/PENDING_ISSUES.md` | 待解決問題追蹤 |
|
||||
| `docs/API_KEY_MANAGEMENT.md` | API Key 管理系統 |
|
||||
| `docs/API_REFERENCE.md` | API 端點參考 |
|
||||
| `docs/SFTPGO_DEMO_USER.md` | SFTPGo 用戶設定 |
|
||||
| `docs/N8N_INTEGRATION_GUIDE.md` | n8n 整合指南 |
|
||||
| `docs/INSTALL_WORDPRESS.md` | WordPress 安裝指南 |
|
||||
|
||||
### 外部資源
|
||||
|
||||
| 資源 | URL |
|
||||
|------|-----|
|
||||
| WordPress REST API | https://developer.wordpress.org/rest-api/ |
|
||||
| WordPress Application Passwords | https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/#authentication-plugins |
|
||||
| SFTPGo REST API | https://docs.sftpgo.com/latest/rest-api/ |
|
||||
|
||||
---
|
||||
|
||||
## 7. 附錄
|
||||
|
||||
### A. 現有使用者資料
|
||||
|
||||
#### WordPress (wp_users)
|
||||
| ID | user_login | user_email | display_name |
|
||||
|----|------------|------------|--------------|
|
||||
| 1 | wp_user | marketing@accusys.com.tw | wp_user |
|
||||
| 2 | sc_demo | susan.cheng@accusys.com.tw | Susan Cheng |
|
||||
|
||||
#### SFTPGo (users)
|
||||
| username | email | home_dir | status |
|
||||
|----------|-------|----------|--------|
|
||||
| demo | demo@momentry.local | /Users/accusys/momentry/var/sftpgo/data/demo | Active |
|
||||
| warren | warren@momentry.local | /Users/accusys/momentry/var/sftpgo/data/warren | Active |
|
||||
| momentry | system@momentry.local | /Users/accusys/momentry/var/sftpgo/data/momentry | Active |
|
||||
|
||||
### B. 服務端口
|
||||
|
||||
| 服務 | Port | URL |
|
||||
|------|------|-----|
|
||||
| WordPress | 9000 (PHP-FPM) | https://wp.momentry.ddns.net |
|
||||
| SFTPGo | 8080 | http://localhost:8080 |
|
||||
| Momentry API | 3002 | http://localhost:3002 |
|
||||
| n8n | 5678 | http://localhost:5678 |
|
||||
Reference in New Issue
Block a user