""" 系統權限 Model 管理員工在各系統的存取權限 (Gitea, Portainer, etc.) 符合設計文件規範: HR Portal設計文件.md """ from datetime import datetime from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Index, UniqueConstraint from sqlalchemy.orm import relationship from app.db.base import Base class Permission(Base): """系統權限表""" __tablename__ = "tenant_permissions" __table_args__ = ( # 同一員工在同一系統只能有一個權限記錄 UniqueConstraint("employee_id", "system_name", name="uq_employee_system"), # 索引 Index("idx_permissions_employee", "employee_id"), Index("idx_permissions_tenant", "tenant_id"), Index("idx_permissions_system", "system_name"), ) id = Column(Integer, primary_key=True, index=True) tenant_id = Column( Integer, ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True, comment="租戶 ID" ) employee_id = Column( Integer, ForeignKey("tenant_employees.id", ondelete="CASCADE"), nullable=False, index=True, comment="員工 ID" ) # 權限設定 system_name = Column( String(100), nullable=False, index=True, comment="系統名稱 (gitea, portainer, traefik, keycloak)" ) access_level = Column( String(50), default='user', nullable=False, comment="存取層級 (admin/user/readonly)" ) # 授予資訊 granted_at = Column( DateTime, default=datetime.utcnow, nullable=False, comment="授予時間" ) granted_by = Column( Integer, ForeignKey("tenant_employees.id", ondelete="SET NULL"), nullable=True, comment="授予人 (員工 ID)" ) # 通用欄位 (Note: Permission 表不需要 is_active,依靠 granted_at 判斷) edit_by = Column(String(100), nullable=True, comment="最後編輯者") created_at = Column(DateTime, default=datetime.utcnow, nullable=False, comment="建立時間") updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False, comment="更新時間") # 關聯 employee = relationship( "Employee", foreign_keys=[employee_id], back_populates="permissions" ) granted_by_employee = relationship( "Employee", foreign_keys=[granted_by] ) granter = relationship( "Employee", foreign_keys=[granted_by], viewonly=True, ) tenant = relationship("Tenant") def __repr__(self): return f"" @classmethod def get_available_systems(cls) -> list[str]: """取得可用的系統清單""" return [ "gitea", # Git 代碼託管 "portainer", # 容器管理 "traefik", # 反向代理管理 "keycloak", # SSO 管理 ] @classmethod def get_available_access_levels(cls) -> list[str]: """取得可用的存取層級""" return [ "admin", # 管理員 (完整控制) "user", # 一般使用者 "readonly", # 唯讀 ]