66 lines
2.2 KiB
Python
66 lines
2.2 KiB
Python
import uuid
|
|
|
|
from hashlib import md5
|
|
from typing import TYPE_CHECKING, List
|
|
|
|
from barker.models.login_history import LoginHistory
|
|
from barker.models.user_role import UserRole
|
|
from sqlalchemy import Boolean, Index, Unicode, desc, func, select, text
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from sqlalchemy.ext.hybrid import hybrid_property
|
|
from sqlalchemy.orm import Mapped, Session, mapped_column, relationship
|
|
|
|
from ..db.base_class import reg
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
from .role import Role
|
|
|
|
|
|
@reg.mapped_as_dataclass(unsafe_hash=True)
|
|
class User:
|
|
__tablename__ = "users"
|
|
id: Mapped[uuid.UUID] = mapped_column(
|
|
"id", UUID(as_uuid=True), primary_key=True, server_default=text("gen_random_uuid()"), insert_default=uuid.uuid4
|
|
)
|
|
name: Mapped[str] = mapped_column("name", Unicode(255), nullable=False)
|
|
_password: Mapped[str] = mapped_column("password", Unicode(60), nullable=False)
|
|
locked_out: Mapped[bool] = mapped_column("locked_out", Boolean, nullable=False)
|
|
|
|
roles: Mapped[List["Role"]] = relationship(
|
|
"Role", secondary=UserRole.__table__, order_by="Role.name" # type: ignore[attr-defined]
|
|
)
|
|
login_history: Mapped[List["LoginHistory"]] = relationship(order_by=desc(LoginHistory.date), back_populates="user")
|
|
|
|
Index("uq_users_name", func.lower(name), unique=True)
|
|
|
|
@hybrid_property
|
|
def password(self):
|
|
return self._password
|
|
|
|
@password.inplace.setter
|
|
def _password_setter(self, value: str) -> None:
|
|
self._password = encrypt(value)
|
|
|
|
def __init__(self, name=None, password=None, locked_out=None, id_=None):
|
|
self.name = name
|
|
self.password = password
|
|
self.locked_out = locked_out
|
|
self.id = id_
|
|
|
|
@classmethod
|
|
def auth(cls, name: str, password: str, db: Session):
|
|
if password is None:
|
|
return None
|
|
user = db.execute(select(User).where(User.name.ilike(name))).scalars().one_or_none()
|
|
if not user:
|
|
return None
|
|
if user.password != encrypt(password) or user.locked_out:
|
|
return None
|
|
else:
|
|
return user
|
|
|
|
|
|
def encrypt(val):
|
|
return md5(val.encode("utf-8") + "v2".encode("utf-8")).hexdigest()
|