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