Подготовка к реализации авторизации сессии

This commit is contained in:
2026-07-13 01:52:04 +03:00
parent 1acd7c0029
commit c9a75b3370
2 changed files with 150 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса AccountManager
"""
class AccountManager:
"""
Реализует методы работы с Аккаунтами
"""
pass

View File

@@ -0,0 +1,133 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса SessionManager
"""
from typing import Type
from django.apps import apps
from environ import ImproperlyConfigured
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
class SessionManager[T:SessionModel]:
"""
Реализует методы работы с Сессиями
"""
DEFAULT_SESSION_TTL = 3600
""" Время жизни сессии по умолчанию """
@classmethod
def authenticate(cls, username: str, password: str) -> SessionModel:
"""
Авторизует новую сессию
:param username: Имя пользователя
:param password: Пароль
:return: Объект данных сессии
"""
pass
@classmethod
def find_by_token(cls, token: str) -> SessionModel | None:
"""
Возвращает объект данных сессии по токену
:param token: Токен
:return: Объект данных сессии или None, если не найдена или просрочена
"""
session = SessionModel.objects.filter(token__exact=token).first()
if session is not None and not session.is_expired():
return session
return None
@classmethod
def open_session(cls, account: AccountModel, actual_account: AccountModel, device_id: str | None = None) -> T:
"""
Открывает сессию для аккаунта
:param account: Модель данных Аккаунта пользователя
:param actual_account: Актуальный Аккаунт пользователя
:param device_id: Идентификатор устройства
:return: Информация о сессии
"""
session = cls._create_session_model(account, actual_account)
session.device_id = device_id
cls.renew_session(session)
return session
@classmethod
def renew_session(cls, session: SessionModel) -> None:
"""
Обновляет время существование сессии
:param session: Модель данных сессии
"""
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:
"""
Создает новую модель Сессии
:param account: Аккаунт пользователя
:param actual_account: Актуальный Аккаунт пользователя
"""
model = cls._get_session_model_class()
return model.objects.create(
token=CryptoManager.gen_token(),
account=account,
actual_account=actual_account
)
@classmethod
def _get_session_model_class(cls) -> Type[T]:
"""
Возвращает класс модели данных сессии
: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 not result:
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__}")
return result