from collections import namedtuple from django.conf import settings from django.db.transaction import on_commit from django.shortcuts import get_object_or_404 from rest_framework import generics, status from rest_framework.response import Response from gallery.tasks import delete_image from search_indexes.documents import es_update # JWT # Login base view mixins class JWTGenericViewMixin(generics.GenericAPIView): """JWT view mixin""" ACCESS_TOKEN_HTTP_ONLY = False ACCESS_TOKEN_SECURE = False REFRESH_TOKEN_HTTP_ONLY = False REFRESH_TOKEN_SECURE = False LOCALE_HTTP_ONLY = False LOCALE_SECURE = False COUNTRY_CODE_HTTP_ONLY = False COUNTRY_CODE_SECURE = False COOKIE = namedtuple('COOKIE', ['key', 'value', 'http_only', 'secure', 'max_age']) def _put_data_in_cookies(self, access_token: str = None, refresh_token: str = None, permanent: bool = None): """ cookies it is list that contain namedtuples cookies would contain key, value and secure parameters. """ COOKIES = [] if hasattr(self.request, 'locale'): COOKIES.append(self.COOKIE(key='locale', value=self.request.locale, http_only=self.ACCESS_TOKEN_HTTP_ONLY, secure=self.LOCALE_SECURE, max_age=settings.COOKIES_MAX_AGE if permanent else None)) if hasattr(self.request, 'country_code'): COOKIES.append(self.COOKIE(key='country_code', value=self.request.country_code, http_only=self.COUNTRY_CODE_HTTP_ONLY, secure=self.COUNTRY_CODE_SECURE, max_age=settings.COOKIES_MAX_AGE if permanent else None)) if access_token: COOKIES.append(self.COOKIE(key='access_token', value=access_token, http_only=self.ACCESS_TOKEN_HTTP_ONLY, secure=self.ACCESS_TOKEN_SECURE, max_age=settings.COOKIES_MAX_AGE if permanent else None)) if refresh_token: COOKIES.append(self.COOKIE(key='refresh_token', value=refresh_token, http_only=self.REFRESH_TOKEN_HTTP_ONLY, secure=self.REFRESH_TOKEN_SECURE, max_age=settings.COOKIES_MAX_AGE if permanent else None)) return COOKIES def _put_cookies_in_response(self, cookies: list, response: Response): """Update COOKIES in response from namedtuple""" for cookie in cookies: # todo: remove config for develop from os import environ configuration = environ.get('SETTINGS_CONFIGURATION', None) if configuration == 'development' or configuration == 'stage': response.set_cookie(key=cookie.key, value=cookie.value, secure=cookie.secure, httponly=cookie.http_only, max_age=cookie.max_age, domain='.id-east.ru') else: response.set_cookie(key=cookie.key, value=cookie.value, secure=cookie.secure, httponly=cookie.http_only, max_age=cookie.max_age,) return response def _get_tokens_from_cookies(self, request, cookies: dict = None): """Get user tokens from cookies and put in namedtuple""" _cookies = request.COOKIES or cookies return [self.COOKIE(key='access_token', value=_cookies.get('access_token'), http_only=self.ACCESS_TOKEN_HTTP_ONLY, secure=self.ACCESS_TOKEN_SECURE, max_age=_cookies.get('max_age')), self.COOKIE(key='refresh_token', value=_cookies.get('refresh_token'), http_only=self.REFRESH_TOKEN_HTTP_ONLY, secure=self.REFRESH_TOKEN_SECURE, max_age=_cookies.get('max_age'))] class CreateDestroyGalleryViewMixin(generics.CreateAPIView, generics.DestroyAPIView): """Mixin for creating and destroying entity linked with gallery.""" def create(self, request, *args, **kwargs): """Overridden create method""" super().create(request, *args, **kwargs) return Response(status=status.HTTP_201_CREATED) def destroy(self, request, *args, **kwargs): """Override destroy method.""" gallery_obj = self.get_object() if settings.USE_CELERY: on_commit(lambda: delete_image.delay(image_id=gallery_obj.image.id, completely=False)) else: on_commit(lambda: delete_image(image_id=gallery_obj.image.id, completely=False)) # Delete an instances of Gallery model gallery_obj.delete() return Response(status=status.HTTP_204_NO_CONTENT) class FavoritesCreateDestroyMixinView(generics.CreateAPIView, generics.DestroyAPIView): """Favorites Create Destroy mixin.""" _model = None serializer_class = None lookup_field = 'slug' def get_base_object(self): return get_object_or_404(self._model, slug=self.kwargs['slug']) def get_object(self): """ Returns the object the view is displaying. """ obj = self.get_base_object() favorites = get_object_or_404(obj.favorites.filter(user=self.request.user)) # May raise a permission denied self.check_object_permissions(self.request, favorites) return favorites def es_update_base_object(self): es_update(self.get_base_object()) def perform_create(self, serializer): serializer.save() self.es_update_base_object() def perform_destroy(self, instance): instance.delete() self.es_update_base_object()