Commit 9bd8c31d05d30e57cdb557c424557af104fcef23

Authored by Andrew Buss
Exists in master

Merge branch 'master' of git.ucsd.edu:110swag/flashy-backend

Showing 2 changed files Side-by-side Diff

flashcards/api.py View file @ 9bd8c31
1 1 from django.contrib.auth import login, authenticate
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
3 5 from rest_framework.views import APIView
4 6 from rest_framework.response import Response
5 7 from rest_framework import status
6   -from rest_framework.exceptions import ValidationError
  8 +from rest_framework.exceptions import ValidationError, NotFound
7 9 from flashcards.serializers import *
8 10  
9 11  
... ... @@ -60,4 +62,84 @@
60 62 login(request, user)
61 63  
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.
  133 + """
  134 + if 'new_password' not in request.data:
  135 + raise ValidationError('New password is required')
  136 + if not request.data['new_password']:
  137 + raise ValidationError('Password cannot be blank')
  138 +
  139 + user = request.user
  140 +
  141 + user.set_password(request.data['new_password'])
  142 + user.save()
  143 +
  144 + return Response(status=status.HTTP_204_NO_CONTENT)
flashy/urls.py View file @ 9bd8c31
... ... @@ -9,7 +9,9 @@
9 9 router.register(r'lectureperiods', LecturePeriodViewSet)
10 10  
11 11 urlpatterns = [
12   - url(r'^api/user/me$', UserDetail.as_view()),
  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()),
13 15 url(r'^api/', include(router.urls)),
14 16 url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
15 17 url(r'^admin/', include(admin.site.urls)),