架构设计:
- Admin Layer: 系统管理 (admin.sqlite)
* system_config - 系统配置
* users - 用户管理
* groups - 群组管理
* permissions - 权限管理
* audit_logs - 审计日志
- Group Layer: 群组管理 (group_{id}.sqlite)
* group_config - 群组配置
* group_members - 群组成员
* group_files - 群组文件
* group_permissions - 群组权限
* group_shares - 群组共享
- User Layer: 用户数据 ({username}.sqlite)
* user_config - 用户配置
* user_files - 用户文件
* user_bookmarks - 用户书签
* search_history - 搜索历史
* video_marks - 视频标记
目录结构:
data/
├── admin/admin.sqlite
├── groups/group_{id}.sqlite
└── users/{username}.sqlite
权限模型:
- Admin: 系统管理
- Group Owner: 群组管理
- Group Member: 群组访问
- User: 个人数据
文档:
- MARKBASE_THREE_LAYER_ARCHITECTURE.md - 完整架构设计
- THREE_LAYER_IMPLEMENTATION_GUIDE.md - 实施指南
脚本:
- init_three_layer_db.sh - 数据库初始化
- check_three_layer.sh - 架构检查
预计工作量: 3-5 天
优先级: 高
885 lines
26 KiB
Markdown
885 lines
26 KiB
Markdown
# 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<Option<String>, 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<u32>) -> Result<Vec<HistoryItem>, String> {
|
|
let limit = limit.unwrap_or(30).min(30);
|
|
let conn = get_user_conn(&username)?; // 使用用户特定连接
|
|
|
|
// ... 其余代码
|
|
}
|
|
|
|
/// 获取用户连接
|
|
fn get_user_conn(username: &str) -> Result<Connection, String> {
|
|
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<bool, String> {
|
|
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
|
|
**状态**: ✅ 架构设计完成,待实施
|
|
**优先级**: 高 |