lesslogs
All checks were successful
Deploy on push / deploy (push) Successful in 2m55s

This commit is contained in:
2025-09-28 17:26:23 +03:00
parent 752e2dcbdc
commit af0f3e3dea
3 changed files with 17 additions and 154 deletions

View File

@@ -44,12 +44,6 @@ class EnhancedGraphQLHTTPHandler(GraphQLHTTPHandler):
except Exception as e:
logger.debug(f"[graphql] Ошибка при получении заголовков: {e}")
logger.debug(f"[graphql] Заголовки в get_context_for_request: {list(headers.keys())}")
if "authorization" in headers:
logger.debug(f"[graphql] Authorization header найден: {headers['authorization'][:50]}...")
else:
logger.debug("[graphql] Authorization header НЕ найден")
# Получаем стандартный контекст от базового класса
context = await super().get_context_for_request(request, data)
@@ -67,15 +61,6 @@ class EnhancedGraphQLHTTPHandler(GraphQLHTTPHandler):
auth_cred: Any | None = request.scope.get("auth")
context["auth"] = auth_cred
# Безопасно логируем информацию о типе объекта auth
logger.debug(f"[graphql] Добавлены данные авторизации в контекст из scope: {type(auth_cred).__name__}")
# Проверяем, есть ли токен в auth_cred
if auth_cred is not None and hasattr(auth_cred, "token") and auth_cred.token:
token_val = auth_cred.token
token_len = len(token_val) if hasattr(token_val, "__len__") else 0
logger.debug(f"[graphql] Токен найден в auth_cred: {token_len}")
else:
logger.debug("[graphql] Токен НЕ найден в auth_cred")
# Добавляем author_id в контекст для RBAC
author_id = None
@@ -89,16 +74,8 @@ class EnhancedGraphQLHTTPHandler(GraphQLHTTPHandler):
try:
author_id_int = int(str(author_id).strip())
context["author"] = {"id": author_id_int}
logger.debug(f"[graphql] Добавлен author_id в контекст: {author_id_int}")
except (ValueError, TypeError) as e:
logger.error(f"[graphql] Ошибка преобразования author_id {author_id}: {e}")
context["author"] = {"id": author_id}
logger.debug(f"[graphql] Добавлен author_id как строка: {author_id}")
else:
logger.debug("[graphql] author_id не найден в auth_cred")
else:
logger.debug("[graphql] Данные авторизации НЕ найдены в scope")
logger.debug("[graphql] Подготовлен расширенный контекст для запроса")
return context

View File

