[0.9.7] - 2025-08-18
Some checks failed
Deploy on push / deploy (push) Failing after 2m22s

### 🔄 Изменения
- **SQLAlchemy KeyError** - исправление ошибки `KeyError: Reaction` при инициализации
- **Исправлена ошибка SQLAlchemy**: Устранена проблема `InvalidRequestError: When initializing mapper Mapper[Shout(shout)], expression Reaction failed to locate a name (Reaction)`

### 🧪 Тестирование
- **Исправление тестов** - адаптация к новой структуре моделей
- **RBAC инициализация** - добавление `rbac.initialize_rbac()` в `conftest.py`
- **Создан тест для getSession**: Добавлен комплексный тест `test_getSession_cookies.py` с проверкой всех сценариев
- **Покрытие edge cases**: Тесты проверяют работу с валидными/невалидными токенами, отсутствующими пользователями
- **Мокирование зависимостей**: Использование unittest.mock для изоляции тестируемого кода

### 🔧 Рефакторинг
- **Упрощена архитектура**: Убраны сложные конструкции с отложенными импортами, заменены на чистую архитектуру
- **Перемещение моделей** - `Author` и связанные модели перенесены в `orm/author.py`: Вынесены базовые модели пользователей (`Author`, `AuthorFollower`, `AuthorBookmark`, `AuthorRating`) из `orm.author` в отдельный модуль
- **Устранены циклические импорты**: Разорван цикл между `auth.core` → `orm.community` → `orm.author` через реструктуризацию архитектуры
- **Создан модуль `utils/password.py`**: Класс `Password` вынесен в utils для избежания циклических зависимостей
- **Оптимизированы импорты моделей**: Убран прямой импорт `Shout` из `orm/community.py`, заменен на строковые ссылки

### 🔧 Авторизация с cookies
- **getSession теперь работает с cookies**: Мутация `getSession` теперь может получать токен из httpOnly cookies даже без заголовка Authorization
- **Убрано требование авторизации**: `getSession` больше не требует декоратор `@login_required`, работает автономно
- **Поддержка dual-авторизации**: Токен может быть получен как из заголовка Authorization, так и из cookie `session_token`
- **Автоматическая установка cookies**: Middleware автоматически устанавливает httpOnly cookies при успешном `getSession`
- **Обновлена GraphQL схема**: `SessionInfo` теперь содержит поля `success`, `error` и опциональные `token`, `author`
- **Единообразная обработка токенов**: Все модули теперь используют централизованные функции для работы с токенами
- **Улучшена обработка ошибок**: Добавлена детальная валидация токенов и пользователей в `getSession`
- **Логирование операций**: Добавлены подробные логи для отслеживания процесса авторизации

### 📝 Документация
- **Обновлена схема GraphQL**: `SessionInfo` тип теперь соответствует новому формату ответа
- Обновлена документация RBAC
- Обновлена документация авторизации с cookies
This commit is contained in:
2025-08-18 14:25:25 +03:00
parent 9a2b792f08
commit 1b48675b92
78 changed files with 1658 additions and 1050 deletions

View File

@@ -8,11 +8,10 @@ import pytest
import time
from unittest.mock import patch, MagicMock
from auth.orm import Author, AuthorBookmark, AuthorRating, AuthorFollower
from orm.author import Author, AuthorBookmark, AuthorRating, AuthorFollower
from auth.internal import verify_internal_auth
from auth.permissions import ContextualPermissionCheck
from rbac.permissions import ContextualPermissionCheck
from orm.community import Community, CommunityAuthor
from auth.permissions import ContextualPermissionCheck
from storage.db import local_session
@@ -69,7 +68,7 @@ class TestAuthORMFixes:
rating = AuthorRating(
rater=test_users[0].id,
author=test_users[1].id,
plus=True
rating=5 # Используем поле rating вместо plus
)
db_session.add(rating)
db_session.commit()
@@ -83,15 +82,15 @@ class TestAuthORMFixes:
assert saved_rating is not None
assert saved_rating.rater == test_users[0].id
assert saved_rating.author == test_users[1].id
assert saved_rating.plus is True
assert saved_rating.rating == 5 # Проверяем поле rating
def test_author_follower_creation(self, db_session, test_users):
"""Тест создания подписки автора"""
follower = AuthorFollower(
follower=test_users[0].id,
author=test_users[1].id,
created_at=int(time.time()),
auto=False
following=test_users[1].id, # Используем поле following вместо author
created_at=int(time.time())
# Убрано поле auto, которого нет в новой модели
)
db_session.add(follower)
db_session.commit()
@@ -99,13 +98,13 @@ class TestAuthORMFixes:
# Проверяем что подписка создана
saved_follower = db_session.query(AuthorFollower).where(
AuthorFollower.follower == test_users[0].id,
AuthorFollower.author == test_users[1].id
AuthorFollower.following == test_users[1].id # Используем поле following
).first()
assert saved_follower is not None
assert saved_follower.follower == test_users[0].id
assert saved_follower.author == test_users[1].id
assert saved_follower.auto is False
assert saved_follower.following == test_users[1].id # Проверяем поле following
# Убрана проверка поля auto
def test_author_oauth_methods(self, db_session, test_users):
"""Тест методов работы с OAuth"""
@@ -145,10 +144,6 @@ class TestAuthORMFixes:
"""Тест метода dict() для сериализации"""
user = test_users[0]
# Добавляем роли
user.roles_data = {"1": ["reader", "author"]}
db_session.commit()
# Получаем словарь
user_dict = user.dict()