Commit 25cc754dea73a51d30ff6415dde4f47500d8c298

Authored by Rachel Lee
1 parent 15af7095ef
Exists in master

api/reset_password post and patch added, not done

Showing 2 changed files with 55 additions and 1 deletions Inline Diff

flashcards/api.py View file @ 25cc754
from django.core.mail import send_mail 1 1 from django.core.mail import send_mail
from django.contrib.auth import authenticate, login 2 2 from django.contrib.auth import authenticate, login
3 from django.contrib.auth.tokens import default_token_generator
from rest_framework.views import APIView 3 4 from rest_framework.views import APIView
from rest_framework.response import Response 4 5 from rest_framework.response import Response
from rest_framework import status 5 6 from rest_framework import status
from rest_framework.exceptions import ValidationError 6 7 from rest_framework.exceptions import ValidationError, NotFound
from flashcards.serializers import * 7 8 from flashcards.serializers import *
8 9
9 10
class UserDetail(APIView): 10 11 class UserDetail(APIView):
def patch(self, request, format=None): 11 12 def patch(self, request, format=None):
""" 12 13 """
Updates a user's password after they enter a valid old password. 13 14 Updates a user's password after they enter a valid old password.
TODO: email verification 14 15 TODO: email verification
""" 15 16 """
16 17
if 'old_password' not in request.data: 17 18 if 'old_password' not in request.data:
raise ValidationError('Old password is required') 18 19 raise ValidationError('Old password is required')
if 'new_password' not in request.data: 19 20 if 'new_password' not in request.data:
raise ValidationError('New password is required') 20 21 raise ValidationError('New password is required')
if not request.data['new_password']: 21 22 if not request.data['new_password']:
raise ValidationError('Password cannot be blank') 22 23 raise ValidationError('Password cannot be blank')
23 24
currentuser = request.user 24 25 currentuser = request.user
25 26
if not currentuser.check_password(request.data['old_password']): 26 27 if not currentuser.check_password(request.data['old_password']):
raise ValidationError('Invalid old password') 27 28 raise ValidationError('Invalid old password')
28 29
currentuser.set_password(request.data['new_password']) 29 30 currentuser.set_password(request.data['new_password'])
currentuser.save() 30 31 currentuser.save()
31 32
return Response(status=status.HTTP_204_NO_CONTENT) 32 33 return Response(status=status.HTTP_204_NO_CONTENT)
33 34
def get(self, request, format=None): 34 35 def get(self, request, format=None):
serializer = UserSerializer(request.user) 35 36 serializer = UserSerializer(request.user)
return Response(serializer.data) 36 37 return Response(serializer.data)
37 38
def post(self, request, format=None): 38 39 def post(self, request, format=None):
if 'email' not in request.data: 39 40 if 'email' not in request.data:
raise ValidationError('Email is required') 40 41 raise ValidationError('Email is required')
if 'password' not in request.data: 41 42 if 'password' not in request.data:
raise ValidationError('Password is required') 42 43 raise ValidationError('Password is required')
43 44
email = request.data['email'] 44 45 email = request.data['email']
user = User.objects.create_user(email) 45 46 user = User.objects.create_user(email)
46 47
body = ''' 47 48 body = '''
Visit the following link to confirm your email address: 48 49 Visit the following link to confirm your email address:
http://flashy.cards/app/verify_email/%s 49 50 http://flashy.cards/app/verify_email/%s
50 51
If you did not register for Flashy, no action is required. 51 52 If you did not register for Flashy, no action is required.
''' 52 53 '''
53 54
send_mail("Please verify your Flashy account", 54 55 send_mail("Please verify your Flashy account",
body % user.confirmation_key, 55 56 body % user.confirmation_key,
"noreply@flashy.cards", 56 57 "noreply@flashy.cards",
[user.email]) 57 58 [user.email])
58 59
return Response(UserSerializer(User).data) 59 60 return Response(UserSerializer(User).data)
60 61
def delete(self, request, format=None): 61 62 def delete(self, request, format=None):
request.user.delete() 62 63 request.user.delete()
return Response(status=status.HTTP_204_NO_CONTENT) 63 64 return Response(status=status.HTTP_204_NO_CONTENT)
64 65
class UserLogin(APIView): 65 66 class UserLogin(APIView):
""" 66 67 """
Authenticates user and returns user data if valid. Handles invalid 67 68 Authenticates user and returns user data if valid. Handles invalid
users. 68 69 users.
""" 69 70 """
def post(self, request, format=None): 70 71 def post(self, request, format=None):
72 """
73 Returns user data if valid.
74 """
if 'email' not in request.data: 71 75 if 'email' not in request.data:
raise ValidationError('Email is required') 72 76 raise ValidationError('Email is required')
if 'password' not in request.data: 73 77 if 'password' not in request.data:
raise ValidationError('Password is required') 74 78 raise ValidationError('Password is required')
75 79
email = request.data['email'] 76 80 email = request.data['email']
password = request.data['password'] 77 81 password = request.data['password']
user = authenticate(username=email, password=password) 78 82 user = authenticate(username=email, password=password)
79 83
if user is not None: 80 84 if user is not None:
if user.is_active: 81 85 if user.is_active:
login(request, user) 82 86 login(request, user)
return Response(UserSerializer(User).data) 83 87 return Response(UserSerializer(User).data)
else: 84 88 else:
raise ValidationError('Account is disabled') 85 89 raise ValidationError('Account is disabled')
else: 86 90 else:
raise ValidationError('Invalid email or password') 87 91 raise ValidationError('Invalid email or password')
92
93 class PasswordReset(APIView):
94 """
95 Allows user to reset their password.
96 """
97 def post(self, request, format=None):
98 """
99 Send a password reset token/link to the provided email.
100 """
101 if 'email' not in request.data:
102 raise ValidationError('Email is required')
103
104 email = request.data['email']
105
106 # Find the user since they are not logged in.
107 try:
108 user = User.objects.get(email=email)
109 except User.DoesNotExist:
110 raise NotFound('Email does not exist')
111
112 token = default_token_generator.make_token(user)
113
114 body = '''
115 Visit the following link to reset your password:
116 http://flashy.cards/app/reset_password/%d/%s
117
118 If you did not request a password reset, no action is required.
119 '''
120
121 send_mail("Please verify your Flashy account",
122 body % (user.pk, token),
123 "noreply@flashy.cards",
flashy/urls.py View file @ 25cc754
from django.conf.urls import include, url 1 1 from django.conf.urls import include, url
from django.contrib import admin 2 2 from django.contrib import admin
from flashcards.views import SectionViewSet, LecturePeriodViewSet 3 3 from flashcards.views import SectionViewSet, LecturePeriodViewSet
from rest_framework.routers import DefaultRouter 4 4 from rest_framework.routers import DefaultRouter
from flashcards.api import * 5 5 from flashcards.api import *
6 6
router = DefaultRouter() 7 7 router = DefaultRouter()
router.register(r'sections', SectionViewSet) 8 8 router.register(r'sections', SectionViewSet)
router.register(r'lectureperiods', LecturePeriodViewSet) 9 9 router.register(r'lectureperiods', LecturePeriodViewSet)
10 10
urlpatterns = [ 11 11 urlpatterns = [
url(r'^api/users/me$', UserDetail.as_view()), 12 12 url(r'^api/users/me$', UserDetail.as_view()),
url(r'^api/login$', UserLogin.as_view()), 13 13 url(r'^api/login$', UserLogin.as_view()),
14 url(r'^api/reset_password$', PasswordReset.as_view()),
url(r'^api/', include(router.urls)), 14 15 url(r'^api/', include(router.urls)),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')), 15 16 url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)), 16 17 url(r'^admin/', include(admin.site.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) 17 18 url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))