""" Middleware для проверки подтверждения email пользователя. Блокирует все запросы, кроме связанных с подтверждением email. """ from django.http import JsonResponse from django.utils.deprecation import MiddlewareMixin from rest_framework_simplejwt.authentication import JWTAuthentication from rest_framework_simplejwt.exceptions import InvalidToken, TokenError class EmailVerificationMiddleware(MiddlewareMixin): """ Middleware для проверки подтверждения email. Разрешает доступ к следующим endpoints без подтверждения email: - /api/users/auth/register/ - /api/users/auth/login/ - /api/users/auth/telegram/ - /api/users/auth/telegram/bot-info/ - /api/users/auth/token/refresh/ - /api/users/auth/verify-email/ - /api/users/auth/resend-verification/ - /api/users/auth/password-reset/ - /api/users/auth/password-reset-confirm/ - /api/users/auth/logout/ - /api/docs/ (Swagger документация) - /api/schema/ (API схема) """ # Список путей, которые разрешены без подтверждения email ALLOWED_PATHS = [ # Аутентификация и регистрация '/api/auth/register/', '/api/auth/login/', '/api/auth/telegram/', '/api/auth/telegram/bot-info/', '/api/auth/token/refresh/', '/api/auth/verify-email/', '/api/auth/resend-verification/', '/api/auth/change-password/', '/api/auth/password-reset/', '/api/auth/password-reset-confirm/', '/api/auth/logout/', # API документация '/api/swagger/', '/api/swagger.json', '/api/swagger.yaml', '/api/redoc/', '/api/schema/', # Статические файлы и медиа '/static/', '/media/', # Admin панель '/admin/', # Health check '/health/', ] def process_request(self, request): """ Обработка запроса перед передачей в view. """ # Проверяем, является ли путь разрешенным if self._is_allowed_path(request.path): return None # Разрешаем запрос # Проверяем, есть ли токен авторизации if not self._has_auth_token(request): return None # Если нет токена, пусть другие middleware обрабатывают # Получаем пользователя из токена user = self._get_user_from_token(request) if user is None: return None # Если не удалось получить пользователя, пусть другие middleware обрабатывают # Проверяем подтверждение email if not user.email_verified: return JsonResponse( { 'success': False, 'error': 'email_not_verified', 'message': 'Необходимо подтвердить email адрес для доступа к платформе', 'email': user.email, }, status=403 ) return None # Разрешаем запрос def _is_allowed_path(self, path: str) -> bool: """ Проверяет, является ли путь разрешенным. """ # Проверяем точное совпадение if path in self.ALLOWED_PATHS: return True # Проверяем, начинается ли путь с разрешенного for allowed_path in self.ALLOWED_PATHS: if path.startswith(allowed_path): return True # Разрешаем доступ к статическим файлам и медиа if path.startswith('/static/') or path.startswith('/media/'): return True # Разрешаем доступ к admin панели if path.startswith('/admin/'): return True return False def _has_auth_token(self, request) -> bool: """ Проверяет наличие токена авторизации в запросе. """ # Проверяем заголовок Authorization auth_header = request.META.get('HTTP_AUTHORIZATION', '') if auth_header.startswith('Bearer '): return True # Проверяем токен в cookies (если используется) if 'access_token' in request.COOKIES: return True return False def _get_user_from_token(self, request): """ Получает пользователя из JWT токена. """ try: # Используем JWTAuthentication для получения пользователя jwt_auth = JWTAuthentication() header = jwt_auth.get_header(request) if header is None: return None raw_token = jwt_auth.get_raw_token(header) if raw_token is None: return None validated_token = jwt_auth.get_validated_token(raw_token) user = jwt_auth.get_user(validated_token) return user except (InvalidToken, TokenError, AttributeError, TypeError, ValueError): # Если токен невалиден или отсутствует, возвращаем None return None except Exception: # Для любых других ошибок также возвращаем None return None