From 52f5582c513e41f069f60b5e45b457dc17413166 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 14 Jan 2025 15:29:45 +0100 Subject: [PATCH] new login api --- src/api/models.py | 7 +++- src/api/serializers.py | 14 ++++++- src/api/urls.py | 6 ++- src/api/views.py | 93 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 3 deletions(-) diff --git a/src/api/models.py b/src/api/models.py index ff1f09a0d..4f0556561 100644 --- a/src/api/models.py +++ b/src/api/models.py @@ -101,7 +101,12 @@ class Consumer(models.Model): class Token(models.Model): REQUEST = 1 ACCESS = 2 - TOKEN_TYPES = ((REQUEST, 'Request'), (ACCESS, 'Access')) + REFRESH = 3 + TOKEN_TYPES = ( + (REQUEST, 'Request'), + (ACCESS, 'Access'), + (REFRESH, 'Refresh') + ) key = models.CharField(max_length=KEY_SIZE) secret = models.CharField(max_length=SECRET_SIZE) diff --git a/src/api/serializers.py b/src/api/serializers.py index dae587c84..4ba660e26 100644 --- a/src/api/serializers.py +++ b/src/api/serializers.py @@ -15,10 +15,11 @@ class PlainSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer): premium = UserPremiumField() + confirmed = serializers.BooleanField(source='is_active') class Meta: model = User - fields = ['username', 'premium'] + fields = ['username', 'premium', 'confirmed'] class BookUserDataSerializer(serializers.ModelSerializer): @@ -30,3 +31,14 @@ class BookUserDataSerializer(serializers.ModelSerializer): class LoginSerializer(serializers.Serializer): username = serializers.CharField() password = serializers.CharField(style={'input_type': 'password'}) + + + +class RegisterSerializer(serializers.Serializer): + email = serializers.CharField() + password = serializers.CharField(style={'input_type': 'password'}) + options = serializers.ListField(child=serializers.IntegerField()) + + +class RefreshTokenSerializer(serializers.Serializer): + refresh_token = serializers.CharField(style={'input_type': 'password'}) diff --git a/src/api/urls.py b/src/api/urls.py index b0ee94def..de3dba77f 100644 --- a/src/api/urls.py +++ b/src/api/urls.py @@ -10,7 +10,11 @@ from . import views urlpatterns1 = [ - path('login/', csrf_exempt(views.LoginView.as_view())), + path('register/', csrf_exempt(views.RegisterView.as_view())), + path('refreshToken/', csrf_exempt(views.RefreshTokenView.as_view())), + path('requestConfirm/', csrf_exempt(views.RequestConfirmView.as_view())), + path('login/', csrf_exempt(views.Login2View.as_view())), + path('me/', views.UserView.as_view()), path('', include('catalogue.api.urls2')), ] diff --git a/src/api/views.py b/src/api/views.py index 622332f2f..08d1650e7 100644 --- a/src/api/views.py +++ b/src/api/views.py @@ -154,6 +154,38 @@ class LoginView(GenericAPIView): return Response({"access_token": key}) +class Login2View(GenericAPIView): + serializer_class = serializers.LoginSerializer + + def post(self, request): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + d = serializer.validated_data + user = authenticate(username=d['username'], password=d['password']) + if user is None: + return Response({"detail": "Invalid credentials."}) + + access_token = generate_token()[:KEY_SIZE] + Token.objects.create( + key=access_token, + token_type=Token.ACCESS, + timestamp=time(), + user=user, + ) + refresh_token = generate_token()[:KEY_SIZE] + Token.objects.create( + key=refresh_token, + token_type=Token.REFRESH, + timestamp=time(), + user=user, + ) + return Response({ + "access_token": access_token, + "refresh_token": refresh_token, + "expires": 3600, + }) + + @vary_on_auth class UserView(RetrieveAPIView): permission_classes = [IsAuthenticated] @@ -192,3 +224,64 @@ class BookUserDataView(RetrieveAPIView): class BlogView(APIView): def get(self, request): return Response([]) + + + +class RegisterView(APIView): + serializer_class = serializers.RegisterSerializer + + def get(self, request): + return Response({ + "options": [ + { + "id": 1, + "html": "Chcę otrzymywać newsletter Wolnych Lektur", + "required": False + } + ], + "info": [ + 'Administratorem danych osobowych jest Fundacja Wolne Lektury (ul. Marszałkowska 84/92 lok. 125, 00-514 Warszawa). Podanie danych osobowych jest dobrowolne. Dane są przetwarzane w zakresie niezbędnym do prowadzenia serwisu, a także w celach prowadzenia statystyk, ewaluacji i sprawozdawczości. W przypadku wyrażenia dodatkowej zgody adres e-mail zostanie wykorzystany także w celu przesyłania newslettera Wolnych Lektur. Osobom, których dane są zbierane, przysługuje prawo dostępu do treści swoich danych oraz ich poprawiania. Więcej informacji w polityce prywatności.' + ] + }) + + def post(self, request): + pass + + +class RefreshTokenView(APIView): + serializer_class = serializers.RefreshTokenSerializer + + def post(self, request): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + d = serializer.validated_data + + t = Token.objects.get( + key=d['refresh_token'], + token_type=Token.REFRESH + ) + user = t.user + + access_token = generate_token()[:KEY_SIZE] + Token.objects.create( + key=access_token, + token_type=Token.ACCESS, + timestamp=time(), + user=user, + ) + refresh_token = generate_token()[:KEY_SIZE] + Token.objects.create( + key=refresh_token, + token_type=Token.REFRESH, + timestamp=time(), + user=user, + ) + return Response({ + "access_token": access_token, + "refresh_token": refresh_token, + "expires": 3600, + }) + + +class RequestConfirmView(APIView): + pass -- 2.20.1