109 lines
4.5 KiB
Python
109 lines
4.5 KiB
Python
"""Модели пользователей, ролей и доступа."""
|
|
from datetime import date, datetime
|
|
|
|
from sqlalchemy import (
|
|
Boolean,
|
|
Date,
|
|
DateTime,
|
|
ForeignKey,
|
|
String,
|
|
UniqueConstraint,
|
|
func,
|
|
)
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.db.session import Base
|
|
from app.models.enums import LoginTokenStatus, MemberType, MessengerType, RoleCode, UserStatus
|
|
from app.models.types import enum_col
|
|
|
|
|
|
class User(Base):
|
|
__tablename__ = "users"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
full_name: Mapped[str | None] = mapped_column(String(200))
|
|
messenger_type: Mapped[MessengerType] = mapped_column(enum_col(MessengerType))
|
|
messenger_id: Mapped[str] = mapped_column(String(64))
|
|
phone: Mapped[str | None] = mapped_column(String(32))
|
|
status: Mapped[UserStatus] = mapped_column(
|
|
enum_col(UserStatus), default=UserStatus.ACTIVE
|
|
)
|
|
member_type: Mapped[MemberType | None] = mapped_column(enum_col(MemberType))
|
|
joined_at: Mapped[date | None] = mapped_column(Date)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
|
)
|
|
|
|
__table_args__ = (UniqueConstraint("messenger_type", "messenger_id", name="uq_user_messenger"),)
|
|
|
|
regions: Mapped[list["UserRegion"]] = relationship(back_populates="user")
|
|
roles: Mapped[list["UserRole"]] = relationship(
|
|
back_populates="user", foreign_keys="UserRole.user_id"
|
|
)
|
|
|
|
|
|
class UserRegion(Base):
|
|
__tablename__ = "user_regions"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"))
|
|
region_id: Mapped[int] = mapped_column(ForeignKey("regions.id", ondelete="CASCADE"))
|
|
is_primary: Mapped[bool] = mapped_column(Boolean, default=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
__table_args__ = (UniqueConstraint("user_id", "region_id", name="uq_user_region"),)
|
|
|
|
user: Mapped[User] = relationship(back_populates="regions")
|
|
|
|
|
|
class Role(Base):
|
|
__tablename__ = "roles"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
code: Mapped[RoleCode] = mapped_column(enum_col(RoleCode), unique=True)
|
|
name: Mapped[str] = mapped_column(String(100))
|
|
|
|
|
|
class UserRole(Base):
|
|
__tablename__ = "user_roles"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"))
|
|
role_id: Mapped[int] = mapped_column(ForeignKey("roles.id"))
|
|
region_id: Mapped[int | None] = mapped_column(ForeignKey("regions.id"))
|
|
granted_by: Mapped[int | None] = mapped_column(ForeignKey("users.id"))
|
|
granted_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
__table_args__ = (UniqueConstraint("user_id", "role_id", "region_id", name="uq_user_role"),)
|
|
|
|
user: Mapped[User] = relationship(back_populates="roles", foreign_keys=[user_id])
|
|
|
|
|
|
class LoginToken(Base):
|
|
__tablename__ = "login_tokens"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True)
|
|
token: Mapped[str] = mapped_column(String(128), unique=True)
|
|
user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"))
|
|
region_id: Mapped[int | None] = mapped_column(ForeignKey("regions.id"))
|
|
issued_by: Mapped[int | None] = mapped_column(ForeignKey("users.id"))
|
|
status: Mapped[LoginTokenStatus] = mapped_column(
|
|
enum_col(LoginTokenStatus), default=LoginTokenStatus.ACTIVE
|
|
)
|
|
expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
|
|
used_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
|
|
class Session(Base):
|
|
__tablename__ = "sessions"
|
|
|
|
id: Mapped[str] = mapped_column(String(36), primary_key=True)
|
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"))
|
|
token_hash: Mapped[str] = mapped_column(String(128), unique=True)
|
|
messenger_type: Mapped[MessengerType] = mapped_column(enum_col(MessengerType))
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
|
|
revoked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|