11# views.py
22from typing import Literal
33
4+ from django .contrib .auth .mixins import UserPassesTestMixin
5+ from django .contrib .auth .models import update_last_login
46from rest_framework import status
57from rest_framework .exceptions import AuthenticationFailed
6- from rest_framework .permissions import IsAuthenticated
8+ from rest_framework .generics import RetrieveUpdateDestroyAPIView
9+ from rest_framework .permissions import IsAuthenticated , AllowAny
710from rest_framework .views import APIView
811from rest_framework_simplejwt .serializers import TokenObtainPairSerializer
912from rest_framework_simplejwt .views import TokenObtainPairView , TokenRefreshView
1013from rest_framework_simplejwt .tokens import RefreshToken
1114from rest_framework .response import Response
1215from django .conf import settings
1316
17+ from izpitnik .accounts .api .permissions import IsOwnerPermission , add_or_change_permission_decorator , \
18+ delete_permission_decorator
19+ from izpitnik .accounts .mixins import GenerateTokenMixin
20+ from izpitnik .accounts .serializers import CustomTokenObtainPairSerializer , UserProfileSerializer
21+ from izpitnik .articles .api .permissions import IsAuthorOnAllMethodsPermission
1422from izpitnik .settings import ENV
1523
1624
17- class CustomTokenObtainPairSerializer (TokenObtainPairSerializer ):
1825
19- @classmethod
20- def get_token (cls , user ):
21- token = super ().get_token (user )
22-
23- token ['is_admin' ] = user .is_staff
24- token ['roles' ] = [role .name for role in user .groups .all ()]
25- token ['is_superuser' ] = user .is_superuser
26-
27- return token
2826
2927class CustomTokenObtainPairView (TokenObtainPairView ):
3028
@@ -33,25 +31,7 @@ class CustomTokenObtainPairView(TokenObtainPairView):
3331 def post (self , request , * args , ** kwargs ):
3432 response = super ().post (request , * args , ** kwargs )
3533 refresh = response .data .pop ('refresh' , None )
36-
37- secure = False
38- samesite = False
39-
40- if ENV == "production" :
41- secure = True
42- samesite = 'Strict'
43-
44- if refresh :
45- response .set_cookie (
46- key = 'refresh_token' ,
47- value = refresh ,
48- httponly = True ,
49- secure = secure ,
50- samesite = samesite ,
51- max_age = 7 * 24 * 60 * 60 , # 7 days
52- path = '/api/token' ,
53- domain = request .build_absolute_uri ('/' )[:- 1 ].replace ("http://" ,"" ).replace ("https://" ,"" ).split (":" )[0 ]
54- )
34+ response = GenerateTokenMixin (response = response , refresh = refresh ).issue_token (request )
5535 return response
5636
5737# views.py
@@ -77,28 +57,72 @@ class ApiLogoutView(APIView):
7757
7858 def post (self , request ):
7959
80- secure = False
81- samesite = False
82-
83- if ENV == "production" :
84- secure = True
85- samesite = "Strict"
86-
8760 try :
88- print (request .COOKIES .get ("refresh_token" ))
8961 refresh_token = request .COOKIES .get ("refresh_token" )
9062 token = RefreshToken (refresh_token )
9163 token .blacklist ()
9264 except Exception as e :
9365 return Response ({"error" : str (e )}, status = 400 )
9466
95- response = Response ({"detail" : "Logout successful." }, status = 200 )
96- response .delete_cookie (
97- key = 'refresh_token' ,
98- samesite = samesite ,
99- path = '/api/token' ,
100- domain = request .build_absolute_uri ('/' )[:- 1 ].replace ("http://" , "" ).replace ("https://" , "" ).split (":" )[0 ]
101- )
67+ return GenerateTokenMixin ().unset_cookie (request )
68+
69+ class ApiSignUpVew (UserPassesTestMixin ,APIView ):
70+
71+ permission_classes = [AllowAny ]
72+
73+ def test_func (self ):
74+ return not self .request .user .is_authenticated
75+
76+ def post (self , request ):
77+
78+ from izpitnik .accounts .forms import MainUserCreationForm
79+
80+ data = request .data
81+
82+ form = MainUserCreationForm (data )
83+
84+ if form .is_valid ():
85+ user = form .save ()
86+ token = CustomTokenObtainPairSerializer .get_token (user )
87+ return GenerateTokenMixin (refresh = str (token ), access = str (token .access_token )).issue_token (request )
88+
89+ else :
90+ return Response (form .errors , status = 400 )
91+
92+ class GetUpdateDeleteProfileAPIView (RetrieveUpdateDestroyAPIView ):
93+ permission_classes = [IsOwnerPermission ]
94+ lookup_url_kwarg = "user_id"
95+ serializer_class = UserProfileSerializer
96+
97+ def get_queryset (self ):
98+ from izpitnik .accounts .models import User
99+ user_id = self .rectify_kwarg (self .request , self .kwargs ).get (self .lookup_url_kwarg )
100+ return User .objects .filter (pk = user_id ).prefetch_related ("profile" )
101+
102+ def get (self , request , * args , ** kwargs ):
103+ kwargs = self .rectify_kwarg (request , kwargs )
104+ response = super ().get (request ,* args , ** kwargs )
102105 return response
103106
107+ def rectify_kwarg (self , request , kwargs ):
108+ user_id = kwargs .get (self .lookup_url_kwarg )
109+ if user_id == 'my' :
110+ kwargs [self .lookup_url_kwarg ] = str (request .user .pk )
111+ return kwargs
112+
113+
114+ @add_or_change_permission_decorator
115+ def put (self , request , * args , ** kwargs ):
116+ kwargs = self .rectify_kwarg (request , kwargs )
117+ return super ().put (request , * args , ** kwargs )
118+
119+ @add_or_change_permission_decorator
120+ def patch (self , request , * args , ** kwargs ):
121+ kwargs = self .rectify_kwarg (request , kwargs )
122+ return super ().patch (request , * args , ** kwargs )
123+
124+ @delete_permission_decorator
125+ def delete (self , request , * args , ** kwargs ):
126+ kwargs = self .rectify_kwarg (request , kwargs )
127+ return super ().delete (request , * args , ** kwargs )
104128
0 commit comments