token-storage-refactored
Some checks failed
Deploy on push / type-check (push) Failing after 8s
Deploy on push / deploy (push) Has been skipped

This commit is contained in:
2025-06-02 21:50:58 +03:00
parent cca2f71c59
commit 21d28a0d8b
33 changed files with 2934 additions and 1533 deletions

View File

@@ -142,8 +142,8 @@ with (
assert "Invalid provider" in body_content.decode()
@pytest.mark.asyncio
async def test_oauth_callback_success(mock_request, mock_oauth_client):
"""Тест успешного OAuth callback"""
async def test_oauth_callback_success(mock_request, mock_oauth_client, oauth_db_session):
"""Тест успешного OAuth callback с правильной БД"""
mock_request.session = {
"provider": "google",
"code_verifier": "test_verifier",
@@ -157,15 +157,9 @@ with (
with (
patch("auth.oauth.oauth.create_client", return_value=mock_oauth_client),
patch("auth.oauth.local_session") as mock_session,
patch("auth.oauth.TokenStorage.create_session", return_value="test_token"),
patch("auth.oauth.get_oauth_state", return_value={"provider": "google"}),
):
# Мокаем сессию базы данных
session = MagicMock()
session.query.return_value.filter.return_value.first.return_value = None
mock_session.return_value.__enter__.return_value = session
response = await oauth_callback_http(mock_request)
assert isinstance(response, RedirectResponse)
@@ -200,8 +194,13 @@ with (
assert "Invalid or expired OAuth state" in body_content.decode()
@pytest.mark.asyncio
async def test_oauth_callback_existing_user(mock_request, mock_oauth_client):
"""Тест OAuth callback с существующим пользователем"""
async def test_oauth_callback_existing_user(mock_request, mock_oauth_client, oauth_db_session):
"""Тест OAuth callback с существующим пользователем через реальную БД"""
from auth.orm import Author
# Сессия уже предоставлена через oauth_db_session fixture
session = oauth_db_session
mock_request.session = {
"provider": "google",
"code_verifier": "test_verifier",
@@ -215,27 +214,16 @@ with (
with (
patch("auth.oauth.oauth.create_client", return_value=mock_oauth_client),
patch("auth.oauth.local_session") as mock_session,
patch("auth.oauth.TokenStorage.create_session", return_value="test_token"),
patch("auth.oauth.get_oauth_state", return_value={"provider": "google"}),
):
# Создаем мок существующего пользователя с правильными атрибутами
existing_user = MagicMock()
existing_user.name = "Test User" # Устанавливаем имя напрямую
existing_user.email_verified = True # Устанавливаем значение напрямую
existing_user.set_oauth_account = MagicMock() # Мок метода
session = MagicMock()
session.query.return_value.filter.return_value.first.return_value = existing_user
mock_session.return_value.__enter__.return_value = session
response = await oauth_callback_http(mock_request)
assert isinstance(response, RedirectResponse)
assert response.status_code == 307
# Проверяем обновление существующего пользователя
assert existing_user.name == "Test User"
# Проверяем, что OAuth аккаунт установлен через новый метод
existing_user.set_oauth_account.assert_called_with("google", "123", email="test@gmail.com")
assert existing_user.email_verified is True
# Проверяем что пользователь был создан в БД через OAuth flow
created_user = session.query(Author).filter(Author.email == "test@gmail.com").first()
assert created_user is not None
assert created_user.name == "Test User"
assert created_user.email_verified is True

View File

@@ -0,0 +1,99 @@
"""
Тест для проверки исправления ошибки SessionInfo.token в GraphQL
"""
import asyncio
import json
import requests
async def test_get_session():
"""
Тестирует GraphQL запрос getSession после исправления
"""
# GraphQL запрос для получения сессии
query = """
mutation {
getSession {
token
author {
id
name
slug
email
}
}
}
"""
# Данные запроса
payload = {"query": query, "variables": {}}
# Заголовки запроса
headers = {"Content-Type": "application/json", "Accept": "application/json"}
try:
# Отправляем запрос к GraphQL endpoint
url = "http://localhost:8000/graphql"
print(f"Отправка GraphQL запроса к {url}")
response = requests.post(url, json=payload, headers=headers, timeout=10)
print(f"Статус ответа: {response.status_code}")
if response.status_code == 200:
result = response.json()
print("Ответ GraphQL:")
print(json.dumps(result, indent=2, ensure_ascii=False))
# Проверяем наличие ошибок
if "errors" in result:
print("❌ GraphQL ошибки найдены:")
for error in result["errors"]:
print(f" - {error.get('message', 'Неизвестная ошибка')}")
if "Cannot return null for non-nullable field SessionInfo.token" in error.get("message", ""):
print("❌ Исходная ошибка SessionInfo.token всё ещё присутствует")
return False
else:
print("✅ GraphQL ошибок не найдено")
# Проверяем структуру данных
data = result.get("data", {})
session_info = data.get("getSession", {})
if session_info:
if "token" in session_info and "author" in session_info:
print("✅ Структура SessionInfo корректна")
return True
print("❌ Некорректная структура SessionInfo")
return False
print("❌ Данные getSession отсутствуют")
return False
else:
print(f"❌ HTTP ошибка: {response.status_code}")
print(response.text)
return False
except requests.exceptions.ConnectionError:
print("Не удалось подключиться к серверу. Убедитесь, что сервер запущен на localhost:8000")
return False
except Exception as e:
print(f"❌ Ошибка при выполнении запроса: {e}")
return False
if __name__ == "__main__":
print("🔍 Тестирование исправления GraphQL ошибки SessionInfo.token")
print("-" * 60)
result = asyncio.run(test_get_session())
print("-" * 60)
if result:
print("✅ Тест пройден успешно!")
else:
print("❌ Тест не пройден")
print("\nПримечание: Ошибка 'Unauthorized' ожидаема, так как мы не передаём токен авторизации.")
print("Главное - что исчезла ошибка 'Cannot return null for non-nullable field SessionInfo.token'")

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""
Тест для проверки исправленной системы токенов
"""
import pytest
from auth.tokens.monitoring import TokenMonitoring
from auth.tokens.sessions import SessionTokenManager
from auth.tokens.storage import TokenStorage
@pytest.mark.asyncio
async def test_token_storage(redis_client):
"""Тест базовой функциональности TokenStorage с правильными fixtures"""
print("✅ Тестирование TokenStorage...")
# Тест создания сессии
print("1. Создание сессии...")
token = await TokenStorage.create_session(user_id="test_user_123", username="test_user", device_info={"test": True})
print(f" Создан токен: {token[:20]}...")
# Тест проверки сессии
print("2. Проверка сессии...")
session_data = await TokenStorage.verify_session(token)
if session_data:
print(f" Сессия найдена для user_id: {session_data.user_id}")
else:
print(" ❌ Сессия не найдена")
return False
# Тест прямого использования SessionTokenManager
print("3. Прямое использование SessionTokenManager...")
sessions = SessionTokenManager()
valid, data = await sessions.validate_session_token(token)
print(f" Валидация: {valid}, данные: {bool(data)}")
# Тест мониторинга
print("4. Мониторинг токенов...")
monitoring = TokenMonitoring()
stats = await monitoring.get_token_statistics()
print(f" Активных сессий: {stats.get('session_tokens', 0)}")
# Очистка
print("5. Отзыв сессии...")
revoked = await TokenStorage.revoke_session(token)
print(f" Отозван: {revoked}")
print("Все тесты пройдены успешно!")
return True