2014-04-30 23:52:05 +04:00
|
|
|
from django.conf import settings
|
2016-12-21 22:40:18 +03:00
|
|
|
from django.contrib.auth import get_user_model
|
2020-03-01 08:56:21 +03:00
|
|
|
from django.contrib.auth import login as django_login
|
|
|
|
from django.contrib.auth import logout as django_logout
|
2015-11-24 00:52:59 +03:00
|
|
|
from django.core.exceptions import ObjectDoesNotExist
|
2016-12-31 23:55:19 +03:00
|
|
|
from django.utils.decorators import method_decorator
|
2016-02-02 17:29:16 +03:00
|
|
|
from django.utils.translation import ugettext_lazy as _
|
2016-12-31 23:55:19 +03:00
|
|
|
from django.views.decorators.debug import sensitive_post_parameters
|
2014-04-30 23:52:05 +04:00
|
|
|
from rest_framework import status
|
2016-11-01 01:01:06 +03:00
|
|
|
from rest_framework.generics import GenericAPIView, RetrieveUpdateAPIView
|
2020-03-01 08:56:21 +03:00
|
|
|
from rest_framework.permissions import AllowAny, IsAuthenticated
|
|
|
|
from rest_framework.response import Response
|
|
|
|
from rest_framework.views import APIView
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2020-03-01 08:56:21 +03:00
|
|
|
from .app_settings import (JWTSerializer, LoginSerializer,
|
|
|
|
PasswordChangeSerializer,
|
|
|
|
PasswordResetConfirmSerializer,
|
|
|
|
PasswordResetSerializer, TokenSerializer,
|
2020-03-22 13:41:16 +03:00
|
|
|
UserDetailsSerializer, create_token)
|
2016-01-01 00:10:52 +03:00
|
|
|
from .models import TokenModel
|
2016-01-04 20:45:33 +03:00
|
|
|
from .utils import jwt_encode
|
|
|
|
|
2016-12-31 23:55:19 +03:00
|
|
|
sensitive_post_parameters_m = method_decorator(
|
|
|
|
sensitive_post_parameters(
|
|
|
|
'password', 'old_password', 'new_password1', 'new_password2'
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2015-08-07 13:54:45 +03:00
|
|
|
class LoginView(GenericAPIView):
|
2014-04-30 23:52:05 +04:00
|
|
|
"""
|
|
|
|
Check the credentials and return the REST Token
|
|
|
|
if the credentials are valid and authenticated.
|
|
|
|
Calls Django Auth login method to register User ID
|
|
|
|
in Django session framework
|
|
|
|
|
|
|
|
Accept the following POST parameters: username, password
|
|
|
|
Return the REST Framework Token Object's key.
|
|
|
|
"""
|
2014-10-24 17:52:07 +04:00
|
|
|
permission_classes = (AllowAny,)
|
2014-04-30 23:52:05 +04:00
|
|
|
serializer_class = LoginSerializer
|
2016-01-01 00:10:52 +03:00
|
|
|
token_model = TokenModel
|
2016-01-04 20:45:33 +03:00
|
|
|
|
2016-12-31 23:55:19 +03:00
|
|
|
@sensitive_post_parameters_m
|
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
|
return super(LoginView, self).dispatch(*args, **kwargs)
|
|
|
|
|
2016-07-18 08:06:28 +03:00
|
|
|
def process_login(self):
|
|
|
|
django_login(self.request, self.user)
|
|
|
|
|
2016-01-04 20:45:33 +03:00
|
|
|
def get_response_serializer(self):
|
|
|
|
if getattr(settings, 'REST_USE_JWT', False):
|
|
|
|
response_serializer = JWTSerializer
|
|
|
|
else:
|
|
|
|
response_serializer = TokenSerializer
|
|
|
|
return response_serializer
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2014-10-02 13:18:23 +04:00
|
|
|
def login(self):
|
2015-01-09 14:05:14 +03:00
|
|
|
self.user = self.serializer.validated_data['user']
|
2016-03-01 14:51:01 +03:00
|
|
|
|
2016-01-04 20:45:33 +03:00
|
|
|
if getattr(settings, 'REST_USE_JWT', False):
|
2020-03-11 13:01:03 +03:00
|
|
|
self.access_token, self.refresh_token = jwt_encode(self.user)
|
2016-01-04 20:45:33 +03:00
|
|
|
else:
|
2016-12-22 01:08:56 +03:00
|
|
|
self.token = create_token(self.token_model, self.user,
|
|
|
|
self.serializer)
|
2016-02-16 08:42:18 +03:00
|
|
|
|
|
|
|
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
2016-07-18 08:06:28 +03:00
|
|
|
self.process_login()
|
2016-02-16 08:42:18 +03:00
|
|
|
|
2014-10-02 13:18:23 +04:00
|
|
|
def get_response(self):
|
2016-01-04 20:45:33 +03:00
|
|
|
serializer_class = self.get_response_serializer()
|
|
|
|
|
|
|
|
if getattr(settings, 'REST_USE_JWT', False):
|
|
|
|
data = {
|
|
|
|
'user': self.user,
|
2020-03-11 13:01:03 +03:00
|
|
|
'access_token': self.access_token,
|
|
|
|
'refresh_token': self.refresh_token
|
2016-01-04 20:45:33 +03:00
|
|
|
}
|
2016-12-22 01:08:56 +03:00
|
|
|
serializer = serializer_class(instance=data,
|
|
|
|
context={'request': self.request})
|
2016-01-04 20:45:33 +03:00
|
|
|
else:
|
2016-12-22 01:08:56 +03:00
|
|
|
serializer = serializer_class(instance=self.token,
|
|
|
|
context={'request': self.request})
|
2016-01-04 20:45:33 +03:00
|
|
|
|
2017-06-30 13:59:10 +03:00
|
|
|
response = Response(serializer.data, status=status.HTTP_200_OK)
|
2020-03-19 21:37:35 +03:00
|
|
|
if getattr(settings, 'REST_USE_JWT', False):
|
2020-03-22 13:41:16 +03:00
|
|
|
cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None)
|
2020-03-19 21:37:35 +03:00
|
|
|
from rest_framework_simplejwt.settings import api_settings as jwt_settings
|
2020-03-22 13:41:16 +03:00
|
|
|
if cookie_name:
|
2020-03-20 00:09:20 +03:00
|
|
|
from datetime import datetime
|
|
|
|
expiration = (datetime.utcnow() + jwt_settings.ACCESS_TOKEN_LIFETIME)
|
2020-03-22 13:41:16 +03:00
|
|
|
response.set_cookie(
|
|
|
|
cookie_name,
|
|
|
|
self.access_token,
|
|
|
|
expires=expiration,
|
|
|
|
httponly=True
|
|
|
|
)
|
2017-06-30 13:59:10 +03:00
|
|
|
return response
|
2014-10-02 13:18:23 +04:00
|
|
|
|
|
|
|
def post(self, request, *args, **kwargs):
|
2016-07-18 08:06:28 +03:00
|
|
|
self.request = request
|
2017-10-02 22:52:33 +03:00
|
|
|
self.serializer = self.get_serializer(data=self.request.data,
|
|
|
|
context={'request': request})
|
2015-11-23 17:04:56 +03:00
|
|
|
self.serializer.is_valid(raise_exception=True)
|
2016-07-18 08:06:28 +03:00
|
|
|
|
2014-10-02 13:18:23 +04:00
|
|
|
self.login()
|
|
|
|
return self.get_response()
|
2014-04-30 23:52:05 +04:00
|
|
|
|
|
|
|
|
2015-08-07 13:54:45 +03:00
|
|
|
class LogoutView(APIView):
|
2014-04-30 23:52:05 +04:00
|
|
|
"""
|
|
|
|
Calls Django logout method and delete the Token object
|
|
|
|
assigned to the current User object.
|
|
|
|
|
|
|
|
Accepts/Returns nothing.
|
|
|
|
"""
|
2014-11-12 12:33:29 +03:00
|
|
|
permission_classes = (AllowAny,)
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2016-01-09 06:11:35 +03:00
|
|
|
def get(self, request, *args, **kwargs):
|
2016-12-01 04:39:57 +03:00
|
|
|
if getattr(settings, 'ACCOUNT_LOGOUT_ON_GET', False):
|
2016-11-27 14:35:11 +03:00
|
|
|
response = self.logout(request)
|
|
|
|
else:
|
|
|
|
response = self.http_method_not_allowed(request, *args, **kwargs)
|
2016-01-09 06:11:35 +03:00
|
|
|
|
|
|
|
return self.finalize_response(request, response, *args, **kwargs)
|
|
|
|
|
2017-10-25 03:14:12 +03:00
|
|
|
def post(self, request, *args, **kwargs):
|
2016-01-09 06:11:35 +03:00
|
|
|
return self.logout(request)
|
|
|
|
|
|
|
|
def logout(self, request):
|
2014-04-30 23:52:05 +04:00
|
|
|
try:
|
|
|
|
request.user.auth_token.delete()
|
2015-11-24 00:52:59 +03:00
|
|
|
except (AttributeError, ObjectDoesNotExist):
|
2014-04-30 23:52:05 +04:00
|
|
|
pass
|
2019-02-03 06:42:24 +03:00
|
|
|
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
|
|
|
django_logout(request)
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2017-06-30 14:23:56 +03:00
|
|
|
response = Response({"detail": _("Successfully logged out.")},
|
|
|
|
status=status.HTTP_200_OK)
|
2020-03-19 21:37:35 +03:00
|
|
|
if getattr(settings, 'REST_USE_JWT', False):
|
2020-03-22 13:52:26 +03:00
|
|
|
cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None)
|
2020-03-22 13:41:16 +03:00
|
|
|
if cookie_name:
|
|
|
|
response.delete_cookie(cookie_name)
|
2017-06-30 14:23:56 +03:00
|
|
|
return response
|
2014-04-30 23:52:05 +04:00
|
|
|
|
|
|
|
|
2015-08-07 13:54:45 +03:00
|
|
|
class UserDetailsView(RetrieveUpdateAPIView):
|
2014-04-30 23:52:05 +04:00
|
|
|
"""
|
2016-11-01 01:01:06 +03:00
|
|
|
Reads and updates UserModel fields
|
|
|
|
Accepts GET, PUT, PATCH methods.
|
|
|
|
|
|
|
|
Default accepted fields: username, first_name, last_name
|
|
|
|
Default display fields: pk, username, email, first_name, last_name
|
|
|
|
Read-only fields: pk, email
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2016-11-01 01:01:06 +03:00
|
|
|
Returns UserModel fields.
|
2014-04-30 23:52:05 +04:00
|
|
|
"""
|
2014-10-02 13:18:23 +04:00
|
|
|
serializer_class = UserDetailsSerializer
|
2014-10-24 17:52:07 +04:00
|
|
|
permission_classes = (IsAuthenticated,)
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2014-10-02 13:18:23 +04:00
|
|
|
def get_object(self):
|
|
|
|
return self.request.user
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2016-12-21 22:40:18 +03:00
|
|
|
def get_queryset(self):
|
|
|
|
"""
|
|
|
|
Adding this method since it is sometimes called when using
|
|
|
|
django-rest-swagger
|
|
|
|
"""
|
|
|
|
return get_user_model().objects.none()
|
|
|
|
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2015-08-07 13:54:45 +03:00
|
|
|
class PasswordResetView(GenericAPIView):
|
2014-04-30 23:52:05 +04:00
|
|
|
"""
|
|
|
|
Calls Django Auth PasswordResetForm save method.
|
|
|
|
|
|
|
|
Accepts the following POST parameters: email
|
|
|
|
Returns the success/fail message.
|
|
|
|
"""
|
|
|
|
serializer_class = PasswordResetSerializer
|
2014-10-24 17:52:07 +04:00
|
|
|
permission_classes = (AllowAny,)
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2014-10-07 17:08:08 +04:00
|
|
|
def post(self, request, *args, **kwargs):
|
2015-08-07 14:31:33 +03:00
|
|
|
# Create a serializer with request.data
|
|
|
|
serializer = self.get_serializer(data=request.data)
|
2015-11-23 17:04:56 +03:00
|
|
|
serializer.is_valid(raise_exception=True)
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2014-10-07 17:08:08 +04:00
|
|
|
serializer.save()
|
|
|
|
# Return the success message with OK HTTP status
|
2015-04-28 11:22:08 +03:00
|
|
|
return Response(
|
2016-03-31 11:58:14 +03:00
|
|
|
{"detail": _("Password reset e-mail has been sent.")},
|
2015-04-28 11:22:08 +03:00
|
|
|
status=status.HTTP_200_OK
|
|
|
|
)
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2014-05-01 00:55:04 +04:00
|
|
|
|
2015-08-07 13:54:45 +03:00
|
|
|
class PasswordResetConfirmView(GenericAPIView):
|
2014-04-30 23:52:05 +04:00
|
|
|
"""
|
2016-12-08 03:12:01 +03:00
|
|
|
Password reset e-mail link is confirmed, therefore
|
|
|
|
this resets the user's password.
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2016-12-08 03:12:01 +03:00
|
|
|
Accepts the following POST parameters: token, uid,
|
|
|
|
new_password1, new_password2
|
2014-04-30 23:52:05 +04:00
|
|
|
Returns the success/fail message.
|
|
|
|
"""
|
2014-10-07 17:08:08 +04:00
|
|
|
serializer_class = PasswordResetConfirmSerializer
|
2014-10-24 17:52:07 +04:00
|
|
|
permission_classes = (AllowAny,)
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2016-12-31 23:55:19 +03:00
|
|
|
@sensitive_post_parameters_m
|
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
|
return super(PasswordResetConfirmView, self).dispatch(*args, **kwargs)
|
|
|
|
|
2017-10-25 03:14:12 +03:00
|
|
|
def post(self, request, *args, **kwargs):
|
2015-08-07 14:31:33 +03:00
|
|
|
serializer = self.get_serializer(data=request.data)
|
2015-11-23 17:04:56 +03:00
|
|
|
serializer.is_valid(raise_exception=True)
|
2014-10-07 17:08:08 +04:00
|
|
|
serializer.save()
|
2016-12-22 01:08:56 +03:00
|
|
|
return Response(
|
|
|
|
{"detail": _("Password has been reset with the new password.")}
|
|
|
|
)
|
2014-04-30 23:52:05 +04:00
|
|
|
|
|
|
|
|
2015-08-07 13:54:45 +03:00
|
|
|
class PasswordChangeView(GenericAPIView):
|
2014-04-30 23:52:05 +04:00
|
|
|
"""
|
|
|
|
Calls Django Auth SetPasswordForm save method.
|
|
|
|
|
|
|
|
Accepts the following POST parameters: new_password1, new_password2
|
|
|
|
Returns the success/fail message.
|
|
|
|
"""
|
2014-10-07 17:08:08 +04:00
|
|
|
serializer_class = PasswordChangeSerializer
|
2014-10-24 17:52:07 +04:00
|
|
|
permission_classes = (IsAuthenticated,)
|
2014-04-30 23:52:05 +04:00
|
|
|
|
2016-12-31 23:55:19 +03:00
|
|
|
@sensitive_post_parameters_m
|
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
|
return super(PasswordChangeView, self).dispatch(*args, **kwargs)
|
|
|
|
|
2017-10-25 03:14:12 +03:00
|
|
|
def post(self, request, *args, **kwargs):
|
2015-08-07 14:31:33 +03:00
|
|
|
serializer = self.get_serializer(data=request.data)
|
2015-11-23 17:04:56 +03:00
|
|
|
serializer.is_valid(raise_exception=True)
|
2014-10-07 17:08:08 +04:00
|
|
|
serializer.save()
|
2016-03-31 11:58:14 +03:00
|
|
|
return Response({"detail": _("New password has been saved.")})
|