middlware-fix
All checks were successful
Deploy on push / deploy (push) Successful in 5s

This commit is contained in:
2025-06-28 13:56:05 +03:00
parent c48f5f9368
commit 52bf78320b
5 changed files with 120 additions and 94 deletions

View File

@@ -82,69 +82,91 @@ class AuthMiddleware:
async def authenticate_user(self, token: str) -> tuple[AuthCredentials, AuthenticatedUser | UnauthenticatedUser]:
"""Аутентифицирует пользователя по токену"""
if not token:
logger.debug("[auth.authenticate] Токен отсутствует")
return AuthCredentials(
author_id=None, scopes={}, logged_in=False, error_message="no token", email=None, token=None
), UnauthenticatedUser()
# Проверяем сессию в Redis
payload = await TokenManager.verify_session(token)
if not payload:
logger.debug("[auth.authenticate] Недействительный токен")
return AuthCredentials(
author_id=None, scopes={}, logged_in=False, error_message="Invalid token", email=None, token=None
), UnauthenticatedUser()
try:
payload = await TokenManager.verify_session(token)
if not payload:
logger.debug("[auth.authenticate] Недействительный токен или сессия не найдена")
return AuthCredentials(
author_id=None,
scopes={},
logged_in=False,
error_message="Invalid token or session",
email=None,
token=None,
), UnauthenticatedUser()
with local_session() as session:
try:
author = session.query(Author).filter(Author.id == payload.user_id).one()
with local_session() as session:
try:
author = session.query(Author).filter(Author.id == payload.user_id).one()
if author.is_locked():
logger.debug(f"[auth.authenticate] Аккаунт заблокирован: {author.id}")
if author.is_locked():
logger.debug(f"[auth.authenticate] Аккаунт заблокирован: {author.id}")
return AuthCredentials(
author_id=None,
scopes={},
logged_in=False,
error_message="Account is locked",
email=None,
token=None,
), UnauthenticatedUser()
# Получаем разрешения из ролей
scopes = author.get_permissions()
# Получаем роли для пользователя
roles = [role.id for role in author.roles] if author.roles else []
# Обновляем last_seen
author.last_seen = int(time.time())
session.commit()
# Создаем объекты авторизации с сохранением токена
credentials = AuthCredentials(
author_id=author.id,
scopes=scopes,
logged_in=True,
error_message="",
email=author.email,
token=token,
)
user = AuthenticatedUser(
user_id=str(author.id),
username=author.slug or author.email or "",
roles=roles,
permissions=scopes,
token=token,
)
logger.debug(f"[auth.authenticate] Успешная аутентификация: {author.email}")
return credentials, user
except exc.NoResultFound:
logger.debug("[auth.authenticate] Пользователь не найден в базе данных")
return AuthCredentials(
author_id=None,
scopes={},
logged_in=False,
error_message="Account is locked",
error_message="User not found",
email=None,
token=None,
), UnauthenticatedUser()
# Получаем разрешения из ролей
scopes = author.get_permissions()
# Получаем роли для пользователя
roles = [role.id for role in author.roles] if author.roles else []
# Обновляем last_seen
author.last_seen = int(time.time())
session.commit()
# Создаем объекты авторизации с сохранением токена
credentials = AuthCredentials(
author_id=author.id,
scopes=scopes,
logged_in=True,
error_message="",
email=author.email,
token=token,
)
user = AuthenticatedUser(
user_id=str(author.id),
username=author.slug or author.email or "",
roles=roles,
permissions=scopes,
token=token,
)
logger.debug(f"[auth.authenticate] Успешная аутентификация: {author.email}")
return credentials, user
except exc.NoResultFound:
logger.debug("[auth.authenticate] Пользователь не найден")
return AuthCredentials(
author_id=None, scopes={}, logged_in=False, error_message="User not found", email=None, token=None
), UnauthenticatedUser()
except Exception as e:
logger.error(f"[auth.authenticate] Ошибка при работе с базой данных: {e}")
return AuthCredentials(
author_id=None, scopes={}, logged_in=False, error_message=str(e), email=None, token=None
), UnauthenticatedUser()
except Exception as e:
logger.error(f"[auth.authenticate] Ошибка при проверке сессии: {e}")
return AuthCredentials(
author_id=None, scopes={}, logged_in=False, error_message=str(e), email=None, token=None
), UnauthenticatedUser()
async def __call__(
self,

View File

@@ -15,7 +15,15 @@ from auth.tokens.storage import TokenStorage
from resolvers.auth import generate_unique_slug
from services.db import local_session
from services.redis import redis
from settings import FRONTEND_URL, OAUTH_CLIENTS
from settings import (
FRONTEND_URL,
OAUTH_CLIENTS,
SESSION_COOKIE_HTTPONLY,
SESSION_COOKIE_MAX_AGE,
SESSION_COOKIE_NAME,
SESSION_COOKIE_SAMESITE,
SESSION_COOKIE_SECURE,
)
from utils.logger import root_logger as logger
# Type для dependency injection сессии
@@ -302,7 +310,10 @@ async def oauth_login(_: None, _info: GraphQLResolveInfo, provider: str, callbac
async def oauth_callback(request: Any) -> JSONResponse | RedirectResponse:
"""Обрабатывает callback от OAuth провайдера"""
"""
Обработчик OAuth callback.
Создает или обновляет пользователя и устанавливает сессионный токен.
"""
try:
# Получаем state из query параметров
state = request.query_params.get("state")
@@ -341,12 +352,12 @@ async def oauth_callback(request: Any) -> JSONResponse | RedirectResponse:
redirect_url = f"{stored_redirect_uri}?state={state}&access_token={session_token}"
response = RedirectResponse(url=redirect_url)
response.set_cookie(
"session_token",
SESSION_COOKIE_NAME,
session_token,
httponly=True,
secure=True,
samesite="lax",
max_age=30 * 24 * 60 * 60, # 30 days
httponly=SESSION_COOKIE_HTTPONLY,
secure=SESSION_COOKIE_SECURE,
samesite=SESSION_COOKIE_SAMESITE,
max_age=SESSION_COOKIE_MAX_AGE,
)
return response
@@ -460,12 +471,12 @@ async def oauth_callback_http(request: Request) -> JSONResponse | RedirectRespon
# Возвращаем redirect с cookie
response = RedirectResponse(url="/auth/success", status_code=307)
response.set_cookie(
"session_token",
SESSION_COOKIE_NAME,
session_token,
httponly=True,
secure=True,
samesite="lax",
max_age=30 * 24 * 60 * 60, # 30 дней
httponly=SESSION_COOKIE_HTTPONLY,
secure=SESSION_COOKIE_SECURE,
samesite=SESSION_COOKIE_SAMESITE,
max_age=SESSION_COOKIE_MAX_AGE,
)
return response

View File

@@ -230,6 +230,10 @@ class SessionTokenManager(BaseTokenManager):
"""
Проверяет сессию по токену для совместимости с TokenStorage
"""
if not token:
logger.debug("Пустой токен")
return None
logger.debug(f"Проверка сессии для токена: {token[:20]}...")
# Декодируем токен для получения payload
@@ -239,15 +243,23 @@ class SessionTokenManager(BaseTokenManager):
logger.error("Не удалось декодировать токен")
return None
if not hasattr(payload, "user_id"):
logger.error("В токене отсутствует user_id")
return None
logger.debug(f"Успешно декодирован токен, user_id={payload.user_id}")
except Exception as e:
logger.error(f"Ошибка при декодировании токена: {e}")
return None
# Проверяем валидность токена
valid, _ = await self.validate_session_token(token)
if valid:
logger.debug(f"Сессия найдена для пользователя {payload.user_id}")
return payload
logger.warning(f"Сессия не найдена: {payload.user_id}")
return None
try:
valid, error = await self.validate_session_token(token)
if valid:
logger.debug(f"Сессия найдена для пользователя {payload.user_id}")
return payload
logger.warning(f"Сессия не найдена: {payload.user_id}, ошибка: {error}")
return None
except Exception as e:
logger.error(f"Ошибка при валидации сессии: {e}")
return None