@@ -28,7 +28,6 @@ from settings import (
SESSION_TOKEN_HEADER,
)
from storage.db import local_session
from storage.redis import redis as redis_adapter
from utils.logger import root_logger as logger
ADMIN_EMAILS = ADMIN_EMAILS_LIST.split(",")
@@ -82,7 +81,6 @@ 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()
@@ -202,24 +200,6 @@ class AuthMiddleware:
scope_headers = scope.get("headers", [])
if scope_headers:
headers.update({k.decode("utf-8").lower(): v.decode("utf-8") for k, v in scope_headers})
logger.debug(f"[middleware] Получены заголовки из scope: {len(headers)}")
# Проверяем наличие authorization заголовка
if "authorization" in headers:
logger.debug(f"[middleware] Authorization заголовок найден: {headers['authorization'][:50]}...")
else:
logger.debug("[middleware] Authorization заголовок НЕ найден в scope headers")
else:
logger.debug("[middleware] Заголовки scope отсутствуют")
# Логируем все заголовки для диагностики
logger.debug(f"[middleware] Все заголовки: {list(headers.keys())}")
# Логируем конкретные заголовки для диагностики
auth_header_value = headers.get("authorization", "")
logger.debug(f"[middleware] Authorization header: {auth_header_value[:50]}...")
session_token_value = headers.get(SESSION_TOKEN_HEADER.lower(), "")
logger.debug(f"[middleware] {SESSION_TOKEN_HEADER} header: {session_token_value[:50]}...")
# Используем тот же механизм получения токена, что и в декораторе
token = None
@@ -227,100 +207,31 @@ class AuthMiddleware:
# 0. Проверяем сохраненный токен в scope (приоритет)
if "auth_token" in scope:
token = scope["auth_token"]
logger.debug(f"[middleware] Токен получен из scope.auth_token: {len(token)}")
else:
logger.debug("[middleware] scope.auth_token НЕ найден")
# Стандартная система сессий уже обрабатывает кэширование
# Дополнительной проверки Redis кэша не требуется
# Отладка: детальная информация о запросе без Authorization
if not token:
# Проверяем, есть ли активные сессии в Redis
try:
# Получаем все активные сессии
session_keys = await redis_adapter.keys("session:*")
logger.debug(f"[middleware] Найдено активных сессий в Redis: {len(session_keys)}")
if session_keys:
# Пытаемся найти токен через активные сессии
for session_key in session_keys[:3]: # Проверяем первые 3 сессии
try:
session_data = await redis_adapter.hgetall(session_key)
if session_data:
logger.debug(f"[middleware] Найдена активная сессия: {session_key}")
# Извлекаем user_id из ключа сессии
user_id = (
session_key.decode("utf-8").split(":")[1]
if isinstance(session_key, bytes)
else session_key.split(":")[1]
)
logger.debug(f"[middleware] User ID из сессии: {user_id}")
break
except Exception as e:
logger.debug(f"[middleware] Ошибка чтения сессии {session_key}: {e}")
else:
logger.debug("[middleware] Активных сессий в Redis не найдено")
except Exception as e:
logger.debug(f"[middleware] Ошибка проверки сессий: {e}")
# 1. Проверяем заголовок Authorization
if not token:
auth_header = headers.get("authorization", "")
if auth_header:
if auth_header.startswith("Bearer "):
token = auth_header[7:].strip()
logger.debug(f"[middleware] Токен получен из заголовка Authorization: {len(token)}")
else:
token = auth_header.strip()
logger.debug(f"[middleware] Прямой токен получен из заголовка Authorization: {len(token)}")
token = auth_header[7:].strip() if auth_header.startswith("Bearer ") else auth_header.strip()
# 2. Проверяем основной заголовок авторизации, если Authorization не найден
if not token:
auth_header = headers.get(SESSION_TOKEN_HEADER.lower(), "")
if auth_header:
if auth_header.startswith("Bearer "):
token = auth_header[7:].strip()
logger.debug(f"[middleware] Токен получен из заголовка {SESSION_TOKEN_HEADER}: {len(token)}")
else:
token = auth_header.strip()
logger.debug(f"[middleware] Прямой токен получен из заголовка {SESSION_TOKEN_HEADER}: {len(token)}")
token = auth_header[7:].strip() if auth_header.startswith("Bearer ") else auth_header.strip()
# 3. Проверяем cookie
if not token:
cookies = headers.get("cookie", "")
logger.debug(f"[middleware] Проверяем cookies: {cookies[:100]}...")
logger.debug(f"[middleware] Ищем cookie с именем: '{SESSION_COOKIE_NAME}'")
# 🔍 Диагностика cookies (только для debug уровня)
if not cookies:
logger.debug("[middleware] Cookie заголовок отсутствует")
logger.debug(f"[middleware] Доступные заголовки: {list(headers.keys())}")
# 💋 OAuth не использует cookies - это нормальное поведение
logger.debug("[middleware] OAuth система работает без cookies - токены передаются через заголовки")
cookie_items = cookies.split(";")
found_cookies = []
for item in cookie_items:
if "=" in item:
name, value = item.split("=", 1)
cookie_name = name.strip()
found_cookies.append(cookie_name)
if cookie_name == SESSION_COOKIE_NAME:
token = value.strip()
logger.debug(
f"[middleware] ✅ Токен получен из cookie {SESSION_COOKIE_NAME}: {len(token)} символов"
)
break
logger.debug(f"[middleware] Найденные cookies: {found_cookies}")
if not token:
logger.debug(f"[middleware] ❌ Cookie '{SESSION_COOKIE_NAME}' не найден среди: {found_cookies}")
if token:
logger.debug(f"[middleware] Токен найден: {len(token)} символов")
else:
logger.debug("[middleware] Токен не найден")
if cookies:
cookie_items = cookies.split(";")
for item in cookie_items:
if "=" in item:
name, value = item.split("=", 1)
cookie_name = name.strip()
if cookie_name == SESSION_COOKIE_NAME:
token = value.strip()
break
# Аутентифицируем пользователя
auth, user = await self.authenticate_user(token or "")
@@ -332,21 +243,12 @@ class AuthMiddleware:
# Сохраняем токен в scope для использования в последующих запросах
if token:
scope["auth_token"] = token
logger.debug(f"[middleware] Токен сохранен в scope.auth_token: {len(token)}")
logger.debug(f"[middleware] Пользователь аутентифицирован: {user.is_authenticated}")
# Токен уже сохранен в стандартной системе сессий через SessionTokenManager
# Дополнительного кэширования не требуется
logger.debug("[middleware] Токен обработан стандартной системой сессий")
else:
logger.debug("[middleware] Токен не найден, пользователь неаутентифицирован")
await self.app(scope, receive, send)
def set_context(self, context) -> None:
"""Сохраняет ссылку на контекст GraphQL запроса"""
self._context = context
logger.debug(f"[middleware] Установлен контекст GraphQL: {bool(context)}")
def set_cookie(self, key: str, value: str, **options: Any) -> None:
"""
@@ -363,7 +265,6 @@ class AuthMiddleware:
if self._context and "response" in self._context and hasattr(self._context["response"], "set_cookie"):
try:
self._context["response"].set_cookie(key, value, **options)
logger.debug(f"[middleware] Установлена cookie {key} через response")
success = True
except Exception as e:
logger.error(f"[middleware] Ошибка при установке cookie {key} через response: {e!s}")
@@ -372,7 +273,6 @@ class AuthMiddleware:
if not success and hasattr(self, "_response") and self._response and hasattr(self._response, "set_cookie"):
try:
self._response.set_cookie(key, value, **options)
logger.debug(f"[middleware] Установлена cookie {key} через _response")
success = True
except Exception as e:
logger.error(f"[middleware] Ошибка при установке cookie {key} через _response: {e!s}")
@@ -390,7 +290,6 @@ class AuthMiddleware:
if self._context and "response" in self._context and hasattr(self._context["response"], "delete_cookie"):
try:
self._context["response"].delete_cookie(key, **options)
logger.debug(f"[middleware] Удалена cookie {key} через response")
success = True
except Exception as e:
logger.error(f"[middleware] Ошибка при удалении cookie {key} через response: {e!s}")
@@ -399,7 +298,6 @@ class AuthMiddleware:
if not success and hasattr(self, "_response") and self._response and hasattr(self._response, "delete_cookie"):
try:
self._response.delete_cookie(key, **options)
logger.debug(f"[middleware] Удалена cookie {key} через _response")
success = True
except Exception as e:
logger.error(f"[middleware] Ошибка при удалении cookie {key} через _response: {e!s}")
@@ -427,9 +325,6 @@ class AuthMiddleware:
# Проверяем наличие response в контексте
if "response" not in context or not context["response"]:
context["response"] = JSONResponse({})
logger.debug("[middleware] Создан новый response объект в контексте GraphQL")
logger.debug("[middleware] GraphQL resolve: контекст подготовлен, добавлены расширения для работы с cookie")
return await next_resolver(root, info, *args, **kwargs)
except Exception as e:
@@ -457,16 +352,8 @@ class AuthMiddleware:
data = await request.json()
op_name = data.get("operationName", "").lower()
# 💋 OAuth НЕ использует cookies - токены передаются только через заголовки/localStorage
# Убираем автоматическую установку cookies для login/refreshtoken/getSession
if op_name in ["login", "refreshtoken", "getsession"]:
logger.debug(f"[graphql_handler] Операция {op_name}: токены передаются БЕЗ cookies")
logger.debug(
"[graphql_handler] Фронтенд должен извлечь токен из ответа и управлять им самостоятельно"
)
# Если это операция logout, удаляем cookie
elif op_name == "logout":
if op_name == "logout":
response.delete_cookie(
key=SESSION_COOKIE_NAME,
secure=SESSION_COOKIE_SECURE,
@@ -474,9 +361,8 @@ class AuthMiddleware:
samesite=SESSION_COOKIE_SAMESITE
if SESSION_COOKIE_SAMESITE in ["strict", "lax", "none"]
else "none",
domain=SESSION_COOKIE_DOMAIN, # ✅ КРИТИЧНО: тот же domain что при установке
domain=SESSION_COOKIE_DOMAIN,
)
logger.debug(f"[graphql_handler] Удалена cookie {SESSION_COOKIE_NAME} для операции {op_name}")
except Exception as e:
logger.error(f"[process_result] Ошибка при обработке POST запроса: {e!s}")

View File

@@ -342,14 +342,14 @@ def get_shouts_with_links(
if has_field(info, "main_topic") or force_topics:
main_topic = None
if hasattr(row, "main_topic"):
logger.debug(f"Raw main_topic for shout#{shout_id}: {row.main_topic}")
# logger.debug(f"Raw main_topic for shout#{shout_id}: {row.main_topic}")
main_topic = (
orjson.loads(row.main_topic) if isinstance(row.main_topic, str) else row.main_topic
)
logger.debug(f"Parsed main_topic for shout#{shout_id}: {main_topic}")
# logger.debug(f"Parsed main_topic for shout#{shout_id}: {main_topic}")
if not main_topic and topics and len(topics) > 0:
logger.info(f"No main_topic found for shout#{shout_id}, using first topic from list")
# logger.info(f"No main_topic found for shout#{shout_id}, using first topic from list")
main_topic = {
"id": topics[0]["id"],
"title": topics[0]["title"],
@@ -365,7 +365,7 @@ def get_shouts_with_links(
"is_main": True,
}
shout_dict["main_topic"] = main_topic
logger.debug(f"Final main_topic for shout#{shout_id}: {main_topic}")
# logger.debug(f"Final main_topic for shout#{shout_id}: {main_topic}")
if has_field(info, "authors") and hasattr(row, "authors"):
authors_data = orjson.loads(row.authors) if isinstance(row.authors, str) else row.authors