mirror of
https://github.com/Tivix/django-rest-auth.git
synced 2025-10-21 11:14:16 +03:00
Knox includes User details after successful login. This should be replicated when using knox for Login and Registration.
280 lines
9.0 KiB
Python
280 lines
9.0 KiB
Python
from django.contrib.auth import (
|
|
login as django_login,
|
|
logout as django_logout
|
|
)
|
|
from django.conf import settings
|
|
from django.contrib.auth import get_user_model
|
|
from django.core.exceptions import ObjectDoesNotExist
|
|
from django.utils.decorators import method_decorator
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.views.decorators.debug import sensitive_post_parameters
|
|
|
|
from rest_framework import status
|
|
from rest_framework.views import APIView
|
|
from rest_framework.response import Response
|
|
from rest_framework.generics import GenericAPIView, RetrieveUpdateAPIView
|
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
|
|
|
from .app_settings import (
|
|
TokenSerializer, KnoxTokenSerializer, UserDetailsSerializer,
|
|
LoginSerializer, PasswordResetSerializer,
|
|
PasswordResetConfirmSerializer, PasswordChangeSerializer,
|
|
JWTSerializer, create_token
|
|
)
|
|
from .models import TokenModel
|
|
from .utils import jwt_encode
|
|
|
|
if getattr(settings, 'REST_USE_KNOX', False):
|
|
try:
|
|
from knox.auth import TokenAuthentication as KnoxTokenAuthentication
|
|
except ImportError:
|
|
raise ImportError("Install django-rest-knox to use REST_USE_KNOX = True")
|
|
|
|
sensitive_post_parameters_m = method_decorator(
|
|
sensitive_post_parameters(
|
|
'password', 'old_password', 'new_password1', 'new_password2'
|
|
)
|
|
)
|
|
|
|
|
|
class LoginView(GenericAPIView):
|
|
"""
|
|
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.
|
|
"""
|
|
permission_classes = (AllowAny,)
|
|
serializer_class = LoginSerializer
|
|
token_model = TokenModel
|
|
|
|
@sensitive_post_parameters_m
|
|
def dispatch(self, *args, **kwargs):
|
|
return super(LoginView, self).dispatch(*args, **kwargs)
|
|
|
|
def process_login(self):
|
|
django_login(self.request, self.user)
|
|
|
|
def get_response_serializer(self):
|
|
if getattr(settings, 'REST_USE_JWT', False):
|
|
response_serializer = JWTSerializer
|
|
elif getattr(settings, 'REST_USE_KNOX', False):
|
|
response_serializer = KnoxTokenSerializer
|
|
else:
|
|
response_serializer = TokenSerializer
|
|
return response_serializer
|
|
|
|
def login(self):
|
|
self.user = self.serializer.validated_data['user']
|
|
|
|
if getattr(settings, 'REST_USE_JWT', False):
|
|
self.token = jwt_encode(self.user)
|
|
else:
|
|
self.token = create_token(self.token_model, self.user,
|
|
self.serializer)
|
|
|
|
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
|
self.process_login()
|
|
|
|
def get_response(self):
|
|
serializer_class = self.get_response_serializer()
|
|
|
|
if getattr(settings, 'REST_USE_JWT', False):
|
|
data = {
|
|
'user': self.user,
|
|
'token': self.token
|
|
}
|
|
serializer = serializer_class(instance=data,
|
|
context={'request': self.request})
|
|
elif getattr(settings, 'REST_USE_KNOX', False):
|
|
data = {
|
|
'user': self.user,
|
|
'token': self.token
|
|
}
|
|
serializer = serializer_class(instance=data,
|
|
context={'request': self.request})
|
|
else:
|
|
serializer = serializer_class(instance=self.token,
|
|
context={'request': self.request})
|
|
|
|
return Response(serializer.data, status=status.HTTP_200_OK)
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
self.request = request
|
|
self.serializer = self.get_serializer(data=self.request.data)
|
|
self.serializer.is_valid(raise_exception=True)
|
|
|
|
self.login()
|
|
return self.get_response()
|
|
|
|
|
|
class LogoutView(APIView):
|
|
"""
|
|
Calls Django logout method and delete the Token object
|
|
assigned to the current User object.
|
|
|
|
Accepts/Returns nothing.
|
|
"""
|
|
if getattr(settings, 'REST_USE_KNOX', False):
|
|
authentication_classes = (KnoxTokenAuthentication,)
|
|
permission_classes = (IsAuthenticated,)
|
|
else:
|
|
permission_classes = (AllowAny,)
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
if getattr(settings, 'ACCOUNT_LOGOUT_ON_GET', False):
|
|
response = self.logout(request)
|
|
else:
|
|
response = self.http_method_not_allowed(request, *args, **kwargs)
|
|
|
|
return self.finalize_response(request, response, *args, **kwargs)
|
|
|
|
def post(self, request):
|
|
return self.logout(request)
|
|
|
|
def logout(self, request):
|
|
try:
|
|
if getattr(settings, 'REST_USE_KNOX', False):
|
|
request._auth.delete()
|
|
else:
|
|
request.user.auth_token.delete()
|
|
except (AttributeError, ObjectDoesNotExist):
|
|
pass
|
|
|
|
django_logout(request)
|
|
|
|
return Response({"detail": _("Successfully logged out.")},
|
|
status=status.HTTP_200_OK)
|
|
|
|
|
|
class LogoutAllView(APIView):
|
|
"""
|
|
Calls Django logout method and deletes all the Knox tokens
|
|
assigned to the current User object.
|
|
|
|
Accepts/Returns nothing.
|
|
"""
|
|
if getattr(settings, 'REST_USE_KNOX', False):
|
|
authentication_classes = (KnoxTokenAuthentication,)
|
|
permission_classes = (IsAuthenticated,)
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
if getattr(settings, 'ACCOUNT_LOGOUT_ON_GET', False):
|
|
response = self.logout_all(request)
|
|
else:
|
|
response = self.http_method_not_allowed(request, *args, **kwargs)
|
|
|
|
return self.finalize_response(request, response, *args, **kwargs)
|
|
|
|
def post(self, request):
|
|
return self.logout_all(request)
|
|
|
|
def logout_all(self, request):
|
|
try:
|
|
request.user.auth_token_set.all().delete()
|
|
except (AttributeError, ObjectDoesNotExist):
|
|
pass
|
|
|
|
django_logout(request)
|
|
|
|
return Response({"detail": _("Successfully logged out.")},
|
|
status=status.HTTP_200_OK)
|
|
|
|
|
|
class UserDetailsView(RetrieveUpdateAPIView):
|
|
"""
|
|
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
|
|
|
|
Returns UserModel fields.
|
|
"""
|
|
serializer_class = UserDetailsSerializer
|
|
permission_classes = (IsAuthenticated,)
|
|
|
|
def get_object(self):
|
|
return self.request.user
|
|
|
|
def get_queryset(self):
|
|
"""
|
|
Adding this method since it is sometimes called when using
|
|
django-rest-swagger
|
|
https://github.com/Tivix/django-rest-auth/issues/275
|
|
"""
|
|
return get_user_model().objects.none()
|
|
|
|
|
|
class PasswordResetView(GenericAPIView):
|
|
"""
|
|
Calls Django Auth PasswordResetForm save method.
|
|
|
|
Accepts the following POST parameters: email
|
|
Returns the success/fail message.
|
|
"""
|
|
serializer_class = PasswordResetSerializer
|
|
permission_classes = (AllowAny,)
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
# Create a serializer with request.data
|
|
serializer = self.get_serializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
serializer.save()
|
|
# Return the success message with OK HTTP status
|
|
return Response(
|
|
{"detail": _("Password reset e-mail has been sent.")},
|
|
status=status.HTTP_200_OK
|
|
)
|
|
|
|
|
|
class PasswordResetConfirmView(GenericAPIView):
|
|
"""
|
|
Password reset e-mail link is confirmed, therefore
|
|
this resets the user's password.
|
|
|
|
Accepts the following POST parameters: token, uid,
|
|
new_password1, new_password2
|
|
Returns the success/fail message.
|
|
"""
|
|
serializer_class = PasswordResetConfirmSerializer
|
|
permission_classes = (AllowAny,)
|
|
|
|
@sensitive_post_parameters_m
|
|
def dispatch(self, *args, **kwargs):
|
|
return super(PasswordResetConfirmView, self).dispatch(*args, **kwargs)
|
|
|
|
def post(self, request):
|
|
serializer = self.get_serializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
serializer.save()
|
|
return Response(
|
|
{"detail": _("Password has been reset with the new password.")}
|
|
)
|
|
|
|
|
|
class PasswordChangeView(GenericAPIView):
|
|
"""
|
|
Calls Django Auth SetPasswordForm save method.
|
|
|
|
Accepts the following POST parameters: new_password1, new_password2
|
|
Returns the success/fail message.
|
|
"""
|
|
serializer_class = PasswordChangeSerializer
|
|
permission_classes = (IsAuthenticated,)
|
|
|
|
@sensitive_post_parameters_m
|
|
def dispatch(self, *args, **kwargs):
|
|
return super(PasswordChangeView, self).dispatch(*args, **kwargs)
|
|
|
|
def post(self, request):
|
|
serializer = self.get_serializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
serializer.save()
|
|
return Response({"detail": _("New password has been saved.")})
|