134 lines
6.9 KiB
Python
134 lines
6.9 KiB
Python
"""
|
||
Middleware для валидации входных данных
|
||
"""
|
||
from typing import Any, Dict, Callable, Awaitable
|
||
|
||
from aiogram import BaseMiddleware
|
||
from aiogram.types import TelegramObject, CallbackQuery, Message
|
||
|
||
from services.infrastructure.logger import get_logger
|
||
from services.validation import InputValidator
|
||
from services.infrastructure.logging_decorators import log_middleware
|
||
from services.infrastructure.logging_utils import log_user_action
|
||
|
||
logger = get_logger(__name__)
|
||
|
||
|
||
class ValidationMiddleware(BaseMiddleware):
|
||
"""Middleware для валидации входных данных"""
|
||
|
||
def __init__(self, validator: InputValidator):
|
||
super().__init__()
|
||
self.validator = validator
|
||
logger.info("🔍 ValidationMiddleware инициализирован")
|
||
|
||
@log_middleware(log_params=True, log_result=False)
|
||
async def __call__(
|
||
self,
|
||
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
|
||
event: TelegramObject,
|
||
data: Dict[str, Any]
|
||
) -> Any:
|
||
"""Валидация входных данных перед обработкой"""
|
||
|
||
try:
|
||
# Валидация callback queries
|
||
if isinstance(event, CallbackQuery):
|
||
await self._validate_callback_query(event, data)
|
||
|
||
# Валидация сообщений
|
||
elif isinstance(event, Message):
|
||
await self._validate_message(event, data)
|
||
|
||
# Продолжаем обработку
|
||
return await handler(event, data)
|
||
|
||
except ValidationError as e:
|
||
logger.warning(f"⚠️ Ошибка валидации: {e}")
|
||
await self._handle_validation_error(event, str(e))
|
||
return
|
||
|
||
@log_middleware(log_params=True, log_result=False)
|
||
async def _validate_callback_query(self, callback: CallbackQuery, data: Dict[str, Any]) -> None:
|
||
"""Валидация callback query"""
|
||
try:
|
||
# Валидируем callback data
|
||
validation_result = self.validator.validate_callback_data(callback.data)
|
||
if not validation_result:
|
||
logger.warning(f"⚠️ Невалидный callback data от пользователя {callback.from_user.id}: {callback.data}")
|
||
await callback.answer("❌ Неверные данные", show_alert=True)
|
||
raise ValidationError(f"Invalid callback data: {validation_result.error_message}")
|
||
|
||
# Валидируем Telegram ID пользователя
|
||
user_id_validation = self.validator.validate_telegram_id(callback.from_user.id)
|
||
if not user_id_validation:
|
||
logger.warning(f"⚠️ Невалидный Telegram ID в callback: {callback.from_user.id}")
|
||
await callback.answer("❌ Ошибка: недопустимый ID пользователя", show_alert=True)
|
||
raise ValidationError(f"Invalid Telegram ID: {user_id_validation.error_message}")
|
||
|
||
# Валидируем username если есть
|
||
if callback.from_user.username:
|
||
username_validation = self.validator.validate_username(callback.from_user.username)
|
||
if not username_validation:
|
||
logger.warning(f"⚠️ Невалидный username в callback: {callback.from_user.username}")
|
||
# Username не критичен, только логируем
|
||
|
||
logger.debug(f"✅ Callback query от пользователя {callback.from_user.id} прошел валидацию")
|
||
|
||
except Exception as e:
|
||
if not isinstance(e, ValidationError):
|
||
logger.error(f"❌ Ошибка валидации callback query: {e}")
|
||
await callback.answer("❌ Ошибка валидации", show_alert=True)
|
||
raise ValidationError(f"Callback validation error: {str(e)}")
|
||
raise
|
||
|
||
@log_middleware(log_params=True, log_result=False)
|
||
async def _validate_message(self, message: Message, data: Dict[str, Any]) -> None:
|
||
"""Валидация сообщения"""
|
||
try:
|
||
# Валидируем Telegram ID пользователя
|
||
user_id_validation = self.validator.validate_telegram_id(message.from_user.id)
|
||
if not user_id_validation:
|
||
logger.warning(f"⚠️ Невалидный Telegram ID в сообщении: {message.from_user.id}")
|
||
await message.answer("❌ Ошибка: недопустимый ID пользователя")
|
||
raise ValidationError(f"Invalid Telegram ID: {user_id_validation.error_message}")
|
||
|
||
# Валидируем username если есть
|
||
if message.from_user.username:
|
||
username_validation = self.validator.validate_username(message.from_user.username)
|
||
if not username_validation:
|
||
logger.warning(f"⚠️ Невалидный username в сообщении: {message.from_user.username}")
|
||
# Username не критичен, только логируем
|
||
|
||
# Валидируем chat ID
|
||
chat_id_validation = self.validator.validate_telegram_id(message.chat.id)
|
||
if not chat_id_validation:
|
||
logger.warning(f"⚠️ Невалидный chat ID в сообщении: {message.chat.id}")
|
||
await message.answer("❌ Ошибка: недопустимый ID чата")
|
||
raise ValidationError(f"Invalid chat ID: {chat_id_validation.error_message}")
|
||
|
||
logger.debug(f"✅ Сообщение от пользователя {message.from_user.id} прошло валидацию")
|
||
|
||
except Exception as e:
|
||
if not isinstance(e, ValidationError):
|
||
logger.error(f"❌ Ошибка валидации сообщения: {e}")
|
||
await message.answer("❌ Ошибка валидации")
|
||
raise ValidationError(f"Message validation error: {str(e)}")
|
||
raise
|
||
|
||
@log_middleware(log_params=True, log_result=False)
|
||
async def _handle_validation_error(self, event: TelegramObject, error_message: str) -> None:
|
||
"""Обработка ошибок валидации"""
|
||
try:
|
||
if isinstance(event, CallbackQuery):
|
||
await event.answer(f"❌ {error_message}", show_alert=True)
|
||
elif isinstance(event, Message):
|
||
await event.answer(f"❌ {error_message}")
|
||
except Exception as e:
|
||
logger.error(f"❌ Ошибка при отправке сообщения об ошибке валидации: {e}")
|
||
|
||
|
||
class ValidationError(Exception):
|
||
"""Исключение для ошибок валидации"""
|
||
pass
|