Commit 33f8a47a8b87874c0ce2e7080fdb43079d2e147b

Authored by Andrew Buss
1 parent f0ac627bcd
Exists in master

enforce 24 hour grace period on email verification

Showing 2 changed files with 23 additions and 7 deletions Side-by-side Diff

flashcards/api.py View file @ 33f8a47
  1 +from django.utils.timezone import now
1 2 from flashcards.models import Flashcard, UserFlashcardQuiz
  3 +from rest_framework.exceptions import PermissionDenied
2 4 from rest_framework.pagination import PageNumberPagination
3 5 from rest_framework.permissions import BasePermission
4 6  
  7 +mock_no_params = lambda x: None
5 8  
6   -mock_no_params = lambda x:None
7 9  
8 10 class StandardResultsSetPagination(PageNumberPagination):
9 11 page_size = 40
... ... @@ -36,4 +38,17 @@
36 38 return True
37 39 assert type(obj) is UserFlashcardQuiz
38 40 return request.user == obj.user_flashcard.user
  41 +
  42 +
  43 +class IsAuthenticatedAndConfirmed(BasePermission):
  44 + """
  45 + Allows access only to authenticated users who have verified their email address, with a 24 hour grace period
  46 + """
  47 +
  48 + def has_permission(self, request, view):
  49 + if not (request.user and request.user.is_authenticated()): return False
  50 + if request.user.confirmed_email: return True
  51 + if (now() - request.user.date_joined).days > 0:
  52 + raise PermissionDenied('Please verify your email before continuing')
  53 + return True
flashcards/views.py View file @ 33f8a47
... ... @@ -2,7 +2,8 @@
2 2 from django.contrib import auth
3 3 from django.db import IntegrityError
4 4 from django.shortcuts import get_object_or_404
5   -from flashcards.api import StandardResultsSetPagination, IsEnrolledInAssociatedSection, IsFlashcardReviewer
  5 +from flashcards.api import StandardResultsSetPagination, IsEnrolledInAssociatedSection, IsFlashcardReviewer, \
  6 + IsAuthenticatedAndConfirmed
6 7 from flashcards.models import Section, User, Flashcard, FlashcardHide, UserFlashcard, UserFlashcardQuiz
7 8 from flashcards.notifications import notify_new_card
8 9 from flashcards.serializers import SectionSerializer, UserUpdateSerializer, RegistrationSerializer, UserSerializer, \
... ... @@ -27,7 +28,7 @@
27 28 queryset = Section.objects.all()
28 29 serializer_class = DeepSectionSerializer
29 30 pagination_class = StandardResultsSetPagination
30   - permission_classes = [IsAuthenticated]
  31 + permission_classes = [IsAuthenticatedAndConfirmed]
31 32  
32 33 @detail_route(methods=['GET'])
33 34 def flashcards(self, request, pk):
... ... @@ -116,7 +117,7 @@
116 117  
117 118 class UserSectionListView(ListAPIView):
118 119 serializer_class = DeepSectionSerializer
119   - permission_classes = [IsAuthenticated]
  120 + permission_classes = [IsAuthenticatedAndConfirmed]
120 121  
121 122 def get_queryset(self):
122 123 return self.request.user.sections.all()
... ... @@ -126,7 +127,7 @@
126 127  
127 128 class UserDetail(GenericAPIView):
128 129 serializer_class = UserSerializer
129   - permission_classes = [IsAuthenticated]
  130 + permission_classes = [IsAuthenticatedAndConfirmed]
130 131  
131 132 def patch(self, request, format=None):
132 133 """
... ... @@ -258,7 +259,7 @@
258 259 class FlashcardViewSet(GenericViewSet, CreateModelMixin, RetrieveModelMixin):
259 260 queryset = Flashcard.objects.all()
260 261 serializer_class = FlashcardSerializer
261   - permission_classes = [IsAuthenticated, IsEnrolledInAssociatedSection]
  262 + permission_classes = [IsAuthenticatedAndConfirmed, IsEnrolledInAssociatedSection]
262 263 # Override create in CreateModelMixin
263 264 def create(self, request, *args, **kwargs):
264 265 serializer = FlashcardSerializer(data=request.data)
... ... @@ -340,7 +341,7 @@
340 341  
341 342  
342 343 class UserFlashcardQuizViewSet(GenericViewSet, CreateModelMixin, UpdateModelMixin):
343   - permission_classes = [IsAuthenticated, IsFlashcardReviewer]
  344 + permission_classes = [IsAuthenticatedAndConfirmed, IsFlashcardReviewer]
344 345 queryset = UserFlashcardQuiz.objects.all()
345 346  
346 347 def get_serializer_class(self):