134 lines
4.3 KiB
Python
134 lines
4.3 KiB
Python
# 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
|