From 8abbd4eab0eccc7a7e2df656eabec33152654339 Mon Sep 17 00:00:00 2001 From: Nazarii Date: Sat, 7 Sep 2024 23:14:12 +0300 Subject: [PATCH] Update logout flow --- web/api/v1/auth_app/services.py | 63 ++++++++++++++------------------- web/api/v1/auth_app/views.py | 8 ++--- web/api/v1/blog/services.py | 1 - 3 files changed, 30 insertions(+), 42 deletions(-) diff --git a/web/api/v1/auth_app/services.py b/web/api/v1/auth_app/services.py index 7a2b8db..3659cef 100644 --- a/web/api/v1/auth_app/services.py +++ b/web/api/v1/auth_app/services.py @@ -1,3 +1,4 @@ +import logging from typing import TYPE_CHECKING from urllib.parse import quote, urlencode, urljoin @@ -36,6 +37,8 @@ User: 'UserType' = get_user_model() +logger = logging.getLogger(__name__) + class PasswordResetHandler: def __init__(self, email: dict): @@ -212,42 +215,30 @@ def verify_email_confirm(key: str) -> User: return user -def full_logout(request): - response = Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) - auth_cookie_name = settings.REST_AUTH['JWT_AUTH_COOKIE'] - refresh_cookie_name = settings.REST_AUTH['JWT_AUTH_REFRESH_COOKIE'] - - response.delete_cookie(auth_cookie_name) - refresh_token = request.COOKIES.get(refresh_cookie_name) - if refresh_cookie_name: - response.delete_cookie(refresh_cookie_name) - try: - token = RefreshToken(refresh_token) - token.blacklist() - except KeyError: - response.data = {"detail": _("Refresh token was not included in request data.")} - response.status_code = status.HTTP_401_UNAUTHORIZED - except (TokenError, AttributeError, TypeError) as error: - if hasattr(error, 'args'): - if 'Token is blacklisted' in error.args or 'Token is invalid or expired' in error.args: - response.data = {"detail": _(error.args[0])} - response.status_code = status.HTTP_401_UNAUTHORIZED - else: - response.data = {"detail": _("An error has occurred.")} - response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR - - else: - response.data = {"detail": _("An error has occurred.")} - response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR - - else: - message = _( - "Neither cookies or blacklist are enabled, so the token " - "has not been deleted server side. Please make sure the token is deleted client side." - ) - response.data = {"detail": message} - response.status_code = status.HTTP_200_OK - return response +class LogoutService: + + def __init__(self, request): + self.request = request + self.access_cookie_name = settings.REST_AUTH['JWT_AUTH_COOKIE'] + self.refresh_cookie_name = settings.REST_AUTH['JWT_AUTH_REFRESH_COOKIE'] + + def _delete_cookies(self, response: Response): + response.delete_cookie(self.access_cookie_name) + response.delete_cookie(self.refresh_cookie_name) + + def _blacklist_refresh_token(self, refresh_token: str): + try: + token = RefreshToken(refresh_token) + token.blacklist() + except TokenError as e: + logger.warning(f'Failed blacklist Token from {self.request.user}.\nException: {e}') + + def logout(self): + response = Response({"detail": _("Successfully logged out.")}, status=status.HTTP_200_OK) + self._delete_cookies(response) + if refresh_token := self.request.COOKIES.get(self.refresh_cookie_name): + self._blacklist_refresh_token(refresh_token) + return response class OAuthLoginService: diff --git a/web/api/v1/auth_app/views.py b/web/api/v1/auth_app/views.py index fb4a9a5..43047df 100644 --- a/web/api/v1/auth_app/views.py +++ b/web/api/v1/auth_app/views.py @@ -7,7 +7,7 @@ from . import serializers from .managers import PasswordResetManager -from .services import AuthAppService, LoginService, PasswordResetHandler, SignUpHandler, full_logout +from .services import AuthAppService, LoginService, PasswordResetHandler, SignUpHandler, LogoutService class SignUpView(GenericAPIView): @@ -40,11 +40,9 @@ def post(self, request): class LogoutView(APIView): - allowed_methods = ('POST', 'OPTIONS') - def post(self, request): - response = full_logout(request) - return response + service = LogoutService(request) + return service.logout() class PasswordResetView(GenericAPIView): diff --git a/web/api/v1/blog/services.py b/web/api/v1/blog/services.py index 53fb160..b8329b7 100644 --- a/web/api/v1/blog/services.py +++ b/web/api/v1/blog/services.py @@ -116,7 +116,6 @@ def _save_tags(self, tags: list[str], article: Article) -> None: @transaction.atomic def create_article(self, author: 'UserType', article_data: CreateArticleT) -> Article: - print(f'{article_data=}') slug = self._get_slug(article_data['title']) if self.is_article_slug_exist(slug): raise ValidationError('Article with this title already exists')