# 統一會員系統 + 影片歸屬追蹤實作計畫 | 項目 | 內容 | |------|------| | 建立者 | 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, pub cache: Arc, } pub async fn auth_middleware( req: Request, next: Next, state: AuthState, ) -> Result { // 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, Json(req): Json, Extension(ctx): Extension, // 新增 ) -> Result, 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 |