# MarkBase 三层架构设计 **设计时间**: 2026-10-12 **架构**: Admin + Group + User 三层隔离 --- ## 📊 架构概览 ``` ┌─────────────────────────────────────────────────────────────┐ │ Admin Layer │ │ (系统管理层) │ │ │ │ admin.sqlite │ │ ├─ 系统配置 (system_config) │ │ ├─ 用户列表 (users) │ │ ├─ 权限管理 (permissions) │ │ ├─ 群组管理 (groups) │ │ └─ 审计日志 (audit_logs) │ └─────────────────────────────────────────────────────────────┘ │ │ 管理 ▼ ┌─────────────────────────────────────────────────────────────┐ │ Group Layer │ │ (群组管理层) │ │ │ │ group_{group_id}.sqlite │ │ ├─ 群组配置 (group_config) │ │ ├─ 群组成员 (group_members) │ │ ├─ 群组文件 (group_files) │ │ ├─ 群组权限 (group_permissions) │ │ └─ 群组共享 (group_shares) │ │ │ │ 示例: │ │ - group_marketing.sqlite │ │ - group_development.sqlite │ │ - group_sales.sqlite │ └─────────────────────────────────────────────────────────────┘ │ │ 包含 ▼ ┌─────────────────────────────────────────────────────────────┐ │ User Layer │ │ (用户数据层) │ │ │ │ {username}.sqlite │ │ ├─ 用户配置 (user_config) │ │ ├─ 用户文件 (user_files) │ │ ├─ 用户书签 (user_bookmarks) │ │ ├─ 搜索历史 (search_history) │ │ ├─ 视频标记 (video_marks) │ │ └─ 个人设置 (user_settings) │ │ │ │ 示例: │ │ - demo.sqlite │ │ - admin.sqlite │ │ - user1.sqlite │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 📁 数据库文件结构 ### 新目录结构 ``` data/ ├── admin/ │ └── admin.sqlite # 系统管理数据库 │ ├── groups/ │ ├── group_marketing.sqlite # 营销群组 │ ├── group_development.sqlite # 开发群组 │ ├── group_sales.sqlite # 销售群组 │ └── group_finance.sqlite # 财务群组 │ └── users/ ├── demo.sqlite # demo 用户数据 ├── admin.sqlite # admin 用户数据 ├── user1.sqlite # user1 用户数据 └── user2.sqlite # user2 用户数据 ``` --- ## 📊 数据库表结构 ### 1. Admin Layer (`admin.sqlite`) #### system_config (系统配置) ```sql CREATE TABLE system_config ( key TEXT PRIMARY KEY, value TEXT NOT NULL, description TEXT, updated_by TEXT, updated_at TEXT DEFAULT (datetime('now')) ); -- 示例数据 INSERT INTO system_config (key, value, description) VALUES ('system_name', 'Momentry Studio', '系统名称'), ('max_users', '100', '最大用户数'), ('max_groups', '20', '最大群组数'), ('storage_quota', '100GB', '存储配额'), ('backup_enabled', 'true', '是否启用备份'); ``` #### users (用户列表) ```sql CREATE TABLE users ( id TEXT PRIMARY KEY, username TEXT NOT NULL UNIQUE, email TEXT UNIQUE, password_hash TEXT NOT NULL, display_name TEXT, role TEXT DEFAULT 'user', -- 'admin', 'user', 'guest' status TEXT DEFAULT 'active', -- 'active', 'disabled', 'suspended' group_ids TEXT, -- JSON 数组: ["group1", "group2"] created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')), last_login_at TEXT ); ``` #### groups (群组管理) ```sql CREATE TABLE groups ( id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, description TEXT, owner_id TEXT NOT NULL, -- 创建者 ID members TEXT, -- JSON 数组: ["user1", "user2"] permissions TEXT, -- JSON 对象: {"read": true, "write": false} storage_quota TEXT, -- 群组存储配额 status TEXT DEFAULT 'active', -- 'active', 'disabled' created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')) ); ``` #### permissions (权限管理) ```sql CREATE TABLE permissions ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT NOT NULL, resource_type TEXT NOT NULL, -- 'system', 'group', 'user' resource_id TEXT NOT NULL, permission TEXT NOT NULL, -- 'read', 'write', 'admin', 'delete' granted_by TEXT NOT NULL, granted_at TEXT DEFAULT (datetime('now')), expires_at TEXT, UNIQUE(user_id, resource_type, resource_id, permission) ); ``` #### audit_logs (审计日志) ```sql CREATE TABLE audit_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT NOT NULL, action TEXT NOT NULL, -- 'login', 'logout', 'create', 'update', 'delete' resource_type TEXT, -- 'user', 'group', 'file', 'config' resource_id TEXT, details TEXT, -- JSON 对象 ip_address TEXT, user_agent TEXT, created_at TEXT DEFAULT (datetime('now')) ); ``` --- ### 2. Group Layer (`group_{group_id}.sqlite`) #### group_config (群组配置) ```sql CREATE TABLE group_config ( key TEXT PRIMARY KEY, value TEXT NOT NULL, description TEXT, updated_by TEXT, updated_at TEXT DEFAULT (datetime('now')) ); -- 示例数据 INSERT INTO group_config (key, value, description) VALUES ('group_name', 'Marketing Team', '群组名称'), ('storage_quota', '50GB', '群组存储配额'), ('max_members', '20', '最大成员数'), ('share_enabled', 'true', '是否允许共享'); ``` #### group_members (群组成员) ```sql CREATE TABLE group_members ( user_id TEXT PRIMARY KEY, username TEXT NOT NULL, role TEXT DEFAULT 'member', -- 'owner', 'admin', 'member', 'guest' permissions TEXT, -- JSON 对象: {"read": true, "write": true} joined_at TEXT DEFAULT (datetime('now')), invited_by TEXT ); ``` #### group_files (群组文件) ```sql CREATE TABLE group_files ( id INTEGER PRIMARY KEY AUTOINCREMENT, file_uuid TEXT NOT NULL UNIQUE, filename TEXT NOT NULL, file_path TEXT NOT NULL, file_size INTEGER, mime_type TEXT, uploaded_by TEXT NOT NULL, access_level TEXT DEFAULT 'group', -- 'public', 'group', 'private' tags TEXT, -- JSON 数组: ["tag1", "tag2"] created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')) ); ``` #### group_permissions (群组权限) ```sql CREATE TABLE group_permissions ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT NOT NULL, permission TEXT NOT NULL, -- 'read', 'write', 'admin', 'delete' resource_type TEXT, -- 'file', 'folder', 'all' resource_id TEXT, granted_by TEXT NOT NULL, granted_at TEXT DEFAULT (datetime('now')), UNIQUE(user_id, permission, resource_type, resource_id) ); ``` #### group_shares (群组共享) ```sql CREATE TABLE group_shares ( id INTEGER PRIMARY KEY AUTOINCREMENT, file_uuid TEXT NOT NULL, shared_by TEXT NOT NULL, shared_with TEXT, -- JSON 数组: ["user1", "user2"] 或 ["group1"] share_type TEXT, -- 'user', 'group', 'public' permissions TEXT, -- JSON 对象: {"read": true, "write": false} expires_at TEXT, created_at TEXT DEFAULT (datetime('now')) ); ``` --- ### 3. User Layer (`{username}.sqlite`) #### user_config (用户配置) ```sql CREATE TABLE user_config ( key TEXT PRIMARY KEY, value TEXT NOT NULL, description TEXT, updated_at TEXT DEFAULT (datetime('now')) ); -- 示例数据 INSERT INTO user_config (key, value, description) VALUES ('theme', 'dark', '界面主题'), ('language', 'zh-TW', '界面语言'), ('notifications_enabled', 'true', '是否启用通知'); ``` #### user_files (用户文件) ```sql CREATE TABLE user_files ( id INTEGER PRIMARY KEY AUTOINCREMENT, file_uuid TEXT NOT NULL UNIQUE, filename TEXT NOT NULL, file_path TEXT NOT NULL, file_size INTEGER, mime_type TEXT, tags TEXT, -- JSON 数组 is_starred INTEGER DEFAULT 0, created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')) ); ``` #### user_bookmarks (用户书签) ```sql CREATE TABLE user_bookmarks ( id INTEGER PRIMARY KEY AUTOINCREMENT, label TEXT NOT NULL, url TEXT, file_uuid TEXT, created_at TEXT DEFAULT (datetime('now')) ); ``` #### search_history (搜索历史) ```sql CREATE TABLE search_history ( id TEXT PRIMARY KEY, query TEXT NOT NULL, title TEXT NOT NULL, chat_state TEXT, mode TEXT DEFAULT 'keyword', pinned INTEGER DEFAULT 0, created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')) ); ``` #### video_marks (视频标记) ```sql CREATE TABLE video_marks ( id INTEGER PRIMARY KEY AUTOINCREMENT, file_uuid TEXT NOT NULL, tag TEXT NOT NULL, start_frame INTEGER NOT NULL, end_frame INTEGER, note TEXT, created_at TEXT DEFAULT (datetime('now')) ); ``` #### user_settings (个人设置) ```sql CREATE TABLE user_settings ( key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at TEXT DEFAULT (datetime('now')) ); ``` --- ## 🔄 数据流向 ### 1. 用户登录流程 ``` 1. 前端发送登录请求 └─> 读取 admin.sqlite/users 表 └─> 验证用户名和密码 ├─> 成功: 读取用户所属群组 │ └─> 返回用户信息 + 群组列表 └─> 失败: 返回错误 2. 加载用户数据 └─> 打开 {username}.sqlite └─> 加载用户配置、书签、历史等 3. 加载群组数据 └─> 打开 group_{group_id}.sqlite └─> 加载群组文件、成员、权限 ``` --- ### 2. 文件访问流程 ``` 1. 用户请求访问文件 └─> 检查文件所有者 ├─> 个人文件: {username}.sqlite/user_files └─> 群组文件: group_{group_id}.sqlite/group_files 2. 权限检查 └─> admin.sqlite/permissions ├─> 用户有权限: 允许访问 └─> 用户无权限: 拒绝访问 3. 审计日志 └─> 写入 admin.sqlite/audit_logs ``` --- ### 3. 群组管理流程 ``` 1. 创建群组 └─> admin.sqlite/groups 表添加记录 └─> 创建 group_{group_id}.sqlite └─> 初始化群组表结构 2. 添加成员 └─> admin.sqlite/groups 更新 members 字段 └─> group_{group_id}.sqlite/group_members 添加成员 3. 删除群组 └─> admin.sqlite/groups 更新 status 为 'disabled' └─> 可选: 删除 group_{group_id}.sqlite ``` --- ## 🛠️ Rust 实现设计 ### 数据库路径函数 ```rust // src-tauri/src/db.rs use std::path::PathBuf; /// Admin 数据库路径 pub fn admin_db_path() -> PathBuf { let base = std::env::var("MOMENTRY_DATA_DIR") .unwrap_or_else(|_| { let home = dirs::home_dir() .expect("Failed to get home directory"); format!("{}/momentry_studio/data/admin", home.display()) }); std::fs::create_dir_all(&base).ok(); PathBuf::from(base).join("admin.sqlite") } /// Group 数据库路径 pub fn group_db_path(group_id: &str) -> PathBuf { let base = std::env::var("MOMENTRY_DATA_DIR") .unwrap_or_else(|_| { let home = dirs::home_dir() .expect("Failed to get home directory"); format!("{}/momentry_studio/data/groups", home.display()) }); std::fs::create_dir_all(&base).ok(); PathBuf::from(base).join(format!("group_{}.sqlite", group_id)) } /// User 数据库路径 pub fn user_db_path(username: &str) -> PathBuf { let base = std::env::var("MOMENTRY_DATA_DIR") .unwrap_or_else(|_| { let home = dirs::home_dir() .expect("Failed to get home directory"); format!("{}/momentry_studio/data/users", home.display()) }); std::fs::create_dir_all(&base).ok(); PathBuf::from(base).join(format!("{}.sqlite", username)) } ``` --- ### Admin 管理函数 ```rust // src-tauri/src/admin.rs use rusqlite::Connection; use crate::db::admin_db_path; /// 初始化 Admin 数据库 pub fn init_admin_db() -> Result<(), String> { let path = admin_db_path(); let conn = Connection::open(&path).map_err(|e| format!("Failed to open admin db: {}", e))?; conn.execute_batch(" CREATE TABLE IF NOT EXISTS system_config ( key TEXT PRIMARY KEY, value TEXT NOT NULL, description TEXT, updated_by TEXT, updated_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS users ( id TEXT PRIMARY KEY, username TEXT NOT NULL UNIQUE, email TEXT UNIQUE, password_hash TEXT NOT NULL, display_name TEXT, role TEXT DEFAULT 'user', status TEXT DEFAULT 'active', group_ids TEXT, created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')), last_login_at TEXT ); CREATE TABLE IF NOT EXISTS groups ( id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, description TEXT, owner_id TEXT NOT NULL, members TEXT, permissions TEXT, storage_quota TEXT, status TEXT DEFAULT 'active', created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS permissions ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT NOT NULL, resource_type TEXT NOT NULL, resource_id TEXT NOT NULL, permission TEXT NOT NULL, granted_by TEXT NOT NULL, granted_at TEXT DEFAULT (datetime('now')), expires_at TEXT, UNIQUE(user_id, resource_type, resource_id, permission) ); CREATE TABLE IF NOT EXISTS audit_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT NOT NULL, action TEXT NOT NULL, resource_type TEXT, resource_id TEXT, details TEXT, ip_address TEXT, user_agent TEXT, created_at TEXT DEFAULT (datetime('now')) ); ").map_err(|e| format!("Failed to create tables: {}", e))?; Ok(()) } /// 获取系统配置 pub fn get_system_config(key: &str) -> Result, String> { let conn = Connection::open(admin_db_path()) .map_err(|e| format!("Failed to open db: {}", e))?; let value = conn.query_row( "SELECT value FROM system_config WHERE key = ?1", [key], |row| row.get(0) ).ok(); Ok(value) } /// 设置系统配置 pub fn set_system_config(key: &str, value: &str, updated_by: &str) -> Result<(), String> { let conn = Connection::open(admin_db_path()) .map_err(|e| format!("Failed to open db: {}", e))?; conn.execute( "INSERT OR REPLACE INTO system_config (key, value, updated_by, updated_at) VALUES (?1, ?2, ?3, datetime('now'))", rusqlite::params![key, value, updated_by] ).map_err(|e| format!("Failed to set config: {}", e))?; Ok(()) } /// 创建群组 pub fn create_group( id: &str, name: &str, description: &str, owner_id: &str ) -> Result<(), String> { // 1. 在 admin 数据库中创建群组记录 let admin_conn = Connection::open(admin_db_path()) .map_err(|e| format!("Failed to open admin db: {}", e))?; admin_conn.execute( "INSERT INTO groups (id, name, description, owner_id, members, created_at, updated_at) VALUES (?1, ?2, ?3, ?4, '[]', datetime('now'), datetime('now'))", rusqlite::params![id, name, description, owner_id] ).map_err(|e| format!("Failed to create group: {}", e))?; // 2. 创建群组数据库 let group_path = crate::db::group_db_path(id); let group_conn = Connection::open(&group_path) .map_err(|e| format!("Failed to create group db: {}", e))?; group_conn.execute_batch(" CREATE TABLE IF NOT EXISTS group_config ( key TEXT PRIMARY KEY, value TEXT NOT NULL, description TEXT, updated_by TEXT, updated_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS group_members ( user_id TEXT PRIMARY KEY, username TEXT NOT NULL, role TEXT DEFAULT 'member', permissions TEXT, joined_at TEXT DEFAULT (datetime('now')), invited_by TEXT ); CREATE TABLE IF NOT EXISTS group_files ( id INTEGER PRIMARY KEY AUTOINCREMENT, file_uuid TEXT NOT NULL UNIQUE, filename TEXT NOT NULL, file_path TEXT NOT NULL, file_size INTEGER, mime_type TEXT, uploaded_by TEXT NOT NULL, access_level TEXT DEFAULT 'group', tags TEXT, created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')) ); ").map_err(|e| format!("Failed to create group tables: {}", e))?; Ok(()) } ``` --- ### User 数据函数 (修改后) ```rust // src-tauri/src/db.rs /// 获取用户搜索历史 pub fn get_search_history(username: String, limit: Option) -> Result, String> { let limit = limit.unwrap_or(30).min(30); let conn = get_user_conn(&username)?; // 使用用户特定连接 // ... 其余代码 } /// 获取用户连接 fn get_user_conn(username: &str) -> Result { let path = user_db_path(username); let conn = Connection::open(&path).map_err(|e| format!("Failed to open user db: {}", e))?; conn.execute_batch("PRAGMA journal_mode=WAL;").ok(); Ok(conn) } ``` --- ## 🔐 权限模型 ### 权限层级 ``` Admin (系统管理员) ├─ 管理所有用户 ├─ 管理所有群组 ├─ 管理系统配置 └─ 查看审计日志 Group Owner (群组所有者) ├─ 管理群组成员 ├─ 管理群组文件 ├─ 管理群组权限 └─ 删除群组 Group Admin (群组管理员) ├─ 管理群组文件 ├─ 添加群组成员 └─ 管理群组共享 Group Member (群组成员) ├─ 访问群组文件 (有权限) └─ 上传文件到群组 (有权限) User (普通用户) ├─ 管理个人文件 ├─ 管理个人设置 └─ 访问共享文件 (有权限) ``` --- ### 权限检查流程 ```rust pub fn check_permission( user_id: &str, resource_type: &str, // 'system', 'group', 'user' resource_id: &str, permission: &str // 'read', 'write', 'admin', 'delete' ) -> Result { let conn = Connection::open(admin_db_path()) .map_err(|e| format!("Failed to open admin db: {}", e))?; // 1. 检查用户是否为超级管理员 let role: String = conn.query_row( "SELECT role FROM users WHERE id = ?1", [user_id], |row| row.get(0) ).unwrap_or_else(|_| "user".to_string()); if role == "admin" { return Ok(true); // 超级管理员拥有所有权限 } // 2. 检查显式权限 let has_permission = conn.query_row( "SELECT COUNT(*) FROM permissions WHERE user_id = ?1 AND resource_type = ?2 AND resource_id = ?3 AND permission = ?4", rusqlite::params![user_id, resource_type, resource_id, permission], |row| row.get::<_, i32>(0) ).unwrap_or(0) > 0; Ok(has_permission) } ``` --- ## 📊 数据库初始化流程 ### 安装时初始化 ```rust pub fn initialize_system() -> Result<(), String> { // 1. 创建 Admin 数据库 init_admin_db()?; // 2. 创建默认管理员 let default_password = std::env::var("MOMENTRY_DEFAULT_PASSWORD") .unwrap_or_else(|_| "admin_default".to_string()); create_default_admin(&default_password)?; // 3. 初始化系统配置 init_system_config()?; // 4. 创建默认用户数据库 init_user_db("demo")?; Ok(()) } fn create_default_admin(password: &str) -> Result<(), String> { let conn = Connection::open(admin_db_path()) .map_err(|e| format!("Failed to open admin db: {}", e))?; let password_hash = hash_password(password); conn.execute( "INSERT OR IGNORE INTO users (id, username, password_hash, display_name, role, status) VALUES ('admin', 'admin', ?1, 'System Administrator', 'admin', 'active')", [password_hash] ).map_err(|e| format!("Failed to create admin: {}", e))?; Ok(()) } ``` --- ## 🚀 API 端点设计 ### Admin API ``` GET /api/v2/admin/config # 获取系统配置 POST /api/v2/admin/config # 设置系统配置 GET /api/v2/admin/users # 获取用户列表 POST /api/v2/admin/users # 创建用户 PUT /api/v2/admin/users/{id} # 更新用户 DELETE /api/v2/admin/users/{id} # 删除用户 GET /api/v2/admin/groups # 获取群组列表 POST /api/v2/admin/groups # 创建群组 PUT /api/v2/admin/groups/{id} # 更新群组 DELETE /api/v2/admin/groups/{id} # 删除群组 GET /api/v2/admin/audit-logs # 获取审计日志 ``` ### Group API ``` GET /api/v2/groups/{group_id}/members # 获取群组成员 POST /api/v2/groups/{group_id}/members # 添加成员 DELETE /api/v2/groups/{group_id}/members/{id} # 移除成员 GET /api/v2/groups/{group_id}/files # 获取群组文件 POST /api/v2/groups/{group_id}/files # 上传文件 DELETE /api/v2/groups/{group_id}/files/{id} # 删除文件 GET /api/v2/groups/{group_id}/permissions # 获取群组权限 POST /api/v2/groups/{group_id}/permissions # 设置权限 ``` ### User API ``` GET /api/v2/users/{username}/files # 获取用户文件 POST /api/v2/users/{username}/files # 上传文件 DELETE /api/v2/users/{username}/files/{id} # 删除文件 GET /api/v2/users/{username}/bookmarks # 获取用户书签 POST /api/v2/users/{username}/bookmarks # 添加书签 GET /api/v2/users/{username}/history # 获取搜索历史 POST /api/v2/users/{username}/history # 保存搜索历史 ``` --- ## 📝 迁移计划 ### 从当前架构迁移到三层架构 **步骤**: 1. **创建新目录结构** ```bash mkdir -p data/admin data/groups data/users ``` 2. **创建 Admin 数据库** - 初始化 admin.sqlite - 创建默认管理员 3. **迁移现有用户数据** ```bash # 保持现有 demo.sqlite 在 data/users/ 中 mv data/users/demo.sqlite data/users/demo.sqlite.backup ``` 4. **更新代码** - 修改 db.rs 支持三层路径 - 添加 admin.rs 管理函数 - 添加 group.rs 群组函数 5. **更新前端** - 添加 Admin 管理界面 - 添加 Group 管理界面 - 修改 API 调用 --- ## 🎯 优势 ### 1. 数据隔离 - ✅ **Admin**: 系统配置独立管理 - ✅ **Group**: 群组数据完全隔离 - ✅ **User**: 用户数据完全隔离 ### 2. 权限控制 - ✅ 精细的权限管理 - ✅ 多层级权限继承 - ✅ 灵活的权限分配 ### 3. 可扩展性 - ✅ 支持无限用户 - ✅ 支持无限群组 - ✅ 群组可嵌套 (未来扩展) ### 4. 安全性 - ✅ 审计日志记录 - ✅ 权限检查严格 - ✅ 数据访问控制 --- ## ⚠️ 注意事项 ### 1. 数据库连接管理 - 使用连接池优化性能 - 避免频繁打开/关闭数据库 - 考虑使用 WAL 模式 ### 2. 数据一致性 - 跨数据库事务需要特殊处理 - 使用两阶段提交或补偿事务 - 定期数据校验 ### 3. 性能优化 - 定期清理审计日志 - 群组数据库索引优化 - 配置缓存机制 --- ## 📚 相关文档 1. **DATABASE_DEPENDENCIES.md** - 数据库依赖说明 2. **USER_DATABASE_ISOLATION_FIX.md** - 用户隔离修复 3. **DATABASE_OPTIMIZATION.md** - 数据库优化 --- **设计时间**: 2026-10-12 **状态**: ✅ 架构设计完成,待实施 **优先级**: 高