diff --git a/lms/djangoapps/verify_student/tests/test_services.py b/lms/djangoapps/verify_student/tests/test_services.py index e8e95b04dd..6232e93320 100644 --- a/lms/djangoapps/verify_student/tests/test_services.py +++ b/lms/djangoapps/verify_student/tests/test_services.py @@ -324,3 +324,25 @@ class TestIDVerificationServiceUserStatus(TestCase): } status = IDVerificationService.user_status(self.user) self.assertDictEqual(status, expected_status) + + def test_denied_after_approved_verification(self): + with freeze_time('2015-07-11') as frozen_datetime: + # create approved photo verification for the user + SoftwareSecurePhotoVerification.objects.create( + user=self.user, + status='approved', + expiration_date=now() + timedelta(days=settings.VERIFY_STUDENT["DAYS_GOOD_FOR"]) + ) + expected_date = now() + frozen_datetime.move_to('2015-07-14') + SoftwareSecurePhotoVerification.objects.create( + user=self.user, + status='denied', + expiration_date=now() + timedelta(days=settings.VERIFY_STUDENT["DAYS_GOOD_FOR"]) + ) + expected_status = { + 'status': 'approved', 'error': '', 'should_display': True, + 'verification_expiry': '', 'status_date': expected_date + } + status = IDVerificationService.user_status(self.user) + self.assertDictEqual(status, expected_status) diff --git a/openedx/core/djangoapps/user_api/serializers.py b/openedx/core/djangoapps/user_api/serializers.py index edcdcd9d8f..a5d26fe45a 100644 --- a/openedx/core/djangoapps/user_api/serializers.py +++ b/openedx/core/djangoapps/user_api/serializers.py @@ -8,10 +8,8 @@ from django.utils.timezone import now from rest_framework import serializers from lms.djangoapps.verify_student.models import ( - IDVerificationAttempt, ManualVerification, - SoftwareSecurePhotoVerification, - SSOVerification + SoftwareSecurePhotoVerification ) from .models import UserPreference @@ -103,40 +101,6 @@ class CountryTimeZoneSerializer(serializers.Serializer): # pylint: disable=abst description = serializers.CharField() -class IDVerificationSerializer(serializers.ModelSerializer): - """ - Serializer that generates a representation of a user's ID verification status. - """ - is_verified = serializers.SerializerMethodField() - - def get_is_verified(self, obj): - """ - Return a boolean indicating if a the user is verified. - """ - return obj.status == 'approved' and obj.expiration_datetime > now() - - -class SoftwareSecurePhotoVerificationSerializer(IDVerificationSerializer): - - class Meta(object): - fields = ('status', 'expiration_datetime', 'is_verified') - model = SoftwareSecurePhotoVerification - - -class SSOVerificationSerializer(IDVerificationSerializer): - - class Meta(object): - fields = ('status', 'expiration_datetime', 'is_verified') - model = SSOVerification - - -class ManualVerificationSerializer(IDVerificationSerializer): - - class Meta(object): - fields = ('status', 'expiration_datetime', 'is_verified') - model = ManualVerification - - class IDVerificationDetailsSerializer(serializers.Serializer): type = serializers.SerializerMethodField() status = serializers.CharField() diff --git a/openedx/core/djangoapps/user_api/verification_api/tests/test_views.py b/openedx/core/djangoapps/user_api/verification_api/tests/test_views.py index 93678ddea4..28d47548bf 100644 --- a/openedx/core/djangoapps/user_api/verification_api/tests/test_views.py +++ b/openedx/core/djangoapps/user_api/verification_api/tests/test_views.py @@ -15,7 +15,7 @@ from lms.djangoapps.verify_student.tests.factories import SSOVerificationFactory from common.djangoapps.student.tests.factories import UserFactory FROZEN_TIME = '2015-01-01' -VERIFY_STUDENT = {'DAYS_GOOD_FOR': 365} +VERIFY_STUDENT = {'DAYS_GOOD_FOR': 365, 'EXPIRING_SOON_WINDOW': 20} class VerificationStatusViewTestsMixin: @@ -95,9 +95,12 @@ class PhotoVerificationStatusViewTests(VerificationStatusViewTestsMixin, TestCas VIEW_NAME = 'verification_status' def get_expected_response(self, *args, **kwargs): + verification_status = self.photo_verification.status + if self.photo_verification.status == 'submitted': + verification_status = 'pending' return { - 'status': self.photo_verification.status, - 'expiration_datetime': '{}Z'.format(kwargs.get('expected_expires').isoformat()), + 'status': verification_status, + 'expiration_datetime': '', 'is_verified': kwargs.get('verified') } @@ -109,6 +112,14 @@ class PhotoVerificationStatusViewTests(VerificationStatusViewTestsMixin, TestCas self.client.login(username=self.user.username, password=self.PASSWORD) self.assert_verification_returned(verified=True) + def test_multiple_verifications(self): + self.photo_verification.status = 'approved' + self.photo_verification.save() + SoftwareSecurePhotoVerification.objects.create(user=self.user, status='denied') + self.client.logout() + self.client.login(username=self.user.username, password=self.PASSWORD) + self.assert_verification_returned(verified=True) + @override_settings(VERIFY_STUDENT=VERIFY_STUDENT) class VerificationsDetailsViewTests(VerificationStatusViewTestsMixin, TestCase): diff --git a/openedx/core/djangoapps/user_api/verification_api/views.py b/openedx/core/djangoapps/user_api/verification_api/views.py index 759fac1e93..b2790bd8c0 100644 --- a/openedx/core/djangoapps/user_api/verification_api/views.py +++ b/openedx/core/djangoapps/user_api/verification_api/views.py @@ -4,57 +4,38 @@ from django.contrib.auth import get_user_model from django.http import Http404 from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication from rest_framework.authentication import SessionAuthentication -from rest_framework.generics import ListAPIView, RetrieveAPIView +from rest_framework.generics import ListAPIView +from rest_framework.response import Response +from rest_framework.views import APIView -from lms.djangoapps.verify_student.models import ManualVerification, SoftwareSecurePhotoVerification, SSOVerification from lms.djangoapps.verify_student.services import IDVerificationService -from lms.djangoapps.verify_student.utils import most_recent_verification -from openedx.core.djangoapps.user_api.serializers import ( - IDVerificationDetailsSerializer, - ManualVerificationSerializer, - SoftwareSecurePhotoVerificationSerializer, - SSOVerificationSerializer -) +from openedx.core.djangoapps.user_api.serializers import IDVerificationDetailsSerializer from openedx.core.lib.api.authentication import BearerAuthentication from openedx.core.lib.api.permissions import IsStaffOrOwner -class IDVerificationStatusView(RetrieveAPIView): - """ IDVerificationStatus detail endpoint. """ +class IDVerificationStatusView(APIView): + """ IDVerification Status endpoint """ authentication_classes = (JwtAuthentication, BearerAuthentication, SessionAuthentication,) permission_classes = (IsStaffOrOwner,) - def get_serializer(self, *args, **kwargs): - """ - Overrides default get_serializer in order to choose the correct serializer for the instance. - """ - instance = args[0] - kwargs['context'] = self.get_serializer_context() - if isinstance(instance, SoftwareSecurePhotoVerification): - return SoftwareSecurePhotoVerificationSerializer(*args, **kwargs) - elif isinstance(instance, SSOVerification): - return SSOVerificationSerializer(*args, **kwargs) - else: - return ManualVerificationSerializer(*args, **kwargs) + def get(self, request, **kwargs): + username = kwargs.get('username') + User = get_user_model() + try: + user = User.objects.get(username=username) + user_status = IDVerificationService.user_status(user) + if user_status.get('status') == 'none': + raise Http404 - def get_object(self): - username = self.kwargs['username'] - photo_verifications = SoftwareSecurePhotoVerification.objects.filter( - user__username=username).order_by('-updated_at') - sso_verifications = SSOVerification.objects.filter(user__username=username).order_by('-updated_at') - manual_verifications = ManualVerification.objects.filter(user__username=username).order_by('-updated_at') + return Response({ + "is_verified": user_status.get('status') == 'approved', + "status": user_status.get('status'), + "expiration_datetime": user_status.get('verification_expiry', '') + }) - if photo_verifications or sso_verifications or manual_verifications: - verification = most_recent_verification( - photo_verifications, - sso_verifications, - manual_verifications, - 'updated_at' - ) - self.check_object_permissions(self.request, verification) - return verification - - raise Http404 + except User.DoesNotExist: + raise Http404 class IDVerificationStatusDetailsView(ListAPIView):