## 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
14 KiB
14 KiB
統一會員系統 + 影片歸屬追蹤實作計畫
| 項目 | 內容 |
|---|---|
| 建立者 | 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 關聯 |
問題:
- 無法追蹤影片歸屬(誰上傳的影片)
- 無法實作 per-user 配額管理
- API 端點全部公開,無認證
- 用戶創建需要多處操作
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+ 內建功能,無需額外插件。
// wp-config.php (如需自訂設定)
define('WP APPLICATION_PASSWORDS_ENABLED', true);
使用方式:
# 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
# 取得用戶列表(需要 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)
-- 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 表結構
-- 新增欄位
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 中介層設計
// 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 端點
// 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 更新
# /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 | 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 |