You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
7.8 KiB

from datetime import datetime
from django.conf import settings
from django.shortcuts import get_object_or_404
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from pytz import timezone
from rest_framework import status
from rest_framework.generics import RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView, RetrieveAPIView, CreateAPIView, ListAPIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import AllowAny, IsAuthenticated, IsAdminUser
from rest_framework.response import Response
from rest_framework.views import APIView
from core.permissions import IsAuthorOrReadOnly
from crypto.services import encrypt
from .models import CustomUser, RefreshToken
from .repositories import RefreshTokenRepository, ProfileRepository, UserRepository, QRCodeRepository
from .serializers import RegistrationSerializer, LoginSerializer, CustomUserSerializer, ProfileSerializer, QRCodeSerializer
from .renderers import CustomUserJSONRenderer
from .token_generators import generate_rt, generate_jwt
# Create your views here.
class RefreshAPIView(APIView):
"""
Refreshing old access token
"""
permission_classes = (AllowAny,)
@swagger_auto_schema(request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'refresh_token': openapi.Schema(type=openapi.TYPE_STRING, description='refresh_token'),
},
required=['refresh_token']
),
responses={
status.HTTP_200_OK: openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'access_token': openapi.Schema(type=openapi.TYPE_STRING),
'refresh_token': openapi.Schema(type=openapi.TYPE_STRING)
}
),
}
)
def post(self, request):
try:
refresh_token = request.data.get('refresh_token')
old_token = RefreshTokenRepository.get(token=refresh_token)
user = old_token.user
except RefreshToken.DoesNotExist:
return Response({
'error': 'Token is not valid'
}, status=status.HTTP_400_BAD_REQUEST)
if not old_token.used and old_token.expires > datetime.now(tz=timezone(settings.TIME_ZONE)):
token = RefreshToken.objects.create(
token=generate_rt(),
user=user
)
old_token.delete()
data = {
'access_token': generate_jwt(user.pk),
'refresh_token': token.token
}
return Response(data, status=status.HTTP_200_OK)
else:
return Response(
data={
'error': 'Token expired',
},
status=status.HTTP_400_BAD_REQUEST
)
class RegistrationAPIView(APIView):
permission_classes = (AllowAny,)
serializer_class = RegistrationSerializer
renderer_classes = (CustomUserJSONRenderer,)
@swagger_auto_schema(request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'email': openapi.Schema(type=openapi.TYPE_STRING, description='email'),
'password': openapi.Schema(type=openapi.TYPE_STRING, description='user password')
}
),
responses={
status.HTTP_200_OK: openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'email': openapi.Schema(type=openapi.TYPE_STRING),
'access_token': openapi.Schema(type=openapi.TYPE_STRING),
'refresh_token': openapi.Schema(type=openapi.TYPE_STRING)
}
),
}
)
def post(self, request):
user = request.data
serializer = self.serializer_class(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
ProfileRepository.create(user=UserRepository.get(serializer.data['email']))
QRCodeRepository.create(qr_str=encrypt(serializer.data['email']),
user=UserRepository.get(serializer.data['email']))
return Response(serializer.data, status=status.HTTP_201_CREATED)
class LoginAPIView(APIView):
permission_classes = (AllowAny,)
serializer_class = LoginSerializer
renderer_classes = (CustomUserJSONRenderer,)
@swagger_auto_schema(request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'email': openapi.Schema(type=openapi.TYPE_STRING, description='email'),
'password': openapi.Schema(type=openapi.TYPE_STRING, description='user password')
},
),
responses={
status.HTTP_200_OK: openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'email': openapi.Schema(type=openapi.TYPE_STRING),
'access_token': openapi.Schema(type=openapi.TYPE_STRING),
'refresh_token': openapi.Schema(type=openapi.TYPE_STRING)
}
),
}
)
def post(self, request):
user = request.data
serializer = self.serializer_class(data=user)
serializer.is_valid(raise_exception=True)
return Response(serializer.data, status=status.HTTP_200_OK)
class CustomUserRetrieveUpdateAPIView(RetrieveUpdateAPIView):
permission_classes = (IsAuthenticated,)
renderer_classes = (CustomUserJSONRenderer,)
serializer_class = CustomUserSerializer
def retrieve(self, request, *args, **kwargs):
serializer = self.serializer_class(request.user)
return Response(serializer.data, status=status.HTTP_200_OK)
def update(self, request, *args, **kwargs):
serializer_data = request.data
serializer = self.serializer_class(
request.user, data=serializer_data, partial=True
)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
# class ChangePasswordAPIView(APIView):
#
# permission_classes = (IsAuthenticated,)
#
# @swagger_auto_schema(request_body=openapi.Schema(
# type=openapi.TYPE_OBJECT,
# properties={
# 'new_password': openapi.Schema(type=openapi.TYPE_STRING, description='refresh_token'),
# },
# required=['new_password']
# ),
# responses={
# status.HTTP_200_OK: openapi.Schema(
# type=openapi.TYPE_OBJECT,
# properties={
# 'message': 'password changed',
# }
# ),
# status.HTTP_401_UN
# }
# )
# def post(self, request):
# pass
class ProfileRetrieveUpdateDestroyAPIView(CreateAPIView, RetrieveUpdateDestroyAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = ProfileSerializer
queryset = ProfileRepository.all()
def get_queryset(self):
return self.queryset
def get_object(self):
queryset = self.get_queryset()
obj = get_object_or_404(queryset, user=self.request.user)
return obj
def perform_create(self, serializer):
serializer.save(user=self.request.user)
def perform_update(self, serializer):
serializer.save(user=self.request.user)
class ProfileRetrieveAPIView(RetrieveAPIView):
permission_classes = (IsAuthorOrReadOnly,)
serializer_class = ProfileSerializer
queryset = ProfileRepository.all()
class ProfileListAPIView(ListAPIView):
queryset = ProfileRepository.all()
serializer_class = ProfileSerializer
permission_classes = [IsAdminUser]
pagination_class = PageNumberPagination
class QRCodeRetrieveAPIView(RetrieveAPIView):
serializer_class = QRCodeSerializer
# queryset = QRCodeRepository.all()
permission_classes = [IsAuthenticated]
def get_object(self):
return QRCodeRepository.get(self.request.user)