Commit 85df4eee by Bill DeRusha

Merge pull request #11630 from edx/bderusha/soft-sec-id

Do not send initial verification photo_id if new photo_id provided
parents d00490ef beacf3c9
...@@ -593,18 +593,22 @@ class SoftwareSecurePhotoVerification(PhotoVerification): ...@@ -593,18 +593,22 @@ class SoftwareSecurePhotoVerification(PhotoVerification):
copy_id_photo_from = models.ForeignKey("self", null=True, blank=True) copy_id_photo_from = models.ForeignKey("self", null=True, blank=True)
@classmethod @classmethod
def get_initial_verification(cls, user): def get_initial_verification(cls, user, earliest_allowed_date=None):
"""Get initial verification for a user with the 'photo_id_key'. """Get initial verification for a user with the 'photo_id_key'.
Arguments: Arguments:
user(User): user object user(User): user object
earliest_allowed_date(datetime): override expiration date for initial verification
Return: Return:
SoftwareSecurePhotoVerification (object) SoftwareSecurePhotoVerification (object) or None
""" """
init_verification = cls.objects.filter( init_verification = cls.objects.filter(
user=user, user=user,
status__in=["submitted", "approved"] status__in=["submitted", "approved"],
created_at__gte=(
earliest_allowed_date or cls._earliest_allowed_date()
)
).exclude(photo_id_key='') ).exclude(photo_id_key='')
return init_verification.latest('created_at') if init_verification.exists() else None return init_verification.latest('created_at') if init_verification.exists() else None
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from datetime import timedelta, datetime from datetime import timedelta, datetime
import ddt
import json import json
import mock
import requests.exceptions
import pytz
import ddt
from django.conf import settings from django.conf import settings
from django.db import IntegrityError from django.db import IntegrityError
from django.test import TestCase from django.test import TestCase
from freezegun import freeze_time
import mock
from mock import patch from mock import patch
from nose.tools import assert_is_none, assert_equals, assert_raises, assert_true, assert_false # pylint: disable=no-name-in-module from nose.tools import assert_is_none, assert_equals, assert_raises, assert_true, assert_false # pylint: disable=no-name-in-module
import pytz
import requests.exceptions
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
...@@ -42,8 +43,9 @@ iwIDAQAB ...@@ -42,8 +43,9 @@ iwIDAQAB
"API_URL": "http://localhost/verify_student/fake_endpoint", "API_URL": "http://localhost/verify_student/fake_endpoint",
"AWS_ACCESS_KEY": "FAKEACCESSKEY", "AWS_ACCESS_KEY": "FAKEACCESSKEY",
"AWS_SECRET_KEY": "FAKESECRETKEY", "AWS_SECRET_KEY": "FAKESECRETKEY",
"S3_BUCKET": "fake-bucket" "S3_BUCKET": "fake-bucket",
} },
"DAYS_GOOD_FOR": 10,
} }
...@@ -524,6 +526,21 @@ class TestPhotoVerification(ModuleStoreTestCase): ...@@ -524,6 +526,21 @@ class TestPhotoVerification(ModuleStoreTestCase):
self.assertIsNotNone(second_result) self.assertIsNotNone(second_result)
self.assertEqual(second_result, first_result) self.assertEqual(second_result, first_result)
# Test method 'get_initial_verification' returns None after expiration
expired_future = datetime.utcnow() + timedelta(days=(FAKE_SETTINGS['DAYS_GOOD_FOR'] + 1))
with freeze_time(expired_future):
third_result = SoftwareSecurePhotoVerification.get_initial_verification(user)
self.assertIsNone(third_result)
# Test method 'get_initial_verification' returns correct attempt after system expiration,
# but within earliest allowed override.
expired_future = datetime.utcnow() + timedelta(days=(FAKE_SETTINGS['DAYS_GOOD_FOR'] + 1))
earliest_allowed = datetime.utcnow() - timedelta(days=1)
with freeze_time(expired_future):
fourth_result = SoftwareSecurePhotoVerification.get_initial_verification(user, earliest_allowed)
self.assertIsNotNone(fourth_result)
self.assertEqual(fourth_result, first_result)
@ddt.ddt @ddt.ddt
class VerificationCheckpointTest(ModuleStoreTestCase): class VerificationCheckpointTest(ModuleStoreTestCase):
......
...@@ -1427,7 +1427,8 @@ class TestSubmitPhotosForVerification(TestCase): ...@@ -1427,7 +1427,8 @@ class TestSubmitPhotosForVerification(TestCase):
"AWS_ACCESS_KEY": "c987c7efe35c403caa821f7328febfa1", "AWS_ACCESS_KEY": "c987c7efe35c403caa821f7328febfa1",
"AWS_SECRET_KEY": "fc595fc657c04437bb23495d8fe64881", "AWS_SECRET_KEY": "fc595fc657c04437bb23495d8fe64881",
"S3_BUCKET": "test.example.com", "S3_BUCKET": "test.example.com",
} },
"DAYS_GOOD_FOR": 10,
}) })
@httpretty.activate @httpretty.activate
@moto.mock_s3 @moto.mock_s3
...@@ -1470,6 +1471,16 @@ class TestSubmitPhotosForVerification(TestCase): ...@@ -1470,6 +1471,16 @@ class TestSubmitPhotosForVerification(TestCase):
self.assertNotEqual(initial_photo_response.content, reverification_photo_response.content) self.assertNotEqual(initial_photo_response.content, reverification_photo_response.content)
# Submit a new face photo and photo id for verification
self._submit_photos(
face_image=self.IMAGE_DATA + "9999",
photo_id_image=self.IMAGE_DATA + "1111",
)
two_photo_reverification_data = self._get_post_data()
# Verify that the initial attempt sent a new ID photo for the reverification attempt
self.assertNotEqual(initial_data["PhotoIDKey"], two_photo_reverification_data["PhotoIDKey"])
@ddt.data('face_image', 'photo_id_image') @ddt.data('face_image', 'photo_id_image')
def test_invalid_image_data(self, invalid_param): def test_invalid_image_data(self, invalid_param):
params = { params = {
......
...@@ -872,6 +872,11 @@ class SubmitPhotosView(View): ...@@ -872,6 +872,11 @@ class SubmitPhotosView(View):
face_image, photo_id_image, response = self._decode_image_data( face_image, photo_id_image, response = self._decode_image_data(
params["face_image"], params.get("photo_id_image") params["face_image"], params.get("photo_id_image")
) )
# If we have a photo_id we do not want use the initial verification image.
if photo_id_image is not None:
initial_verification = None
if response is not None: if response is not None:
return response return response
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment