Commit 01ea09616ba2c99b9940139176d84e4f701c3675

Authored by Andrew Buss
1 parent 7aa4b42d3e
Exists in master

Don't be silly, you can't log out twice!

Showing 1 changed file with 2 additions and 0 deletions Inline Diff

flashcards/views.py View file @ 01ea096
from flashcards.api import StandardResultsSetPagination 1 1 from flashcards.api import StandardResultsSetPagination
from flashcards.models import Section, User 2 2 from flashcards.models import Section, User
from flashcards.serializers import SectionSerializer, UserUpdateSerializer, RegistrationSerializer, UserSerializer, \ 3 3 from flashcards.serializers import SectionSerializer, UserUpdateSerializer, RegistrationSerializer, UserSerializer, \
PasswordResetSerializer, PasswordResetRequestSerializer, EmailPasswordSerializer 4 4 PasswordResetSerializer, PasswordResetRequestSerializer, EmailPasswordSerializer
5 from rest_framework.permissions import IsAuthenticated
from rest_framework.viewsets import ReadOnlyModelViewSet 5 6 from rest_framework.viewsets import ReadOnlyModelViewSet
from django.core.mail import send_mail 6 7 from django.core.mail import send_mail
from django.contrib.auth import authenticate, login, logout 7 8 from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.tokens import default_token_generator 8 9 from django.contrib.auth.tokens import default_token_generator
from rest_framework.status import HTTP_204_NO_CONTENT, HTTP_401_UNAUTHORIZED, HTTP_201_CREATED 9 10 from rest_framework.status import HTTP_204_NO_CONTENT, HTTP_401_UNAUTHORIZED, HTTP_201_CREATED
from rest_framework.views import APIView 10 11 from rest_framework.views import APIView
from rest_framework.response import Response 11 12 from rest_framework.response import Response
from rest_framework.exceptions import AuthenticationFailed, NotAuthenticated, ValidationError 12 13 from rest_framework.exceptions import AuthenticationFailed, NotAuthenticated, ValidationError
from simple_email_confirmation import EmailAddress 13 14 from simple_email_confirmation import EmailAddress
14 15
15 16
class SectionViewSet(ReadOnlyModelViewSet): 16 17 class SectionViewSet(ReadOnlyModelViewSet):
queryset = Section.objects.all() 17 18 queryset = Section.objects.all()
serializer_class = SectionSerializer 18 19 serializer_class = SectionSerializer
pagination_class = StandardResultsSetPagination 19 20 pagination_class = StandardResultsSetPagination
20 21
21 22
class UserDetail(APIView): 22 23 class UserDetail(APIView):
def patch(self, request, format=None): 23 24 def patch(self, request, format=None):
""" 24 25 """
Updates the user's password, or verifies their email address 25 26 Updates the user's password, or verifies their email address
--- 26 27 ---
request_serializer: UserUpdateSerializer 27 28 request_serializer: UserUpdateSerializer
response_serializer: UserSerializer 28 29 response_serializer: UserSerializer
""" 29 30 """
data = UserUpdateSerializer(data=request.data, context={'user': request.user}) 30 31 data = UserUpdateSerializer(data=request.data, context={'user': request.user})
data.is_valid(raise_exception=True) 31 32 data.is_valid(raise_exception=True)
data = data.validated_data 32 33 data = data.validated_data
33 34
if 'new_password' in data: 34 35 if 'new_password' in data:
if not request.user.check_password(data['old_password']): 35 36 if not request.user.check_password(data['old_password']):
raise ValidationError('old_password is incorrect') 36 37 raise ValidationError('old_password is incorrect')
request.user.set_password(data['new_password']) 37 38 request.user.set_password(data['new_password'])
request.user.save() 38 39 request.user.save()
39 40
if 'confirmation_key' in data: 40 41 if 'confirmation_key' in data:
try: 41 42 try:
request.user.confirm_email(data['confirmation_key']) 42 43 request.user.confirm_email(data['confirmation_key'])
except EmailAddress.DoesNotExist: 43 44 except EmailAddress.DoesNotExist:
raise ValidationError('confirmation_key is invalid') 44 45 raise ValidationError('confirmation_key is invalid')
45 46
return Response(UserSerializer(request.user).data) 46 47 return Response(UserSerializer(request.user).data)
47 48
def get(self, request, format=None): 48 49 def get(self, request, format=None):
""" 49 50 """
Return data about the user 50 51 Return data about the user
--- 51 52 ---
response_serializer: UserSerializer 52 53 response_serializer: UserSerializer
""" 53 54 """
if not request.user.is_active: return Response(status=HTTP_401_UNAUTHORIZED) 54 55 if not request.user.is_active: return Response(status=HTTP_401_UNAUTHORIZED)
serializer = UserSerializer(request.user) 55 56 serializer = UserSerializer(request.user)
return Response(serializer.data) 56 57 return Response(serializer.data)
57 58
def post(self, request, format=None): 58 59 def post(self, request, format=None):
""" 59 60 """
Register a new user 60 61 Register a new user
--- 61 62 ---
request_serializer: EmailPasswordSerializer 62 63 request_serializer: EmailPasswordSerializer
response_serializer: UserSerializer 63 64 response_serializer: UserSerializer
""" 64 65 """
data = RegistrationSerializer(data=request.data) 65 66 data = RegistrationSerializer(data=request.data)
data.is_valid(raise_exception=True) 66 67 data.is_valid(raise_exception=True)
67 68
User.objects.create_user(**data.validated_data) 68 69 User.objects.create_user(**data.validated_data)
user = authenticate(**data.validated_data) 69 70 user = authenticate(**data.validated_data)
login(request, user) 70 71 login(request, user)
71 72
body = ''' 72 73 body = '''
Visit the following link to confirm your email address: 73 74 Visit the following link to confirm your email address:
https://flashy.cards/app/verify_email/%s 74 75 https://flashy.cards/app/verify_email/%s
75 76
If you did not register for Flashy, no action is required. 76 77 If you did not register for Flashy, no action is required.
''' 77 78 '''
78 79
assert send_mail("Flashy email verification", 79 80 assert send_mail("Flashy email verification",
body % user.confirmation_key, 80 81 body % user.confirmation_key,
"noreply@flashy.cards", 81 82 "noreply@flashy.cards",
[user.email]) 82 83 [user.email])
83 84
return Response(UserSerializer(request.user).data, status=HTTP_201_CREATED) 84 85 return Response(UserSerializer(request.user).data, status=HTTP_201_CREATED)
85 86
def delete(self, request): 86 87 def delete(self, request):
""" 87 88 """
Irrevocably delete the user and their data 88 89 Irrevocably delete the user and their data
89 90
Yes, really 90 91 Yes, really
""" 91 92 """
request.user.delete() 92 93 request.user.delete()
return Response(status=HTTP_204_NO_CONTENT) 93 94 return Response(status=HTTP_204_NO_CONTENT)
94 95
95 96
class UserLogin(APIView): 96 97 class UserLogin(APIView):
def post(self, request): 97 98 def post(self, request):
""" 98 99 """
Authenticates user and returns user data if valid. 99 100 Authenticates user and returns user data if valid.
--- 100 101 ---
request_serializer: EmailPasswordSerializer 101 102 request_serializer: EmailPasswordSerializer
response_serializer: UserSerializer 102 103 response_serializer: UserSerializer
""" 103 104 """
104 105
data = EmailPasswordSerializer(data=request.data) 105 106 data = EmailPasswordSerializer(data=request.data)
data.is_valid(raise_exception=True) 106 107 data.is_valid(raise_exception=True)
user = authenticate(**data.validated_data) 107 108 user = authenticate(**data.validated_data)
108 109
if user is None: 109 110 if user is None:
raise AuthenticationFailed('Invalid email or password') 110 111 raise AuthenticationFailed('Invalid email or password')
if not user.is_active: 111 112 if not user.is_active:
raise NotAuthenticated('Account is disabled') 112 113 raise NotAuthenticated('Account is disabled')
login(request, user) 113 114 login(request, user)
return Response(UserSerializer(request.user).data) 114 115 return Response(UserSerializer(request.user).data)
115 116
116 117
class UserLogout(APIView): 117 118 class UserLogout(APIView):
119 permission_classes = (IsAuthenticated,)
def post(self, request, format=None): 118 120 def post(self, request, format=None):
""" 119 121 """
Logs the authenticated user out. 120 122 Logs the authenticated user out.
""" 121 123 """
logout(request) 122 124 logout(request)
return Response(status=HTTP_204_NO_CONTENT) 123 125 return Response(status=HTTP_204_NO_CONTENT)
124 126
125 127
class PasswordReset(APIView): 126 128 class PasswordReset(APIView):
""" 127 129 """
Allows user to reset their password. 128 130 Allows user to reset their password.
""" 129 131 """
130 132
def post(self, request, format=None): 131 133 def post(self, request, format=None):
""" 132 134 """
Send a password reset token/link to the provided email. 133 135 Send a password reset token/link to the provided email.
--- 134 136 ---
request_serializer: PasswordResetRequestSerializer 135 137 request_serializer: PasswordResetRequestSerializer
""" 136 138 """
data = PasswordResetRequestSerializer(data=request.data) 137 139 data = PasswordResetRequestSerializer(data=request.data)
data.is_valid(raise_exception=True) 138 140 data.is_valid(raise_exception=True)
user = User.objects.get(email=data['email'].value) 139 141 user = User.objects.get(email=data['email'].value)
token = default_token_generator.make_token(user) 140 142 token = default_token_generator.make_token(user)
141 143