Подготовка к переносу классов моделей
This commit is contained in:
@@ -8,15 +8,20 @@
|
||||
Описание класса SessionManager
|
||||
"""
|
||||
|
||||
from typing import NoReturn
|
||||
from typing import Type
|
||||
|
||||
from django.apps import apps
|
||||
from django.contrib.auth import authenticate
|
||||
from environ import ImproperlyConfigured
|
||||
|
||||
from net.xeaf.rack.enums import AuthRejectReason
|
||||
from net.xeaf.rack.managers import ConfigurationManager
|
||||
from net.xeaf.rack.managers import CryptoManager
|
||||
from net.xeaf.rack.models import AccountModel
|
||||
from net.xeaf.rack.models import SessionModel
|
||||
from net.xeaf.rack.utils.exceptions import UnauthorizedException
|
||||
from .account_manager import AccountManager
|
||||
|
||||
|
||||
class SessionManager[T:SessionModel]:
|
||||
@@ -27,21 +32,39 @@ class SessionManager[T:SessionModel]:
|
||||
DEFAULT_SESSION_TTL = 3600
|
||||
""" Время жизни сессии по умолчанию """
|
||||
|
||||
__model_class: Type[T] | None
|
||||
""" Хранилище для класса сессии """
|
||||
|
||||
@classmethod
|
||||
def authenticate(cls, username: str, password: str) -> SessionModel:
|
||||
def authenticate(cls, username: str, password: str, device_id: str | None = None) -> T:
|
||||
"""
|
||||
Авторизует новую сессию
|
||||
|
||||
:param username: Имя пользователя
|
||||
:param password: Пароль
|
||||
:param device_id: Идентификатор устройства
|
||||
|
||||
:return: Объект данных сессии
|
||||
"""
|
||||
|
||||
pass
|
||||
# noinspection PyTypeChecker
|
||||
account: AccountModel | None = authenticate(username=username, password=password)
|
||||
|
||||
# Обрабатываем ошибки
|
||||
if account is None:
|
||||
cls._raise_auth_error(AuthRejectReason.INVALID_USERNAME_OR_PASSWORD)
|
||||
elif not account.is_active:
|
||||
cls._raise_auth_error(AuthRejectReason.ACCOUNT_IS_NOT_ACTIVE)
|
||||
elif account.joined_at is None:
|
||||
cls._raise_auth_error(AuthRejectReason.REGISTRATION_IS_NOT_COMPLETE)
|
||||
|
||||
# Создаем и возвращаем объект сессии
|
||||
AccountManager.restore_account(account)
|
||||
session = cls.open_session(account, account, device_id)
|
||||
return session
|
||||
|
||||
@classmethod
|
||||
def find_by_token(cls, token: str) -> SessionModel | None:
|
||||
def find_by_token(cls, token: str) -> T | None:
|
||||
"""
|
||||
Возвращает объект данных сессии по токену
|
||||
|
||||
@@ -50,7 +73,8 @@ class SessionManager[T:SessionModel]:
|
||||
:return: Объект данных сессии или None, если не найдена или просрочена
|
||||
"""
|
||||
|
||||
session = SessionModel.objects.filter(token__exact=token).first()
|
||||
model = cls._get_session_model_class()
|
||||
session = model.objects.filter(token__exact=token).first()
|
||||
if session is not None and not session.is_expired():
|
||||
return session
|
||||
|
||||
@@ -74,7 +98,17 @@ class SessionManager[T:SessionModel]:
|
||||
return session
|
||||
|
||||
@classmethod
|
||||
def renew_session(cls, session: SessionModel) -> None:
|
||||
def close_session(cls, session: T) -> None:
|
||||
"""
|
||||
Закрывает сессию пользователя
|
||||
|
||||
:param session: Модель данных сессии
|
||||
"""
|
||||
|
||||
session.expire(save=True)
|
||||
|
||||
@classmethod
|
||||
def renew_session(cls, session: T) -> None:
|
||||
"""
|
||||
Обновляет время существование сессии
|
||||
|
||||
@@ -84,16 +118,6 @@ class SessionManager[T:SessionModel]:
|
||||
ttl = ConfigurationManager.get_int("SESSION_TTL", cls.DEFAULT_SESSION_TTL)
|
||||
session.renew(ttl, save=True)
|
||||
|
||||
@classmethod
|
||||
def close_session(cls, session: SessionModel) -> None:
|
||||
"""
|
||||
Закрывает сессию пользователя
|
||||
|
||||
:param session: Модель данных сессии
|
||||
"""
|
||||
|
||||
session.expire(save=True)
|
||||
|
||||
@classmethod
|
||||
def _create_session_model(cls, account: AccountModel, actual_account: AccountModel) -> T:
|
||||
"""
|
||||
@@ -118,16 +142,31 @@ class SessionManager[T:SessionModel]:
|
||||
:return: Класс модели данных сессии
|
||||
"""
|
||||
|
||||
model_path = ConfigurationManager.get_string("AUTH_SESSION_MODEL", "net_xeaf_rack.AccountModel")
|
||||
app_label, model_name = model_path.split(".")
|
||||
result = apps.get_model(app_label, model_name)
|
||||
if cls.__model_class is None:
|
||||
model_path = ConfigurationManager.get_string("AUTH_SESSION_MODEL", "net_xeaf_rack.SessionModel")
|
||||
app_label, model_name = model_path.split(".")
|
||||
model = apps.get_model(app_label, model_name)
|
||||
|
||||
# Нет класса
|
||||
if not result:
|
||||
raise ImproperlyConfigured("AUTH_SESSION_MODEL must be set in settings.py")
|
||||
# Нет класса
|
||||
if not model:
|
||||
raise ImproperlyConfigured("AUTH_SESSION_MODEL must be set in settings.py")
|
||||
|
||||
# Некорректный класс
|
||||
if not issubclass(result, SessionModel):
|
||||
raise ImproperlyConfigured(f"AUTH_SESSION_MODEL must be a subclass of {SessionModel.__name__}")
|
||||
# Некорректный класс
|
||||
if not issubclass(model, SessionModel):
|
||||
raise ImproperlyConfigured(f"AUTH_SESSION_MODEL must be a subclass of {SessionModel.__name__}")
|
||||
|
||||
return result
|
||||
cls.__model_class = model
|
||||
|
||||
# noinspection PyTypeChecker
|
||||
return cls.__model_class
|
||||
|
||||
@classmethod
|
||||
def _raise_auth_error(cls, reason: AuthRejectReason) -> NoReturn:
|
||||
"""
|
||||
Выбрасывает исключение с ошибкой аутентификации
|
||||
|
||||
:param reason: Причина ошибки
|
||||
"""
|
||||
|
||||
detail = AuthRejectReason.get_message(reason)
|
||||
raise UnauthorizedException(detail=detail, reason=reason)
|
||||
|
||||
Reference in New Issue
Block a user