class Permission(Model, SurrogatePK): """ 角色表 :attr name: str(80) 权限名称 :attr description: str(255) 权限描述 :attr roles: Role 所有角色 :attr users: User 所有用户 """ __tablename__ = "permissions" name = db.Column(db.String(80), unique=True, doc="权限名称", nullable=True) description = db.Column(db.String(255), doc="权限描述") @classmethod def get_by_name(cls, name: str) -> Model: return cls.query.filter_by(name=name).first() @classmethod def get_by_names(cls, *names: List[str]) -> Model: return cls.query.filter(cls.name.in_(names)).all() def __str__(self) -> str: return self.name
class Log(Model, SurrogatePK): """ 日志 :attr module: str(128) 请求模块 :attr line: int 行 :attr level 日志等级 :attr message 日志消息 """ __tablename__ = "logs" module = db.Column(db.String(length=128), nullable=False, doc="请求模块") line = db.Column(db.Integer, nullable=False, doc="行", info={"marshmallow": { "dump_only": True }}) level = db.Column(db.String(length=20), nullable=False, doc="日志等级") message = db.Column(db.TEXT, nullable=False, doc="日志消息", info={"marshmallow": { "dump_only": True }})
class Role(Model, SurrogatePK): """ 角色表 :attr name: str(80) 角色名称 :attr description: str(255) 角色描述 :attr permissions: Permission 所有权限 :attr user_default: bool 用户默认角色 :attr group_default: bool 组默认角色 """ __tablename__ = "roles" name = db.Column(db.String(80), unique=True, doc="角色名称", nullable=True) description = db.Column(db.String(255), doc="角色描述") user_default = db.Column(db.Boolean, doc="用户默认角色", default=False) group_default = db.Column(db.Boolean, doc="组默认角色", default=False) permissions = db.relationship( "Permission", secondary=permission_roles, doc="所有权限", primaryjoin="foreign(permission_roles.c.role_id) == Role.id", secondaryjoin= "foreign(permission_roles.c.permission_id) == Permission.id", backref=db.backref("roles", lazy="dynamic", doc="所有角色"), info={"marshmallow": { "column": ["id", "name"] }}) @classmethod def get_by_name(cls, name: str) -> Model: return cls.query.filter_by(name=name).first() @classmethod def get_by_user_default(cls, is_admin=False) -> Model: if is_admin: return cls.query.filter_by(name=ROLES.SuperUser).all() return cls.query.filter_by(user_default=True).all() def add_permissions(self, permissions: List[Permission]) -> List[Permission]: """ 获取权限 兼容flask-security """ for permission in permissions: if permission not in self.permissions: self.permissions.append(permission) return list(permission.name for permission in self.permissions) def __str__(self) -> str: return self.name
class UserInfo(SurrogatePK, Model): """ 用户信息表 :attr avator_id: int 用户头像ID :attr uid: int 用户ID :attr avator: Storages 用户头像 :attr user: User 关联用户 :attr sex: int 性别 :attr age: int 年龄 :attr first_name: str(80) 姓 :attr second_name: str(80) 名 """ __tablename__ = "userinfo" avator_id = db.Column( db.Integer, doc="头像ID", info={"marshmallow": {"dump_only": True}} ) uid = db.Column(db.Integer, doc="用户ID") sex = db.Column(db.Integer, doc="性别", default=1,) age = db.Column(db.Integer, doc="年龄",) first_name = db.Column(db.String(80), doc="姓",) last_name = db.Column(db.String(80), doc="名",) user = db.relationship( "User", doc="用户", primaryjoin="User.id_ == UserInfo.uid", foreign_keys=uid, ) avator = db.relationship( Storages, primaryjoin="Storages.id_ == UserInfo.avator_id", foreign_keys=avator_id, doc="头像", lazy="joined", ) def __repr__(self) -> str: return self.nickname @property def nickname(self) -> str: if self.first_name and self.last_name: return self.first_name + " " + self.last_name return self.user.username @property def sex_label(self) -> str: """性别标签""" labels = {1: "男", 2: "女"} try: return labels[self.sex] except KeyError: return "未填写"
class Group(Model, SurrogatePK, BaseNestedSets): """ 用户组 :attr name: str(128) 用户组名称 :attr description str(255) 组描述 :attr default bool 是否为初始化默认组 :attr roles 所有角色 :attr users 所有用户 """ sqlalchemy_mptt_pk_name = "id_" __tablename__ = "groups" name = db.Column(db.String(length=128), nullable=False, doc="用户组名称") description = db.Column(db.String(255), doc="组描述") default = db.Column(db.Boolean, default=False, doc="初始化默认组") users = db.relationship( "User", secondary="groups_users", primaryjoin="Group.id_ == groups_users.c.group_id", secondaryjoin="User.id_ == groups_users.c.user_id", doc="组下用户", foreign_keys="[groups_users.c.group_id, groups_users.c.user_id]", active_history=True, lazy="joined", info={"marshmallow": { "column": ["id", "username"] }}, ) roles = db.relationship( "Role", uselist=True, secondary="groups_roles", primaryjoin="Group.id_ == groups_roles.c.group_id", secondaryjoin="Role.id_ == groups_roles.c.role_id", doc="组下默认角色", foreign_keys="[groups_roles.c.group_id, groups_roles.c.role_id]", active_history=True, lazy="joined", info={"marshmallow": { "column": ["id", "name"] }}, ) @classmethod def get_by_name(cls, name: str) -> Group: return cls.where(name=name).first_or_404() def __repr__(self) -> str: return self.name
class Role(Model, SurrogatePK): """ 角色表 :attr name: str(80) 角色名称 :attr description: str(255) 角色描述 :attr permissions: Permission 所有权限 :attr user_default: bool 用户默认角色 :attr group_default: bool 组默认角色 """ __tablename__ = "roles" name = db.Column(db.String(80), unique=True, doc="角色名称", nullable=False) description = db.Column(db.String(255), doc="角色描述") user_default = db.Column(db.Boolean, doc="用户默认角色", default=False) group_default = db.Column(db.Boolean, doc="组默认角色", default=False) permissions = db.relationship( "Permission", uselist=True, secondary=permission_roles, doc="所有权限", primaryjoin="foreign(permission_roles.c.role_id) == Role.id_", secondaryjoin= "foreign(permission_roles.c.permission_id) == Permission.id_", # backref=db.backref("roles", lazy="dynamic", doc="所有角色"), ) @classmethod def get_by_name(cls, name: str) -> Role: return cls.where(name=name).first_or_404() @classmethod def get_by_user_default(cls, is_admin: bool = False) -> List[Role]: if is_admin: return cls.where(name__in=[ROLES.SuperUser, ROLES.User]).all() return cls.where(user_default=True).all() def add_permissions(self, permissions: List[Permission]) -> List[str]: """ 获取权限 兼容flask-security """ for permission in permissions: if permission not in self.permissions: assert isinstance(self.permissions, list) self.permissions.append(permission) return list(permission.name for permission in self.permissions)
class Code(Model, SurrogatePK, BaseNestedSets): """ 编码 :attr name: str(128) 编码名称 """ sqlalchemy_mptt_pk_name = "id_" __tablename__ = "codes" name = db.Column(db.String(length=128), nullable=False, doc="编码名称") type_code = db.Column(db.String(length=16), nullable=False, doc="类型码") def __repr__(self) -> str: return self.name
class EmailTemplate(Model, SurrogatePK): """ 电子邮件模板 :attr name: str(128) 电子邮件模板名称 """ __tablename__ = "email_templates" name = db.Column( db.String(length=128), nullable=False, unique=True, doc="email_templates的名称" ) template = db.Column(db.Text, nullable=False, doc="模板") @classmethod def get_by_name(cls, name): return cls.query.filter_by(name=name).one() @classmethod def get_template(cls, name): """获取模板""" template = cls.get_by_name(name) return template.template def __repr__(self): return self.name
class EmailTemplate(Model, SurrogatePK): """ 电子邮件模板 :attr name: str(128) 电子邮件模板名称 """ __tablename__ = "email_templates" name = db.Column(db.String(length=128), nullable=False, unique=True, doc="email_templates的名称") template = db.Column(db.Text, nullable=False, doc="模板") @classmethod def get_by_name(cls, name: str) -> EmailTemplate: """根据名称获取电子邮箱模板""" return cls.where(name=name).first_or_404() @classmethod def get_template(cls, name: str) -> str: """获取模板""" template = cls.get_by_name(name) return template.template def __repr__(self) -> str: return self.name
class TokenBlackList(SurrogatePK, Model): """ Token Black List Table :attr user_identity: str(50) 验证信息 :attr jit: str(36) 36位jti信息 :attr revoked: bool 是否撤销 :attr token_type: str(10) token类型 :attr expires: DateTime 过期时间 """ __tablename__ = "jwt_token_blacklist" user_identity = db.Column(db.String(50), nullable=False) jti = db.Column(db.String(36), unique=True, nullable=False) revoked = db.Column(db.Boolean, nullable=False) token_type = db.Column(db.String(10), nullable=False) expires = db.Column(db.DateTime(True), nullable=False)
class ResponseLog(Model, SurrogatePK): """ 请求日志 :attr url: str(4096) url地址 :attr arguments: json 请求数据 :attr method: str(10) 请求方法 :attr ip: str(128) IP地址 :attr module: str(128) 模块名 :attr status_code: int 状态码 """ __tablename__ = "response_logs" url = db.Column(db.String(4096), nullable=False, doc="请求url") arguments = db.Column(JSONType, doc="请求数据") method = db.Column(db.String(10), nullable=False, doc="请求方法") ip = db.Column(db.String(128), doc="IP地址") module = db.Column(db.String(128), doc="模块名") status_code = db.Column(db.Integer, doc="状态码")
class Permission(Model, SurrogatePK): """ 角色表 :attr name: str(80) 权限名称 :attr description: str(255) 权限描述 :attr roles: Role 所有角色 :attr users: User 所有用户 """ __tablename__ = "permissions" name = db.Column(db.String(80), unique=True, doc="权限名称", nullable=False) description = db.Column(db.String(255), doc="权限描述") @classmethod def get_by_name(cls, name: str) -> Optional[Permission]: return cls.where(name=name).first() @classmethod def get_by_names(cls, *names: str) -> List[Permission]: return cls.where(name__in=names).all()
class Menu(Model, SurrogatePK, BaseNestedSets): """ 菜单 :attr name: str(128) 菜单名称 """ sqlalchemy_mptt_pk_name = "id_" __tablename__ = "menus" name = db.Column(db.String(length=128), nullable=False, doc="菜单名称") img = db.Column(db.String(512), doc="菜单图片") url = db.Column(db.String(512), doc="菜单URL") permission_id = db.Column(db.Integer) permission = db.relationship( "Permission", primaryjoin="Permission.id_ == Menu.permission_id", foreign_keys=permission_id, uselist=False, ) def __repr__(self) -> str: return self.name
class Project(Model, SurrogatePK): """ 项目 Attribute: name (str): 项目名称,禁止非空,非值,最大长度128 """ __tablename__ = "projects" name = db.Column(db.String(length=128), nullable=False, doc="项目名称") def __repr__(self) -> str: return self.name
class User(Model, SurrogatePK): """ 用户表 :attr username: str(255) 用户名 :attr email: str(255) 用户邮箱 :attr password: str(255) 用户密码 :attr active: bool 是否启用 :attr confirmed_at: DateTime 确认时间 :attr roles: Role 角色 :attr permissions: Permission 权限 """ __tablename__ = "users" username = db.Column(db.String(255), nullable=False, unique=True, doc="用户名") phonenum = db.Column(db.String(255), nullable=True, unique=True, doc="电话号码") email = db.Column(db.String(255), nullable=True, unique=True, doc="用户邮箱") password = db.Column( PasswordType(schemes=["pbkdf2_sha512"]), nullable=False, doc="用户密码" ) active = db.Column(db.Boolean(), doc="启用", default=False) confirmed_at = db.Column(db.DateTime(), doc="确认时间") roles = db.relationship( "Role", secondary=roles_users, doc="所有角色", primaryjoin="foreign(roles_users.c.user_id) == User.id", secondaryjoin="foreign(roles_users.c.role_id) == Role.id", backref=db.backref("users", lazy="dynamic", doc="所有用户"), info={"marshmallow": {"column": ["id", "name"]}}, ) permissions = db.relationship( "Permission", secondary=user_permissions, doc="权限", primaryjoin="User.id == roles_users.c.user_id", secondaryjoin="Permission.id == permission_roles.c.permission_id", backref=db.backref("users", doc="用户", lazy="dynamic"), viewonly=True, info={"marshmallow": {"dump_only": True, "column": ["id", "name"]}}, ) @classmethod def get_by_keyword(cls, keyword: str) -> Model: """ 根据邮箱获取用户 """ return cls.query.filter( db.and_( cls.deleted.is_(False), db.or_( cls.email == keyword, cls.username == keyword, cls.phonenum == keyword, ), ) ).first() def __str__(self) -> str: # pragma: no cover return self.email @property def nickname(self) -> str: if self.userinfo.first_name and self.userinfo.last_name: return self.userinfo.first_name + " " + self.userinfo.last_name return self.username
class UserInfo(SurrogatePK, Model): """ 用户信息表 :attr avator_id: int 用户头像ID :attr uid: int 用户ID :attr avator: Storages 用户头像 :attr user: User 关联用户 :attr sex: int 性别 :attr age: int 年龄 :attr first_name: str(80) 姓 :attr second_name: str(80) 名 """ # from app.modules.storages.models import Storages __tablename__ = "userinfo" avator_id = db.Column( db.Integer, doc="头像ID", info={"marshmallow": {"dump_only": True}} ) uid = db.Column(db.Integer, doc="用户ID", info={"marshmallow": {"dump_only": True}}) avator = db.relationship( "Storages", primaryjoin="Storages.id == UserInfo.avator_id", foreign_keys=avator_id, doc="头像", lazy="joined", info={"marshmallow": {"dump_only": True}}, ) sex = db.Column( db.Integer, doc="性别", default=1, info={ "marshmallow": { "validate": [OneOf([1, 2])], "allow_none": False, "required": True, } }, ) age = db.Column( db.Integer, doc="年龄", info={ "marshmallow": { "allow_none": False, "validate": [Range(1, None)], "required": True, } }, ) first_name = db.Column( db.String(80), doc="姓", info={"marshmallow": {"allow_none": False, "required": True}}, ) last_name = db.Column( db.String(80), doc="名", info={"marshmallow": {"allow_none": False, "required": True}}, ) user = db.relationship( "User", doc="用户", primaryjoin="User.id == UserInfo.uid", foreign_keys=uid, backref=db.backref( "userinfo", uselist=False, lazy="joined", info={ "marshmallow": { "column": ["avator_id", "first_name", "last_name", "sex", "age"] } }, ), info={"marshmallow": {"dump_only": True}}, ) def __str__(self) -> str: return self.user.username @property def sex_label(self) -> str: """性别标签""" labels = {1: "男", 2: "女"} try: return labels[self.sex] except KeyError: return "未填写"
class User(Model, SurrogatePK): """ 用户表 :attr username required: str(255) 用户名 :attr email: str(255) 用户邮箱 :attr password required: str(255) 用户密码 :attr phonenum: str(255) 电话号码 :attr active opt: bool 是否启用 :attr confirmed_at: DateTime 确认时间 :attr roles: Role 角色 :attr permissions: Permission 权限 :attr userinfo required: UserInfo 用户详情 :attr groups: Group 用户组信息 """ __tablename__ = "users" username = db.Column(db.String(255), nullable=False, unique=True, doc="用户名") phonenum = db.Column(db.String(255), nullable=True, unique=True, doc="电话号码") email = db.Column(db.String(255), nullable=True, unique=True, doc="用户邮箱") password = db.Column( PasswordType(schemes=["pbkdf2_sha512"]), nullable=False, doc="用户密码" ) active = db.Column(db.Boolean(), doc="启用", default=False) confirmed_at = db.Column(db.DateTime(), doc="确认时间") roles = db.relationship( "Role", secondary=roles_users, uselist=True, doc="所有角色", primaryjoin="foreign(roles_users.c.user_id) == User.id_", secondaryjoin="foreign(roles_users.c.role_id) == Role.id_", # backref=db.backref("users", lazy="dynamic", doc="所有用户"), order_by="Role.id_", ) permissions = db.relationship( "Permission", secondary=user_permissions, doc="权限", primaryjoin="User.id_ == roles_users.c.user_id", secondaryjoin="Permission.id_ == permission_roles.c.permission_id", viewonly=True, ) userinfo = db.relationship( "UserInfo", doc="用户", primaryjoin="User.id_ == UserInfo.uid", foreign_keys="UserInfo.uid", uselist=False, lazy="joined", ) groups = db.relationship( Group, secondary=groups_users, uselist=True, primaryjoin="User.id_ == groups_users.c.user_id", secondaryjoin=Group.id_ == groups_users.c.group_id, doc="组下用户", foreign_keys=[groups_users.c.group_id, groups_users.c.user_id], ) @classmethod def get_by_keyword(cls, keyword: str) -> User: """ 根据邮箱获取用户 """ return cls.query.filter( db.or_( cls.email == keyword, cls.username == keyword, cls.phonenum == keyword, ), ).first_or_404() def __repr__(self) -> str: # pragma: no cover return self.nickname @property def nickname(self) -> str: if self.userinfo: return self.userinfo.nickname return self.username