V3.1 自定义角色 + Worker 权限组

角色管理(管理员可编辑角色权限功能):
- 18 个权限功能点按模块分组(仪表盘/项目/Worker/协作/评估/模板/报表/日志/告警/API/设置/企业版)
- 内置角色(admin/auditor/member)权限点可编辑、不可删除;自定义角色任意创建/删除/编辑
- 用户可绑定多个自定义角色,权限自动合并(内置基础 ∪ 自定义),即时生效无需重启
- 前端侧边栏按有效权限点自动显隐;未授权模块 API 返回 403

Worker 权限组(批量授权):
- 把一批 Worker+权限(查看/使用/管理)打包成组,整组授权给用户
- 与直接授权并行生效取高值;组内 Worker 自动对绑定用户可见
- 企业版用户与权限新增三个子页:用户列表/角色管理/Worker 权限组

新表:roles / user_roles / worker_perm_groups / worker_perm_group_members / user_worker_groups
This commit is contained in:
2026-08-13 13:03:57 +08:00
parent eb92a4e591
commit 1f37344d03
6 changed files with 758 additions and 64 deletions
+82
View File
@@ -297,11 +297,60 @@ CREATE TABLE IF NOT EXISTS user_workers (
UNIQUE(user_id, worker_id)
);
-- ===================================================================
-- V3.1 表结构:自定义角色(权限功能点)+ Worker 权限组(批量授权)
-- ===================================================================
CREATE TABLE IF NOT EXISTS roles (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
description TEXT DEFAULT '',
perms TEXT DEFAULT '[]', -- JSON: 权限点 id 列表
is_builtin INTEGER DEFAULT 0, -- 内置角色(admin/auditor/member)不可删除
created_at INTEGER,
updated_at INTEGER
);
CREATE TABLE IF NOT EXISTS user_roles (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
role_id INTEGER NOT NULL,
created_at INTEGER,
UNIQUE(user_id, role_id)
);
CREATE TABLE IF NOT EXISTS worker_perm_groups (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
description TEXT DEFAULT '',
created_at INTEGER,
updated_at INTEGER
);
CREATE TABLE IF NOT EXISTS worker_perm_group_members (
id INTEGER PRIMARY KEY AUTOINCREMENT,
group_id INTEGER NOT NULL,
worker_id INTEGER NOT NULL,
perm TEXT DEFAULT 'view', -- 组内该 Worker 权限(可覆盖组默认)
created_at INTEGER,
UNIQUE(group_id, worker_id)
);
CREATE TABLE IF NOT EXISTS user_worker_groups (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
group_id INTEGER NOT NULL,
created_at INTEGER,
UNIQUE(user_id, group_id)
);
CREATE INDEX IF NOT EXISTS idx_deliverables_project ON project_deliverables(project_id);
CREATE INDEX IF NOT EXISTS idx_user_projects_user ON user_projects(user_id);
CREATE INDEX IF NOT EXISTS idx_user_projects_project ON user_projects(project_id);
CREATE INDEX IF NOT EXISTS idx_user_workers_user ON user_workers(user_id);
CREATE INDEX IF NOT EXISTS idx_user_workers_worker ON user_workers(worker_id);
CREATE INDEX IF NOT EXISTS idx_user_roles_user ON user_roles(user_id);
CREATE INDEX IF NOT EXISTS idx_wpg_members_group ON worker_perm_group_members(group_id);
CREATE INDEX IF NOT EXISTS idx_uwg_user ON user_worker_groups(user_id);
CREATE INDEX IF NOT EXISTS idx_agent_steps_run ON agent_steps(run_id);
CREATE INDEX IF NOT EXISTS idx_agent_runs_status ON agent_runs(status);
CREATE INDEX IF NOT EXISTS idx_eval_cases_ds ON eval_cases(dataset_id);
@@ -401,6 +450,39 @@ def init_db():
conn.close()
_migrate()
migrate_v2()
seed_builtin_roles()
# V3.1 内置角色权限点定义(admin 为特殊值 ALL,表示全部权限)
BUILTIN_ROLE_PERMS = {
'admin': ['*'],
# 审计员:全量只读
'auditor': ['dashboard.view', 'project.view', 'worker.view', 'agent.view', 'eval.view',
'template.view', 'report.view', 'log.view', 'alert.view'],
# 成员:基础功能(资源级仍受项目/Worker 授权约束)
'member': ['dashboard.view', 'project.view', 'project.create', 'project.deliver',
'worker.view', 'agent.view', 'agent.run', 'eval.view', 'eval.run',
'template.view', 'report.view', 'log.view', 'alert.view'],
}
def seed_builtin_roles():
"""幂等:仅首次创建 admin/auditor/member 内置角色(不覆盖管理员后续编辑)"""
import json as _json
conn = get_conn()
try:
for name, perms in BUILTIN_ROLE_PERMS.items():
r = conn.execute('SELECT id FROM roles WHERE name=?', (name,)).fetchone()
if not r:
conn.execute(
'INSERT INTO roles (name, description, perms, is_builtin, created_at, updated_at) '
'VALUES (?,?,?,1,?,?)',
(name, {'admin': '超级管理员:全部权限', 'auditor': '审计员:全量只读',
'member': '成员:基础功能,资源级按项目/Worker 授权'}[name],
_json.dumps(perms), now(), now()))
conn.commit()
finally:
conn.close()
def recover_stale_runs():