feat(db): all domain models, initial Alembic migration (32 tables), seed script (8 districts, 89 regions, roles)
This commit is contained in:
1 parent
71460ab56a
commit
4a610ba94a
19 files changed
+1290
-2
No files matched your search
@@ -0,0 +1,108 @@
|
||||
"""Модели пользователей, ролей и доступа."""
|
||||
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))
|
||||
Reference in new issue
Block a user