Commit 05ddc98b926f0da0fdf85c4b43c68650b46ebeaf

Authored by Andrew Buss
1 parent eb304424c4
Exists in master

Return user object on PATCH of user detail view

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

flashcards/api.py View file @ 05ddc98
from django.core.mail import send_mail 1 1 from django.core.mail import send_mail
from django.contrib.auth import authenticate, login, logout 2 2 from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.tokens import default_token_generator 3 3 from django.contrib.auth.tokens import default_token_generator
from rest_framework.permissions import BasePermission 4 4 from rest_framework.permissions import BasePermission
from rest_framework.status import HTTP_201_CREATED, HTTP_204_NO_CONTENT, HTTP_401_UNAUTHORIZED 5 5 from rest_framework.status import HTTP_201_CREATED, HTTP_204_NO_CONTENT, HTTP_401_UNAUTHORIZED
from rest_framework.views import APIView 6 6 from rest_framework.views import APIView
from rest_framework.response import Response 7 7 from rest_framework.response import Response
from rest_framework.exceptions import ValidationError, NotFound 8 8 from rest_framework.exceptions import ValidationError, NotFound
from flashcards.serializers import * 9 9 from flashcards.serializers import *
10 10
11 11
class UserDetailPermissions(BasePermission): 12 12 class UserDetailPermissions(BasePermission):
def has_object_permission(self, request, view, obj): 13 13 def has_object_permission(self, request, view, obj):
if request.method == 'POST': 14 14 if request.method == 'POST':
return True 15 15 return True
return request.user.is_active 16 16 return request.user.is_active
17 17
18 18
class UserDetail(APIView): 19 19 class UserDetail(APIView):
def patch(self, request, format=None): 20 20 def patch(self, request, format=None):
""" 21 21 """
This method checks either the email or the password passed in 22 22 This method checks either the email or the password passed in
is valid. If confirmation key is correct, it validates the 23 23 is valid. If confirmation key is correct, it validates the
user. It updates the password if the new password 24 24 user. It updates the password if the new password
is valid. 25 25 is valid.
26 26
""" 27 27 """
currentuser = request.user 28 28 currentuser = request.user
29 29
if 'confirmation_key' in request.data: 30 30 if 'confirmation_key' in request.data:
if not currentuser.confirm_email(request.data['confirmation_key']): 31 31 if not currentuser.confirm_email(request.data['confirmation_key']):
raise ValidationError('confirmation_key is invalid') 32 32 raise ValidationError('confirmation_key is invalid')
33 33
if 'new_password' in request.data: 34 34 if 'new_password' in request.data:
if not currentuser.check_password(request.data['old_password']): 35 35 if not currentuser.check_password(request.data['old_password']):
raise ValidationError('Invalid old password') 36 36 raise ValidationError('Invalid old password')
if not request.data['new_password']: 37 37 if not request.data['new_password']:
raise ValidationError('Password cannot be blank') 38 38 raise ValidationError('Password cannot be blank')
currentuser.set_password(request.data['new_password']) 39 39 currentuser.set_password(request.data['new_password'])
currentuser.save() 40 40 currentuser.save()
41 41
return Response(status=HTTP_204_NO_CONTENT) 42 42 return Response(UserSerializer(request.user).data)
43 43
def get(self, request, format=None): 44 44 def get(self, request, format=None):
if not request.user.is_active: return Response(status=HTTP_401_UNAUTHORIZED) 45 45 if not request.user.is_active: return Response(status=HTTP_401_UNAUTHORIZED)
serializer = UserSerializer(request.user) 46 46 serializer = UserSerializer(request.user)
return Response(serializer.data) 47 47 return Response(serializer.data)
48 48
def post(self, request, format=None): 49 49 def post(self, request, format=None):
if 'email' not in request.data: 50 50 if 'email' not in request.data:
raise ValidationError('Email is required') 51 51 raise ValidationError('Email is required')
if 'password' not in request.data: 52 52 if 'password' not in request.data:
raise ValidationError('Password is required') 53 53 raise ValidationError('Password is required')
email = request.data['email'] 54 54 email = request.data['email']
existing_users = User.objects.filter(email=email) 55 55 existing_users = User.objects.filter(email=email)
if existing_users.exists(): 56 56 if existing_users.exists():
raise ValidationError("An account with this email already exists") 57 57 raise ValidationError("An account with this email already exists")
user = User.objects.create_user(email, email=email, password=request.data['password']) 58 58 user = User.objects.create_user(email, email=email, password=request.data['password'])
59 59
body = ''' 60 60 body = '''
Visit the following link to confirm your email address: 61 61 Visit the following link to confirm your email address:
http://flashy.cards/app/verify_email/%s 62 62 http://flashy.cards/app/verify_email/%s
63 63
If you did not register for Flashy, no action is required. 64 64 If you did not register for Flashy, no action is required.
''' 65 65 '''
send_mail("Flashy email verification", 66 66 send_mail("Flashy email verification",
body % user.confirmation_key, 67 67 body % user.confirmation_key,
"noreply@flashy.cards", 68 68 "noreply@flashy.cards",
[user.email]) 69 69 [user.email])
70 70
user = authenticate(email=email, password=request.data['password']) 71 71 user = authenticate(email=email, password=request.data['password'])
login(request, user) 72 72 login(request, user)
return Response(UserSerializer(user).data, status=HTTP_201_CREATED) 73 73 return Response(UserSerializer(user).data, status=HTTP_201_CREATED)
74 74
def delete(self, request): 75 75 def delete(self, request):
request.user.delete() 76 76 request.user.delete()
return Response(status=HTTP_204_NO_CONTENT) 77 77 return Response(status=HTTP_204_NO_CONTENT)
78 78
79 79
class UserLogin(APIView): 80 80 class UserLogin(APIView):
""" 81 81 """
Authenticates user and returns user data if valid. Handles invalid 82 82 Authenticates user and returns user data if valid. Handles invalid
users. 83 83 users.
""" 84 84 """
85 85
def post(self, request, format=None): 86 86 def post(self, request, format=None):
""" 87 87 """
Authenticates and logs in the user and returns their data if valid. 88 88 Authenticates and logs in the user and returns their data if valid.
""" 89 89 """
if 'email' not in request.data: 90 90 if 'email' not in request.data:
raise ValidationError('Email is required') 91 91 raise ValidationError('Email is required')
if 'password' not in request.data: 92 92 if 'password' not in request.data:
raise ValidationError('Password is required') 93 93 raise ValidationError('Password is required')
94 94
email = request.data['email'] 95 95 email = request.data['email']
password = request.data['password'] 96 96 password = request.data['password']
user = authenticate(email=email, password=password) 97 97 user = authenticate(email=email, password=password)
98 98
if user is None: 99 99 if user is None:
raise ValidationError('Invalid email or password') 100 100 raise ValidationError('Invalid email or password')
if not user.is_active: 101 101 if not user.is_active:
raise ValidationError('Account is disabled') 102 102 raise ValidationError('Account is disabled')
login(request, user) 103 103 login(request, user)
return Response(UserSerializer(user).data) 104 104 return Response(UserSerializer(user).data)
105 105
106 106
class UserLogout(APIView): 107 107 class UserLogout(APIView):
""" 108 108 """
Authenticated user log out. 109 109 Authenticated user log out.
""" 110 110 """
111 111
def post(self, request, format=None): 112 112 def post(self, request, format=None):
""" 113 113 """
Logs the authenticated user out. 114 114 Logs the authenticated user out.
""" 115 115 """
logout(request) 116 116 logout(request)
return Response(status=HTTP_204_NO_CONTENT) 117 117 return Response(status=HTTP_204_NO_CONTENT)
118 118
119 119
class PasswordReset(APIView): 120 120 class PasswordReset(APIView):
""" 121 121 """
Allows user to reset their password. 122 122 Allows user to reset their password.
System sends an email to the user's email with a token that may be verified 123 123 System sends an email to the user's email with a token that may be verified
to reset their password. 124 124 to reset their password.
""" 125 125 """
126 126
def post(self, request, format=None): 127 127 def post(self, request, format=None):
""" 128 128 """
Send a password reset token/link to the provided email. 129 129 Send a password reset token/link to the provided email.
""" 130 130 """
if 'email' not in request.data: 131 131 if 'email' not in request.data:
raise ValidationError('Email is required') 132 132 raise ValidationError('Email is required')
133 133
email = request.data['email'] 134 134 email = request.data['email']
135 135
# Find the user since they are not logged in. 136 136 # Find the user since they are not logged in.
try: 137 137 try:
user = User.objects.get(email=email) 138 138 user = User.objects.get(email=email)
except User.DoesNotExist: 139 139 except User.DoesNotExist:
# Don't leak that email does not exist. 140 140 # Don't leak that email does not exist.