PayrollManagementSystem/backend/app/models/role.py
liuwenxin 273ebf4657 chore: 初始化项目结构与登录鉴权模块
后端 FastAPI 六层结构(api/services/repositories/models/schemas/core),
统一响应信封、全局异常、日志脱敏;6 张表经 Alembic 迁移建库,SQL 留存
db/migration;登录鉴权含图形验证码(Redis GETDEL 防重放)、JWT、登录限流、
登出黑名单(TTL=令牌剩余有效期)、登录日志。

前端 Vue3 + TS + Element Plus 骨架,含登录页、路由守卫、请求封装与 Vite 代理。

工程配置:uv 锁定 Python 3.12、ruff 检查与格式化、editorconfig、gitattributes。

测试 184 项(单元 155 / 集成 29)全绿,浏览器端到端 8 项通过。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-09 18:46:36 +08:00

106 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""角色、权限及其关联模型(RBAC 标准五表的后四张)。
权限与角色是多对多:一个权限(如「计提参数配置」)可授予多个角色,
因此关联必须独立成表,不能把 role_id 塞进 permissions 表。
"""
from datetime import datetime
from typing import TYPE_CHECKING
from sqlalchemy import DateTime, ForeignKey, Index, Integer, String, UniqueConstraint, text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.models.base import BIGINT_UNSIGNED, TINYINT_TYPE, Base, TimestampMixin, mysql_table_args
if TYPE_CHECKING:
from app.models.user import UserRole
class Role(Base, TimestampMixin):
"""角色表。本期仅 admin / user 两个角色,数据随迁移脚本初始化。"""
__tablename__ = "roles"
__table_args__ = mysql_table_args("角色表")
id: Mapped[int] = mapped_column(
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
)
role_code: Mapped[str] = mapped_column(
String(32), nullable=False, unique=True, comment="角色编码:admin系统管理员 user普通用户"
)
role_name: Mapped[str] = mapped_column(String(64), nullable=False, comment="角色名称")
description: Mapped[str | None] = mapped_column(String(255), comment="角色说明")
sort_order: Mapped[int] = mapped_column(
Integer, nullable=False, server_default="0", comment="显示排序"
)
status: Mapped[int] = mapped_column(
TINYINT_TYPE, nullable=False, server_default="1", comment="状态:1启用 0禁用"
)
user_roles: Mapped[list["UserRole"]] = relationship(back_populates="role")
class Permission(Base, TimestampMixin):
"""权限表。
perm_type 区分菜单/按钮/接口三类,parent_id 支撑树形结构。
本期只建表不填数据 —— 具体权限清单待需求澄清后确定。
"""
__tablename__ = "permissions"
__table_args__ = mysql_table_args("权限表")
id: Mapped[int] = mapped_column(
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
)
perm_code: Mapped[str] = mapped_column(
String(128), nullable=False, unique=True, comment="权限编码,如 system:user:create"
)
perm_name: Mapped[str] = mapped_column(String(64), nullable=False, comment="权限名称")
perm_type: Mapped[int] = mapped_column(
TINYINT_TYPE, nullable=False, server_default="1", comment="类型:1菜单 2按钮 3接口"
)
parent_id: Mapped[int | None] = mapped_column(
BIGINT_UNSIGNED,
ForeignKey("permissions.id", ondelete="CASCADE"),
comment="父权限ID(permissions.id),顶级为空",
)
sort_order: Mapped[int] = mapped_column(
Integer, nullable=False, server_default="0", comment="显示排序"
)
status: Mapped[int] = mapped_column(
TINYINT_TYPE, nullable=False, server_default="1", comment="状态:1启用 0禁用"
)
class RolePermission(Base):
"""角色-权限关联表。"""
__tablename__ = "role_permissions"
__table_args__ = mysql_table_args(
"角色权限关联表",
UniqueConstraint(
"role_id", "permission_id", name="uk_role_permissions_role_id_permission_id"
),
Index("idx_role_permissions_permission_id", "permission_id"),
)
id: Mapped[int] = mapped_column(
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
)
role_id: Mapped[int] = mapped_column(
BIGINT_UNSIGNED,
ForeignKey("roles.id", ondelete="CASCADE"),
nullable=False,
comment="角色ID(roles.id)",
)
permission_id: Mapped[int] = mapped_column(
BIGINT_UNSIGNED,
ForeignKey("permissions.id", ondelete="CASCADE"),
nullable=False,
comment="权限ID(permissions.id)",
)
create_time: Mapped[datetime] = mapped_column(
DateTime, nullable=False, server_default=text("CURRENT_TIMESTAMP"), comment="创建时间"
)