Files
ctms/backend/app/models/permission_template.py
Cheng Zhou 20ce6bccef 完全移除模块级权限系统,迁移至接口级权限
后端:
- 删除 StudyRolePermission 模型和 project_permissions API 文件
- 重写 project_permissions.py core,移除所有模块级权限函数
- 重写 permission_cache.py,移除模块级权限缓存逻辑
- 新增权限模板功能(PermissionTemplate 模型、API、服务层)
- 新增 permission_templates 数据库迁移
- 迁移 8 个模块(attachments、audit_logs、dashboard、faqs、
  faq_categories、fees_attachments、knowledge_notes、
  material_equipments、overview、subject_histories、subject_pds)
  至接口级权限检查
- 删除所有模块级权限相关测试文件,新增权限模板测试

前端:
- 删除 ProjectPermissions.vue 和 ProjectPermissionsModule.vue
- 重写 projectRoutePermissions.ts,改为基于接口级权限格式
- 更新 store/study.ts、router/index.ts、AuditLogs.vue、Projects.vue
  中的权限 API 调用,从 fetchProjectRolePermissions 改为
  fetchApiEndpointPermissions
- 清理 types/api.ts 中的旧模块级权限类型定义
- 新增 PermissionTemplateSelector.vue 组件
- 更新权限管理页面,移除模块级权限 tab

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 09:07:43 +08:00

64 lines
2.6 KiB
Python

from datetime import datetime
from enum import Enum
from typing import Optional
from uuid import UUID, uuid4
from sqlalchemy import JSON, Boolean, DateTime, Enum as SQLEnum, ForeignKey, Integer, String, UniqueConstraint, func
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.db.base_class import Base
class TemplateType(str, Enum):
ROLE = "ROLE"
SCENARIO = "SCENARIO"
CUSTOM = "CUSTOM"
class PermissionTemplate(Base):
__tablename__ = "permission_templates"
id: Mapped[UUID] = mapped_column(primary_key=True, default=uuid4)
name: Mapped[str] = mapped_column(String(100), nullable=False)
description: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
template_type: Mapped[TemplateType] = mapped_column(SQLEnum(TemplateType), nullable=False)
is_system: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default="false")
created_by: Mapped[Optional[UUID]] = mapped_column(nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now(), onupdate=func.now())
# 权限配置 JSON: {role: {endpoint_key: allowed}}
permissions: Mapped[dict] = mapped_column(JSON, nullable=False)
# 元数据
tags: Mapped[Optional[str]] = mapped_column(String(200), nullable=True)
category: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
recommended_roles: Mapped[Optional[str]] = mapped_column(String(200), nullable=True)
# 关系
versions: Mapped[list["PermissionTemplateVersion"]] = relationship(
"PermissionTemplateVersion",
back_populates="template",
cascade="all, delete-orphan",
)
class PermissionTemplateVersion(Base):
__tablename__ = "permission_template_versions"
__table_args__ = (
UniqueConstraint("template_id", "version", name="uq_template_versions"),
)
id: Mapped[UUID] = mapped_column(primary_key=True, default=uuid4)
template_id: Mapped[UUID] = mapped_column(ForeignKey("permission_templates.id"), nullable=False)
version: Mapped[int] = mapped_column(Integer, nullable=False)
permissions: Mapped[dict] = mapped_column(JSON, nullable=False)
change_log: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
# 关系
template: Mapped["PermissionTemplate"] = relationship(
"PermissionTemplate",
back_populates="versions",
)