Skip to content

Commit 4aad656

Browse files
authored
Merge pull request #27 from PROCOLLAB-github/feature/auth
Feature/auth
2 parents 973bea0 + 39f25cb commit 4aad656

2 files changed

Lines changed: 60 additions & 34 deletions

File tree

users/urls.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
from django.urls import path, re_path
22

33
from users.views import (
4+
CurrentUser,
45
EmailResetPassword,
56
ResetPassword,
67
SpecialistsList,
7-
UserAdditionalRolesView,
8+
UserAdditionalRoles,
89
UserDetail,
910
UserList,
10-
UserTypesView,
11-
VerifyEmail,
1211
UserTypes,
12+
VerifyEmail,
1313
)
1414

1515
app_name = "users"
@@ -19,11 +19,11 @@
1919
"specialists/", SpecialistsList.as_view()
2020
), # this url actually returns mentors, experts and investors
2121
path("users/", UserList.as_view()),
22-
path("users/roles/", UserAdditionalRolesView.as_view()),
23-
path("users/types/", UserTypesView.as_view()),
22+
path("users/roles/", UserAdditionalRoles.as_view()),
23+
path("users/types/", UserTypes.as_view()),
2424
path("users/<int:pk>/", UserDetail.as_view()),
2525
path("users/reset-password/", EmailResetPassword.as_view()),
26-
path("users/user-types", UserTypes.as_view()),
26+
path("users/current/", CurrentUser.as_view()),
2727
re_path(
2828
r"^account-confirm-email/",
2929
VerifyEmail.as_view(),

users/views.py

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
from rest_framework.permissions import AllowAny, IsAuthenticated
2020
from rest_framework.response import Response
2121
from rest_framework.views import APIView
22-
from rest_framework_simplejwt.tokens import RefreshToken
22+
from rest_framework_simplejwt.tokens import RefreshToken, TokenError
2323

2424
from core.permissions import IsOwnerOrReadOnly
2525
from core.utils import Email
26-
from users.helpers import VERBOSE_ROLE_TYPES, VERBOSE_USER_TYPES
26+
from users.helpers import VERBOSE_ROLE_TYPES
2727
from users.serializers import (
2828
EmailSerializer,
2929
PasswordSerializer,
@@ -73,17 +73,7 @@ def post(self, request, *args, **kwargs):
7373
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
7474

7575

76-
class UserTypesView(GenericAPIView):
77-
permission_classes = [AllowAny]
78-
79-
def get(self, request, format=None):
80-
"""
81-
Return a tuple of user types.
82-
"""
83-
return Response(VERBOSE_USER_TYPES, status=status.HTTP_200_OK)
84-
85-
86-
class UserAdditionalRolesView(GenericAPIView):
76+
class UserAdditionalRoles(GenericAPIView):
8777
permission_classes = [AllowAny]
8878

8979
def get(self, request, format=None):
@@ -111,6 +101,17 @@ class UserDetail(RetrieveUpdateDestroyAPIView):
111101
serializer_class = UserDetailSerializer
112102

113103

104+
class CurrentUser(APIView):
105+
queryset = User.objects.get_users_for_detail_view()
106+
permission_classes = [IsAuthenticated]
107+
serializer_class = UserDetailSerializer
108+
109+
def get(self, request):
110+
user = request.user
111+
serializer = UserDetailSerializer(user)
112+
return Response(serializer.data, status=status.HTTP_200_OK)
113+
114+
114115
class UserTypes(APIView):
115116
def get(self, request, format=None):
116117
"""
@@ -145,13 +146,13 @@ def get(self, request):
145146
except jwt.ExpiredSignatureError:
146147
return redirect(
147148
REDIRECT_URL,
148-
status=status.HTTP_200_OK,
149+
status=status.HTTP_400_BAD_REQUEST,
149150
message="Activate Expired",
150151
)
151152
except jwt.DecodeError:
152153
return redirect(
153154
REDIRECT_URL,
154-
status=status.HTTP_200_OK,
155+
status=status.HTTP_400_BAD_REQUEST,
155156
message="Decode error",
156157
)
157158

@@ -166,20 +167,26 @@ def post(self, request, *args, **kwargs):
166167

167168
user = User.objects.get(email=serializer.data["email"])
168169

169-
token = RefreshToken.for_user(user).access_token
170+
access_token = RefreshToken.for_user(user).access_token
171+
refresh_token = RefreshToken.for_user(user)
170172

171173
relative_link = reverse("users:password_reset_sent")
172174

173175
current_site = get_current_site(request).domain
174-
absolute_url = "http://" + current_site + relative_link + "?token=" + str(token)
176+
absolute_url = (
177+
"http://"
178+
+ current_site
179+
+ relative_link
180+
+ f"?access_token={access_token}&refresh_token={refresh_token}"
181+
)
175182

176-
email_body = "Hi, {} {}! Use link below verify your email {}".format(
183+
email_body = "Hi, {} {}! Use link below for reset password {}".format(
177184
user.first_name, user.last_name, absolute_url
178185
)
179186

180187
data = {
181188
"email_body": email_body,
182-
"email_subject": "Verify your email",
189+
"email_subject": "Reset password",
183190
"to_email": user.email,
184191
}
185192

@@ -192,24 +199,43 @@ class ResetPassword(UpdateAPIView):
192199
serializer_class = PasswordSerializer
193200
permission_classes = [AllowAny]
194201

202+
def get(self, request, *args, **kwargs):
203+
refresh_token = request.GET.get("refresh_token")
204+
try:
205+
RefreshToken(refresh_token).check_blacklist()
206+
except TokenError:
207+
return redirect(
208+
"https://procollab.ru/auth/reset_password/",
209+
status=status.HTTP_400_BAD_REQUEST,
210+
message="Used token",
211+
)
212+
213+
return Response({"message": "Enter new password"})
214+
195215
def update(self, request, *args, **kwargs):
196216
serializer = self.get_serializer(data=request.data)
197217
serializer.is_valid()
198218

199219
try:
200-
token = request.GET.get("token")
201-
payload = jwt.decode(jwt=token, key=settings.SECRET_KEY, algorithms=["HS256"])
220+
refresh_token = request.GET.get("refresh_token")
221+
access_token = request.GET.get("access_token")
222+
payload = jwt.decode(
223+
jwt=access_token, key=settings.SECRET_KEY, algorithms=["HS256"]
224+
)
202225
user = User.objects.get(id=payload["user_id"])
203-
last_update = user.datatime_updated
204-
if (datetime.now().minute - last_update.minute) <= 10:
205-
return Response(
206-
{"response": "You can't change your password so often"},
207-
status=status.HTTP_200_OK,
226+
last_update = user.datetime_updated
227+
frequency_update = datetime.utcnow().minute - last_update.minute
228+
if frequency_update <= 10:
229+
return redirect(
230+
"https://procollab.ru/auth/reset_password/",
231+
status=status.HTTP_400_BAD_REQUEST,
232+
message="You can't change your password so often",
208233
)
209234

210235
user.set_password(serializer.data["new_password"])
211236
user.save()
212237

238+
RefreshToken(refresh_token).blacklist()
213239
return redirect(
214240
"https://procollab.ru/auth/reset_password/",
215241
status=status.HTTP_200_OK,
@@ -219,12 +245,12 @@ def update(self, request, *args, **kwargs):
219245
except jwt.ExpiredSignatureError:
220246
return redirect(
221247
"https://procollab.ru/auth/reset_password/",
222-
status=status.HTTP_200_OK,
248+
status=status.HTTP_400_BAD_REQUEST,
223249
message="Activate Expired",
224250
)
225251
except jwt.DecodeError:
226252
return redirect(
227253
"https://procollab.ru/auth/reset_password/",
228-
status=status.HTTP_200_OK,
254+
status=status.HTTP_400_BAD_REQUEST,
229255
message="Decode error",
230256
)

0 commit comments

Comments
 (0)