mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-09-05 07:36:53 +08:00
refactor: remove Permission model and update related code to use permission codes
This commit is contained in:
@@ -3,9 +3,7 @@ from fastapi import HTTPException
|
|||||||
|
|
||||||
from models.database import (
|
from models.database import (
|
||||||
UserAccount,
|
UserAccount,
|
||||||
Role,
|
|
||||||
UserRole,
|
UserRole,
|
||||||
Permission,
|
|
||||||
RolePermission,
|
RolePermission,
|
||||||
PathRule,
|
PathRule,
|
||||||
)
|
)
|
||||||
@@ -144,13 +142,8 @@ class PermissionService:
|
|||||||
if not role_ids:
|
if not role_ids:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 检查角色是否有该权限
|
|
||||||
permission = await Permission.get_or_none(code=permission_code)
|
|
||||||
if not permission:
|
|
||||||
return False
|
|
||||||
|
|
||||||
role_permission = await RolePermission.filter(
|
role_permission = await RolePermission.filter(
|
||||||
role_id__in=role_ids, permission_id=permission.id
|
role_id__in=role_ids, permission_code=permission_code
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
return role_permission is not None
|
return role_permission is not None
|
||||||
@@ -180,12 +173,12 @@ class PermissionService:
|
|||||||
|
|
||||||
# 超级管理员拥有所有权限
|
# 超级管理员拥有所有权限
|
||||||
if user.is_admin:
|
if user.is_admin:
|
||||||
all_permissions = await Permission.all()
|
all_permission_codes = [item["code"] for item in PERMISSION_DEFINITIONS]
|
||||||
all_path_rules = await PathRule.all()
|
all_path_rules = await PathRule.all()
|
||||||
return UserPermissions(
|
return UserPermissions(
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
is_admin=True,
|
is_admin=True,
|
||||||
permissions=[p.code for p in all_permissions],
|
permissions=all_permission_codes,
|
||||||
path_rules=[
|
path_rules=[
|
||||||
PathRuleInfo(
|
PathRuleInfo(
|
||||||
id=r.id,
|
id=r.id,
|
||||||
@@ -210,10 +203,8 @@ class PermissionService:
|
|||||||
# 获取权限
|
# 获取权限
|
||||||
permissions = []
|
permissions = []
|
||||||
if role_ids:
|
if role_ids:
|
||||||
role_permissions = await RolePermission.filter(
|
role_permissions = await RolePermission.filter(role_id__in=role_ids)
|
||||||
role_id__in=role_ids
|
permissions = sorted(set(rp.permission_code for rp in role_permissions))
|
||||||
).prefetch_related("permission")
|
|
||||||
permissions = list(set(rp.permission.code for rp in role_permissions))
|
|
||||||
|
|
||||||
# 获取路径规则
|
# 获取路径规则
|
||||||
path_rules = []
|
path_rules = []
|
||||||
@@ -245,16 +236,14 @@ class PermissionService:
|
|||||||
@classmethod
|
@classmethod
|
||||||
async def get_all_permissions(cls) -> List[PermissionInfo]:
|
async def get_all_permissions(cls) -> List[PermissionInfo]:
|
||||||
"""获取所有权限定义"""
|
"""获取所有权限定义"""
|
||||||
permissions = await Permission.all()
|
|
||||||
return [
|
return [
|
||||||
PermissionInfo(
|
PermissionInfo(
|
||||||
id=p.id,
|
code=item["code"],
|
||||||
code=p.code,
|
name=item["name"],
|
||||||
name=p.name,
|
category=item["category"],
|
||||||
category=p.category,
|
description=item.get("description"),
|
||||||
description=p.description,
|
|
||||||
)
|
)
|
||||||
for p in permissions
|
for item in PERMISSION_DEFINITIONS
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ PERMISSION_DEFINITIONS = [
|
|||||||
|
|
||||||
# Pydantic 模型
|
# Pydantic 模型
|
||||||
class PermissionInfo(BaseModel):
|
class PermissionInfo(BaseModel):
|
||||||
id: int
|
|
||||||
code: str
|
code: str
|
||||||
name: str
|
name: str
|
||||||
category: str
|
category: str
|
||||||
|
|||||||
+8
-47
@@ -1,9 +1,9 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
|
||||||
from models.database import Role, RolePermission, Permission, PathRule, UserRole
|
from models.database import Role, RolePermission, PathRule, UserRole
|
||||||
from domain.permission.service import PermissionService
|
from domain.permission.service import PermissionService
|
||||||
from domain.permission.types import PathRuleCreate, PathRuleInfo
|
from domain.permission.types import PathRuleCreate, PathRuleInfo, PERMISSION_DEFINITIONS
|
||||||
from .types import RoleInfo, RoleDetail, RoleCreate, RoleUpdate, SystemRoles
|
from .types import RoleInfo, RoleDetail, RoleCreate, RoleUpdate, SystemRoles
|
||||||
|
|
||||||
|
|
||||||
@@ -33,10 +33,8 @@ class RoleService:
|
|||||||
raise HTTPException(404, detail="角色不存在")
|
raise HTTPException(404, detail="角色不存在")
|
||||||
|
|
||||||
# 获取权限
|
# 获取权限
|
||||||
role_permissions = await RolePermission.filter(role_id=role_id).prefetch_related(
|
role_permissions = await RolePermission.filter(role_id=role_id)
|
||||||
"permission"
|
permissions = sorted(set(rp.permission_code for rp in role_permissions))
|
||||||
)
|
|
||||||
permissions = [rp.permission.code for rp in role_permissions]
|
|
||||||
|
|
||||||
# 获取路径规则数量
|
# 获取路径规则数量
|
||||||
path_rules_count = await PathRule.filter(role_id=role_id).count()
|
path_rules_count = await PathRule.filter(role_id=role_id).count()
|
||||||
@@ -126,12 +124,8 @@ class RoleService:
|
|||||||
if not role:
|
if not role:
|
||||||
raise HTTPException(404, detail="角色不存在")
|
raise HTTPException(404, detail="角色不存在")
|
||||||
|
|
||||||
# 获取权限ID
|
all_permission_codes = {item["code"] for item in PERMISSION_DEFINITIONS}
|
||||||
permissions = await Permission.filter(code__in=permission_codes)
|
invalid_codes = set(permission_codes) - all_permission_codes
|
||||||
permission_map = {p.code: p.id for p in permissions}
|
|
||||||
|
|
||||||
# 验证所有权限代码
|
|
||||||
invalid_codes = set(permission_codes) - set(permission_map.keys())
|
|
||||||
if invalid_codes:
|
if invalid_codes:
|
||||||
raise HTTPException(400, detail=f"无效的权限代码: {', '.join(invalid_codes)}")
|
raise HTTPException(400, detail=f"无效的权限代码: {', '.join(invalid_codes)}")
|
||||||
|
|
||||||
@@ -142,13 +136,13 @@ class RoleService:
|
|||||||
for code in permission_codes:
|
for code in permission_codes:
|
||||||
await RolePermission.create(
|
await RolePermission.create(
|
||||||
role_id=role_id,
|
role_id=role_id,
|
||||||
permission_id=permission_map[code],
|
permission_code=code,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 清除权限缓存
|
# 清除权限缓存
|
||||||
PermissionService.clear_cache()
|
PermissionService.clear_cache()
|
||||||
|
|
||||||
return permission_codes
|
return list(permission_codes)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_role_path_rules(cls, role_id: int) -> List[PathRuleInfo]:
|
async def get_role_path_rules(cls, role_id: int) -> List[PathRuleInfo]:
|
||||||
@@ -292,36 +286,3 @@ class RoleService:
|
|||||||
existing = await Role.get_or_none(name=role_data["name"])
|
existing = await Role.get_or_none(name=role_data["name"])
|
||||||
if not existing:
|
if not existing:
|
||||||
await Role.create(**role_data)
|
await Role.create(**role_data)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def setup_admin_role_permissions(cls) -> None:
|
|
||||||
"""为管理员角色设置所有权限"""
|
|
||||||
admin_role = await Role.get_or_none(name=SystemRoles.ADMIN)
|
|
||||||
if not admin_role:
|
|
||||||
return
|
|
||||||
|
|
||||||
# 获取所有权限
|
|
||||||
all_permissions = await Permission.all()
|
|
||||||
|
|
||||||
# 清除现有权限
|
|
||||||
await RolePermission.filter(role_id=admin_role.id).delete()
|
|
||||||
|
|
||||||
# 添加所有权限
|
|
||||||
for perm in all_permissions:
|
|
||||||
await RolePermission.create(role_id=admin_role.id, permission_id=perm.id)
|
|
||||||
|
|
||||||
# 添加全路径访问规则
|
|
||||||
existing_rule = await PathRule.filter(
|
|
||||||
role_id=admin_role.id, path_pattern="/**"
|
|
||||||
).first()
|
|
||||||
if not existing_rule:
|
|
||||||
await PathRule.create(
|
|
||||||
role_id=admin_role.id,
|
|
||||||
path_pattern="/**",
|
|
||||||
is_regex=False,
|
|
||||||
can_read=True,
|
|
||||||
can_write=True,
|
|
||||||
can_delete=True,
|
|
||||||
can_share=True,
|
|
||||||
priority=100,
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ async def get_temp_link(
|
|||||||
current_user: Annotated[User, Depends(get_current_active_user)],
|
current_user: Annotated[User, Depends(get_current_active_user)],
|
||||||
expires_in: int = Query(3600, description="有效时间(秒), 0或负数表示永久"),
|
expires_in: int = Query(3600, description="有效时间(秒), 0或负数表示永久"),
|
||||||
):
|
):
|
||||||
await PermissionService.require_path_permission(current_user.id, full_path, PathAction.SHARE)
|
await PermissionService.require_path_permission(current_user.id, full_path, PathAction.READ)
|
||||||
data = await VirtualFSService.create_temp_link(full_path, expires_in)
|
data = await VirtualFSService.create_temp_link(full_path, expires_in)
|
||||||
return success(data)
|
return success(data)
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from middleware.exception_handler import (
|
|||||||
import httpx
|
import httpx
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from domain.tasks import task_queue_service, task_scheduler
|
from domain.tasks import task_queue_service, task_scheduler
|
||||||
|
from domain.role.service import RoleService
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
@@ -66,6 +67,7 @@ async def lifespan(app: FastAPI):
|
|||||||
os.makedirs("data/db", exist_ok=True)
|
os.makedirs("data/db", exist_ok=True)
|
||||||
os.makedirs("data/plugins", exist_ok=True)
|
os.makedirs("data/plugins", exist_ok=True)
|
||||||
await init_db()
|
await init_db()
|
||||||
|
await RoleService.ensure_system_roles()
|
||||||
await runtime_registry.refresh()
|
await runtime_registry.refresh()
|
||||||
await ConfigService.set("APP_VERSION", VERSION)
|
await ConfigService.set("APP_VERSION", VERSION)
|
||||||
await task_queue_service.start_worker()
|
await task_queue_service.start_worker()
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from .database import (
|
|||||||
UserAccount,
|
UserAccount,
|
||||||
Role,
|
Role,
|
||||||
UserRole,
|
UserRole,
|
||||||
Permission,
|
|
||||||
RolePermission,
|
RolePermission,
|
||||||
PathRule,
|
PathRule,
|
||||||
)
|
)
|
||||||
@@ -13,7 +12,6 @@ __all__ = [
|
|||||||
"UserAccount",
|
"UserAccount",
|
||||||
"Role",
|
"Role",
|
||||||
"UserRole",
|
"UserRole",
|
||||||
"Permission",
|
|
||||||
"RolePermission",
|
"RolePermission",
|
||||||
"PathRule",
|
"PathRule",
|
||||||
]
|
]
|
||||||
|
|||||||
+2
-17
@@ -62,19 +62,6 @@ class UserRole(Model):
|
|||||||
unique_together = (("user", "role"),)
|
unique_together = (("user", "role"),)
|
||||||
|
|
||||||
|
|
||||||
class Permission(Model):
|
|
||||||
"""权限定义表"""
|
|
||||||
|
|
||||||
id = fields.IntField(pk=True)
|
|
||||||
code = fields.CharField(max_length=50, unique=True) # 权限代码
|
|
||||||
name = fields.CharField(max_length=100) # 权限名称
|
|
||||||
category = fields.CharField(max_length=50) # 分类:system/adapter/file
|
|
||||||
description = fields.CharField(max_length=255, null=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
table = "permissions"
|
|
||||||
|
|
||||||
|
|
||||||
class RolePermission(Model):
|
class RolePermission(Model):
|
||||||
"""角色-权限关联表"""
|
"""角色-权限关联表"""
|
||||||
|
|
||||||
@@ -82,13 +69,11 @@ class RolePermission(Model):
|
|||||||
role: fields.ForeignKeyRelation[Role] = fields.ForeignKeyField(
|
role: fields.ForeignKeyRelation[Role] = fields.ForeignKeyField(
|
||||||
"models.Role", related_name="role_permissions", on_delete=fields.CASCADE
|
"models.Role", related_name="role_permissions", on_delete=fields.CASCADE
|
||||||
)
|
)
|
||||||
permission: fields.ForeignKeyRelation[Permission] = fields.ForeignKeyField(
|
permission_code = fields.CharField(max_length=50)
|
||||||
"models.Permission", related_name="permission_roles", on_delete=fields.CASCADE
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
table = "role_permissions"
|
table = "role_permissions"
|
||||||
unique_together = (("role", "permission"),)
|
unique_together = (("role", "permission_code"),)
|
||||||
|
|
||||||
|
|
||||||
class PathRule(Model):
|
class PathRule(Model):
|
||||||
|
|||||||
+12
-153
@@ -10,17 +10,12 @@ import sys
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
DEFAULT_DB_PATH = PROJECT_ROOT / "data/db/db.sqlite3"
|
||||||
if str(PROJECT_ROOT) not in sys.path:
|
if str(PROJECT_ROOT) not in sys.path:
|
||||||
sys.path.insert(0, str(PROJECT_ROOT))
|
sys.path.insert(0, str(PROJECT_ROOT))
|
||||||
|
|
||||||
from domain.config import VERSION
|
from domain.config import VERSION
|
||||||
from domain.auth import get_password_hash
|
from domain.auth import get_password_hash
|
||||||
from domain.permission.types import PERMISSION_DEFINITIONS
|
|
||||||
from domain.role.types import SystemRoles
|
|
||||||
|
|
||||||
|
|
||||||
def _project_root() -> Path:
|
|
||||||
return PROJECT_ROOT
|
|
||||||
|
|
||||||
|
|
||||||
def _supports_color() -> bool:
|
def _supports_color() -> bool:
|
||||||
@@ -67,10 +62,6 @@ def _print_banner() -> None:
|
|||||||
print(f"{title}\n", file=sys.stderr)
|
print(f"{title}\n", file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
def _default_db_path() -> Path:
|
|
||||||
return _project_root() / "data/db/db.sqlite3"
|
|
||||||
|
|
||||||
|
|
||||||
def _gen_password(length: int) -> str:
|
def _gen_password(length: int) -> str:
|
||||||
alphabet = string.ascii_letters + string.digits
|
alphabet = string.ascii_letters + string.digits
|
||||||
return "".join(secrets.choice(alphabet) for _ in range(length))
|
return "".join(secrets.choice(alphabet) for _ in range(length))
|
||||||
@@ -78,19 +69,17 @@ def _gen_password(length: int) -> str:
|
|||||||
|
|
||||||
def _find_user(conn: sqlite3.Connection, username_or_email: str) -> tuple[int, str] | None:
|
def _find_user(conn: sqlite3.Connection, username_or_email: str) -> tuple[int, str] | None:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute("SELECT id, username FROM user WHERE username = ?", (username_or_email,))
|
|
||||||
row = cursor.fetchone()
|
|
||||||
if row:
|
|
||||||
return int(row[0]), str(row[1])
|
|
||||||
|
|
||||||
cursor.execute("SELECT id, username FROM user WHERE email = ?", (username_or_email,))
|
|
||||||
row = cursor.fetchone()
|
|
||||||
if row:
|
|
||||||
return int(row[0]), str(row[1])
|
|
||||||
|
|
||||||
normalized = username_or_email.strip().lower()
|
normalized = username_or_email.strip().lower()
|
||||||
|
|
||||||
|
candidates = [
|
||||||
|
("username", username_or_email),
|
||||||
|
("email", username_or_email),
|
||||||
|
]
|
||||||
if normalized and normalized != username_or_email:
|
if normalized and normalized != username_or_email:
|
||||||
cursor.execute("SELECT id, username FROM user WHERE email = ?", (normalized,))
|
candidates.append(("email", normalized))
|
||||||
|
|
||||||
|
for field, value in candidates:
|
||||||
|
cursor.execute(f"SELECT id, username FROM user WHERE {field} = ?", (value,))
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
if row:
|
if row:
|
||||||
return int(row[0]), str(row[1])
|
return int(row[0]), str(row[1])
|
||||||
@@ -99,7 +88,7 @@ def _find_user(conn: sqlite3.Connection, username_or_email: str) -> tuple[int, s
|
|||||||
|
|
||||||
|
|
||||||
def _cmd_reset_password(args: argparse.Namespace) -> int:
|
def _cmd_reset_password(args: argparse.Namespace) -> int:
|
||||||
db_path = Path(args.db).expanduser() if args.db else _default_db_path()
|
db_path = Path(args.db).expanduser() if args.db else DEFAULT_DB_PATH
|
||||||
|
|
||||||
if args.random:
|
if args.random:
|
||||||
password = _gen_password(args.length)
|
password = _gen_password(args.length)
|
||||||
@@ -108,8 +97,7 @@ def _cmd_reset_password(args: argparse.Namespace) -> int:
|
|||||||
|
|
||||||
hashed_password = get_password_hash(password)
|
hashed_password = get_password_hash(password)
|
||||||
|
|
||||||
conn = sqlite3.connect(str(db_path))
|
with sqlite3.connect(str(db_path)) as conn:
|
||||||
try:
|
|
||||||
user = _find_user(conn, args.username_or_email)
|
user = _find_user(conn, args.username_or_email)
|
||||||
if not user:
|
if not user:
|
||||||
print(f"用户不存在: {args.username_or_email}", file=sys.stderr)
|
print(f"用户不存在: {args.username_or_email}", file=sys.stderr)
|
||||||
@@ -120,8 +108,6 @@ def _cmd_reset_password(args: argparse.Namespace) -> int:
|
|||||||
(hashed_password, user_id),
|
(hashed_password, user_id),
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
finally:
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
if args.random:
|
if args.random:
|
||||||
print(password)
|
print(password)
|
||||||
@@ -129,129 +115,6 @@ def _cmd_reset_password(args: argparse.Namespace) -> int:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _cmd_init_rbac(args: argparse.Namespace) -> int:
|
|
||||||
db_path = Path(args.db).expanduser() if args.db else _default_db_path()
|
|
||||||
|
|
||||||
role_definitions = [
|
|
||||||
{
|
|
||||||
"name": SystemRoles.ADMIN,
|
|
||||||
"description": "管理员角色,拥有所有系统和适配器权限",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": SystemRoles.USER,
|
|
||||||
"description": "普通用户角色,需要管理员配置路径权限",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": SystemRoles.VIEWER,
|
|
||||||
"description": "只读用户角色,仅可查看文件",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
conn = sqlite3.connect(str(db_path))
|
|
||||||
try:
|
|
||||||
conn.execute("PRAGMA foreign_keys = ON")
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
try:
|
|
||||||
cursor.execute("SELECT 1 FROM permissions LIMIT 1")
|
|
||||||
cursor.execute("SELECT 1 FROM roles LIMIT 1")
|
|
||||||
cursor.execute("SELECT 1 FROM role_permissions LIMIT 1")
|
|
||||||
cursor.execute("SELECT 1 FROM path_rules LIMIT 1")
|
|
||||||
except sqlite3.OperationalError as exc:
|
|
||||||
print(f"数据库未初始化(缺少表)。请先启动一次服务生成表。{exc}", file=sys.stderr)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# upsert permissions
|
|
||||||
for perm in PERMISSION_DEFINITIONS:
|
|
||||||
cursor.execute(
|
|
||||||
"""
|
|
||||||
INSERT INTO permissions (code, name, category, description)
|
|
||||||
VALUES (?, ?, ?, ?)
|
|
||||||
ON CONFLICT(code) DO UPDATE SET
|
|
||||||
name = excluded.name,
|
|
||||||
category = excluded.category,
|
|
||||||
description = excluded.description
|
|
||||||
""",
|
|
||||||
(
|
|
||||||
perm["code"],
|
|
||||||
perm["name"],
|
|
||||||
perm["category"],
|
|
||||||
perm.get("description"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
# upsert roles
|
|
||||||
for role in role_definitions:
|
|
||||||
cursor.execute(
|
|
||||||
"""
|
|
||||||
INSERT INTO roles (name, description, is_system)
|
|
||||||
VALUES (?, ?, 1)
|
|
||||||
ON CONFLICT(name) DO UPDATE SET
|
|
||||||
description = excluded.description,
|
|
||||||
is_system = 1
|
|
||||||
""",
|
|
||||||
(role["name"], role["description"]),
|
|
||||||
)
|
|
||||||
|
|
||||||
# grant all permissions to Admin role
|
|
||||||
cursor.execute("SELECT id FROM roles WHERE name = ?", (SystemRoles.ADMIN,))
|
|
||||||
admin_row = cursor.fetchone()
|
|
||||||
if not admin_row:
|
|
||||||
print("初始化失败:未找到 Admin 角色", file=sys.stderr)
|
|
||||||
return 1
|
|
||||||
admin_role_id = int(admin_row[0])
|
|
||||||
|
|
||||||
cursor.execute("DELETE FROM role_permissions WHERE role_id = ?", (admin_role_id,))
|
|
||||||
cursor.execute("SELECT id FROM permissions")
|
|
||||||
permission_ids = [int(row[0]) for row in cursor.fetchall()]
|
|
||||||
cursor.executemany(
|
|
||||||
"INSERT INTO role_permissions (role_id, permission_id) VALUES (?, ?)",
|
|
||||||
[(admin_role_id, pid) for pid in permission_ids],
|
|
||||||
)
|
|
||||||
|
|
||||||
# ensure Admin has full access path rule
|
|
||||||
cursor.execute(
|
|
||||||
"SELECT id FROM path_rules WHERE role_id = ? AND path_pattern = ? LIMIT 1",
|
|
||||||
(admin_role_id, "/**"),
|
|
||||||
)
|
|
||||||
existing_rule = cursor.fetchone()
|
|
||||||
if existing_rule:
|
|
||||||
cursor.execute(
|
|
||||||
"""
|
|
||||||
UPDATE path_rules
|
|
||||||
SET is_regex = 0,
|
|
||||||
can_read = 1,
|
|
||||||
can_write = 1,
|
|
||||||
can_delete = 1,
|
|
||||||
can_share = 1,
|
|
||||||
priority = 100
|
|
||||||
WHERE id = ?
|
|
||||||
""",
|
|
||||||
(int(existing_rule[0]),),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
cursor.execute(
|
|
||||||
"""
|
|
||||||
INSERT INTO path_rules (
|
|
||||||
role_id, path_pattern, is_regex,
|
|
||||||
can_read, can_write, can_delete, can_share,
|
|
||||||
priority
|
|
||||||
)
|
|
||||||
VALUES (?, ?, 0, 1, 1, 1, 1, 100)
|
|
||||||
""",
|
|
||||||
(admin_role_id, "/**"),
|
|
||||||
)
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
finally:
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
print(f"已初始化权限: {len(PERMISSION_DEFINITIONS)} 条", file=sys.stderr)
|
|
||||||
print("已补齐内置角色: Admin / User / Viewer", file=sys.stderr)
|
|
||||||
print("已为 Admin 角色授予全部权限并设置 /** 全路径规则", file=sys.stderr)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def _build_parser() -> argparse.ArgumentParser:
|
def _build_parser() -> argparse.ArgumentParser:
|
||||||
parser = argparse.ArgumentParser(prog="foxel")
|
parser = argparse.ArgumentParser(prog="foxel")
|
||||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||||
@@ -264,10 +127,6 @@ def _build_parser() -> argparse.ArgumentParser:
|
|||||||
reset_password.add_argument("--db", help="sqlite db 路径(默认 data/db/db.sqlite3)")
|
reset_password.add_argument("--db", help="sqlite db 路径(默认 data/db/db.sqlite3)")
|
||||||
reset_password.set_defaults(func=_cmd_reset_password)
|
reset_password.set_defaults(func=_cmd_reset_password)
|
||||||
|
|
||||||
init_rbac = subparsers.add_parser("init-rbac", help="初始化权限与内置角色")
|
|
||||||
init_rbac.add_argument("--db", help="sqlite db 路径(默认 data/db/db.sqlite3)")
|
|
||||||
init_rbac.set_defaults(func=_cmd_init_rbac)
|
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import request from './client';
|
|||||||
import type { PathRuleInfo } from './roles';
|
import type { PathRuleInfo } from './roles';
|
||||||
|
|
||||||
export interface PermissionInfo {
|
export interface PermissionInfo {
|
||||||
id: number;
|
|
||||||
code: string;
|
code: string;
|
||||||
name: string;
|
name: string;
|
||||||
category: string;
|
category: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user