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", )