示例#1
0
    def test_initial_verification_for_user(self):
        """Test that method 'get_initial_verification' of model
        'SoftwareSecurePhotoVerification' always returns the initial
        verification with field 'photo_id_key' set against a user.
        """
        user = UserFactory.create()

        # No initial verification for the user
        result = SoftwareSecurePhotoVerification.get_initial_verification(
            user=user)
        self.assertIs(result, None)

        # Make an initial verification with 'photo_id_key'
        attempt = SoftwareSecurePhotoVerification(
            user=user, photo_id_key="dummy_photo_id_key")
        attempt.status = 'approved'
        attempt.save()

        # Check that method 'get_initial_verification' returns the correct
        # initial verification attempt
        first_result = SoftwareSecurePhotoVerification.get_initial_verification(
            user=user)
        self.assertIsNotNone(first_result)

        # Now create a second verification without 'photo_id_key'
        attempt = SoftwareSecurePhotoVerification(user=user)
        attempt.status = 'submitted'
        attempt.save()

        # Test method 'get_initial_verification' still returns the correct
        # initial verification attempt which have 'photo_id_key' set
        second_result = SoftwareSecurePhotoVerification.get_initial_verification(
            user=user)
        self.assertIsNotNone(second_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)
示例#2
0
    def test_active_for_user(self):
        """
        Make sure we can retrive a user's active (in progress) verification
        attempt.
        """
        user = UserFactory.create()

        # This user has no active at the moment...
        assert_is_none(SoftwareSecurePhotoVerification.active_for_user(user))

        # Create an attempt and mark it ready...
        attempt = SoftwareSecurePhotoVerification(user=user)
        attempt.mark_ready()
        assert_equals(attempt,
                      SoftwareSecurePhotoVerification.active_for_user(user))

        # A new user won't see this...
        user2 = UserFactory.create()
        user2.save()
        assert_is_none(SoftwareSecurePhotoVerification.active_for_user(user2))

        # If it's got a different status, it doesn't count
        for status in ["submitted", "must_retry", "approved", "denied"]:
            attempt.status = status
            attempt.save()
            assert_is_none(
                SoftwareSecurePhotoVerification.active_for_user(user))

        # But if we create yet another one and mark it ready, it passes again.
        attempt_2 = SoftwareSecurePhotoVerification(user=user)
        attempt_2.mark_ready()
        assert_equals(attempt_2,
                      SoftwareSecurePhotoVerification.active_for_user(user))

        # And if we add yet another one with a later created time, we get that
        # one instead. We always want the most recent attempt marked ready()
        attempt_3 = SoftwareSecurePhotoVerification(
            user=user, created_at=attempt_2.created_at + timedelta(days=1))
        attempt_3.save()

        # We haven't marked attempt_3 ready yet, so attempt_2 still wins
        assert_equals(attempt_2,
                      SoftwareSecurePhotoVerification.active_for_user(user))

        # Now we mark attempt_3 ready and expect it to come back
        attempt_3.mark_ready()
        assert_equals(attempt_3,
                      SoftwareSecurePhotoVerification.active_for_user(user))
示例#3
0
    def _submit_attempt(self, user, face_image, photo_id_image=None, initial_verification=None):
        """
        Submit a verification attempt.

        Arguments:
            user (User): The user making the attempt.
            face_image (str): Decoded face image data.

        Keyword Arguments:
            photo_id_image (str or None): Decoded photo ID image data.
            initial_verification (SoftwareSecurePhotoVerification): The initial verification attempt.
        """
        attempt = SoftwareSecurePhotoVerification(user=user)

        # We will always have face image data, so upload the face image
        attempt.upload_face_image(face_image)

        # If an ID photo wasn't submitted, re-use the ID photo from the initial attempt.
        # Earlier validation rules ensure that at least one of these is available.
        if photo_id_image is not None:
            attempt.upload_photo_id_image(photo_id_image)
        elif initial_verification is None:
            # Earlier validation should ensure that we never get here.
            log.error(
                "Neither a photo ID image or initial verification attempt provided. "
                "Parameter validation in the view should prevent this from happening!"
            )

        # Submit the attempt
        attempt.mark_ready()
        attempt.submit(copy_id_photo_from=initial_verification)

        return attempt
示例#4
0
 def test_parse_error_msg_success(self):
     user = UserFactory.create()
     attempt = SoftwareSecurePhotoVerification(user=user)
     attempt.status = 'denied'
     attempt.error_msg = '[{"userPhotoReasons": ["Face out of view"]}, {"photoIdReasons": ["Photo hidden/No photo", "ID name not provided"]}]'
     parsed_error_msg = attempt.parsed_error_msg()
     self.assertEquals(parsed_error_msg, ['id_image_missing_name', 'user_image_not_clear', 'id_image_not_clear'])
示例#5
0
 def test_parse_error_msg_success(self):
     user = UserFactory.create()
     attempt = SoftwareSecurePhotoVerification(user=user)
     attempt.status = 'denied'
     attempt.error_msg = '[{"photoIdReasons": ["Not provided"]}]'
     parsed_error_msg = attempt.parsed_error_msg()
     self.assertEquals("No photo ID was provided.", parsed_error_msg)
示例#6
0
 def _verify_user():
     if not SoftwareSecurePhotoVerification.user_is_verified(user):
         obj = SoftwareSecurePhotoVerification(
             user=user, photo_id_key="dummy_photo_id_key")
         obj.status = 'approved'
         obj.submitted_at = datetime.datetime.now()
         obj.reviewing_user = User.objects.get(username='******')
         obj.save()
 def create_and_submit(self, user):
     """ Helper method that lets us create new SoftwareSecurePhotoVerifications """
     attempt = SoftwareSecurePhotoVerification(user=user)
     attempt.upload_face_image("Fake Data")
     attempt.upload_photo_id_image("More Fake Data")
     attempt.mark_ready()
     attempt.submit()
     return attempt
 def create_and_submit(self, user):
     """ Helper method that lets us create new SoftwareSecurePhotoVerifications """
     attempt = SoftwareSecurePhotoVerification(user=user)
     attempt.upload_face_image("Fake Data")
     attempt.upload_photo_id_image("More Fake Data")
     attempt.mark_ready()
     attempt.submit()
     attempt.expiry_date = now() + timedelta(days=FAKE_SETTINGS["DAYS_GOOD_FOR"])
     return attempt
示例#9
0
    def test_state_transitions(self):
        """
        Make sure we can't make unexpected status transitions.

        The status transitions we expect are::

                        → → → must_retry
                        ↑        ↑ ↓
            created → ready → submitted → approved
                                    ↓        ↑ ↓
                                    ↓ → →  denied
        """
        user = UserFactory.create()
        attempt = SoftwareSecurePhotoVerification(user=user)
        assert_equals(attempt.status, "created")

        # These should all fail because we're in the wrong starting state.
        assert_raises(VerificationException, attempt.submit)
        assert_raises(VerificationException, attempt.approve)
        assert_raises(VerificationException, attempt.deny)

        # Now let's fill in some values so that we can pass the mark_ready() call
        attempt.mark_ready()
        assert_equals(attempt.status, "ready")

        # ready (can't approve or deny unless it's "submitted")
        assert_raises(VerificationException, attempt.approve)
        assert_raises(VerificationException, attempt.deny)

        DENY_ERROR_MSG = '[{"photoIdReasons": ["Not provided"]}]'

        # must_retry
        attempt.status = "must_retry"
        attempt.system_error("System error")
        attempt.approve()
        attempt.status = "must_retry"
        attempt.deny(DENY_ERROR_MSG)

        # submitted
        attempt.status = "submitted"
        attempt.deny(DENY_ERROR_MSG)
        attempt.status = "submitted"
        attempt.approve()

        # approved
        assert_raises(VerificationException, attempt.submit)
        attempt.approve()  # no-op
        attempt.system_error(
            "System error")  # no-op, something processed it without error
        attempt.deny(DENY_ERROR_MSG)

        # denied
        assert_raises(VerificationException, attempt.submit)
        attempt.deny(DENY_ERROR_MSG)  # no-op
        attempt.system_error(
            "System error")  # no-op, something processed it without error
        attempt.approve()
示例#10
0
    def test_no_approved_verification(self):
        """Test that method 'get_recent_verification' of model
        'SoftwareSecurePhotoVerification' returns None if no
        'approved' verification are found
        """
        user = UserFactory.create()
        SoftwareSecurePhotoVerification(user=user)

        result = SoftwareSecurePhotoVerification.get_recent_verification(user=user)
        self.assertIs(result, None)
示例#11
0
    def test_user_has_ever_been_verified(self):
        """
        Test to make sure we correctly answer whether a user has ever been verified.
        """
        # Missing user
        assert not IDVerificationService.user_has_ever_been_verified(None)

        # User without any attempts
        photo_user = UserFactory.create()
        assert not IDVerificationService.user_has_ever_been_verified(
            photo_user)

        # User without an approved attempt
        attempt = SoftwareSecurePhotoVerification(user=photo_user,
                                                  status='submitted')
        attempt.save()
        assert not IDVerificationService.user_has_ever_been_verified(
            photo_user)

        # User with a submitted, then an approved attempt
        attempt = SoftwareSecurePhotoVerification(user=photo_user,
                                                  status='approved')
        attempt.save()
        assert IDVerificationService.user_has_ever_been_verified(photo_user)

        # User with a manual approved attempt
        manual_user = UserFactory.create()
        attempt = ManualVerification(user=manual_user, status='approved')
        attempt.save()
        assert IDVerificationService.user_has_ever_been_verified(manual_user)

        # User with 2 manual approved attempts
        attempt = ManualVerification(user=manual_user, status='approved')
        attempt.save()
        assert IDVerificationService.user_has_ever_been_verified(manual_user)

        # User with an SSO approved attempt, then a must_retry attempt
        sso_user = UserFactory.create()
        attempt = SSOVerification(user=sso_user, status='approved')
        attempt.save()
        attempt = SSOVerification(user=sso_user, status='must_retry')
        attempt.save()
        assert IDVerificationService.user_has_ever_been_verified(sso_user)
示例#12
0
    def create_and_submit(self):
        """Helper method to create a generic submission and send it."""
        user = UserFactory.create()
        attempt = SoftwareSecurePhotoVerification(user=user)
        user.profile.name = u"Rust\u01B4"

        attempt.upload_face_image("Just pretend this is image data")
        attempt.upload_photo_id_image("Hey, we're a photo ID")
        attempt.mark_ready()
        attempt.submit()

        return attempt
示例#13
0
    def test_retire_nonuser(self):
        """
        Attempt to Retire User with no records in table
        """
        user = UserFactory.create()
        attempt = SoftwareSecurePhotoVerification(user=user)

        # User with no records in table
        assert not attempt.retire_user(user_id=user.id)

        # No user
        assert not attempt.retire_user(user_id=47)
示例#14
0
    def test_get_verification_from_receipt(self):
        result = SoftwareSecurePhotoVerification.get_verification_from_receipt(
            '')
        assert result is None

        user = UserFactory.create()
        attempt = SoftwareSecurePhotoVerification(user=user)
        attempt.status = PhotoVerification.STATUS.submitted
        attempt.save()
        receipt_id = attempt.receipt_id
        result = SoftwareSecurePhotoVerification.get_verification_from_receipt(
            receipt_id)
        assert result is not None
示例#15
0
    def test_name_preset(self):
        """
        If a name was set when creating the photo verification
        (from name affirmation / verified name flow) it should not
        be overwritten by the profile name
        """
        user = UserFactory.create()
        user.profile.name = "Profile"

        preset_attempt = SoftwareSecurePhotoVerification(user=user)
        preset_attempt.name = "Preset"
        preset_attempt.mark_ready()
        assert "Preset" == preset_attempt.name
示例#16
0
    def test_expiration_date_null(self):
        """
        Test if the `expiration_date` field is null, `expiration_datetime` returns a
        default expiration date based on the time the entry was created.
        """
        user = UserFactory.create()
        verification = SoftwareSecurePhotoVerification(user=user)
        verification.expiration_date = None
        verification.save()

        assert verification.expiration_datetime == (
            verification.created_at +
            timedelta(days=FAKE_SETTINGS['DAYS_GOOD_FOR']))
 def test_deprecated_expiry_date(self):
     """
     Test `expiration_datetime` returns `expiry_date` if it is not null.
     """
     user = UserFactory.create()
     with freeze_time(now()):
         verification = SoftwareSecurePhotoVerification(user=user)
         # First, assert that expiration_date is set correctly
         assert verification.expiration_datetime == (
             now() + timedelta(days=FAKE_SETTINGS['DAYS_GOOD_FOR']))
         verification.expiry_date = now() + timedelta(days=10)
         # Then, assert that expiration_datetime favors expiry_date's value if set
         assert verification.expiration_datetime == (now() +
                                                     timedelta(days=10))
示例#18
0
    def test_submission_while_testing_flag_is_true(self):
        """ Test that a fake value is set for field 'photo_id_key' of user's
        initial verification when the feature flag 'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING'
        is enabled.
        """
        user = UserFactory.create()
        attempt = SoftwareSecurePhotoVerification(user=user)
        user.profile.name = "test-user"

        attempt.upload_photo_id_image("Image data")
        attempt.mark_ready()
        attempt.submit()

        self.assertEqual(attempt.photo_id_key, "fake-photo-id-key")
示例#19
0
    def create_upload_and_submit_attempt_for_user(self, user=None):
        """
        Helper method to create a generic submission with photos for
        a user and send it.
        """
        if not user:
            user = UserFactory.create()
        attempt = SoftwareSecurePhotoVerification(user=user)
        user.profile.name = u"Rust\u01B4"

        attempt.upload_face_image("Just pretend this is image data")
        attempt.upload_photo_id_image("Hey, we're a photo ID")
        attempt.mark_ready()
        return self.submit_attempt(attempt)
示例#20
0
 def test_parse_error_msg_failure(self):
     user = UserFactory.create()
     attempt = SoftwareSecurePhotoVerification(user=user)
     attempt.status = 'denied'
     # when we can't parse into json
     bad_messages = {
         'Not Provided',
         '[{"IdReasons": ["Not provided"]}]',
         '{"IdReasons": ["Not provided"]}',
         u'[{"ïḋṚëäṡöṅṡ": ["Ⓝⓞⓣ ⓟⓡⓞⓥⓘⓓⓔⓓ "]}]',
     }
     for msg in bad_messages:
         attempt.error_msg = msg
         parsed_error_msg = attempt.parsed_error_msg()
         self.assertEquals(parsed_error_msg,
                           "There was an error verifying your ID photos.")
示例#21
0
    def test_name_freezing(self):
        """
        You can change your name prior to marking a verification attempt ready,
        but changing your name afterwards should not affect the value in the
        in the attempt record. Basically, we want to always know what your name
        was when you submitted it.
        """
        user = UserFactory.create()
        user.profile.name = "Jack \u01B4"  # gratuious non-ASCII char to test encodings

        attempt = SoftwareSecurePhotoVerification(user=user)
        user.profile.name = "Clyde \u01B4"
        attempt.mark_ready()

        user.profile.name = "Rusty \u01B4"

        assert 'Clyde ƴ' == attempt.name
示例#22
0
    def test_user_is_verified(self):
        """
        Test to make sure we correctly answer whether a user has been verified.
        """
        user = UserFactory.create()
        attempt = SoftwareSecurePhotoVerification(user=user)
        attempt.save()

        # If it's any of these, they're not verified...
        for status in ["created", "ready", "denied", "submitted", "must_retry"]:
            attempt.status = status
            attempt.save()
            assert_false(SoftwareSecurePhotoVerification.user_is_verified(user), status)

        attempt.status = "approved"
        attempt.save()
        assert_true(SoftwareSecurePhotoVerification.user_is_verified(user), attempt.status)
示例#23
0
    def test_update_expiry_email_date_for_user(self):
        """Test that method update_expiry_email_date_for_user of
        model 'SoftwareSecurePhotoVerification' set expiry_email_date
        if the most recent approved verification is expired.
        """
        email_config = getattr(settings, 'VERIFICATION_EXPIRY_EMAIL', {'DAYS_RANGE': 1, 'RESEND_DAYS': 15})
        user = UserFactory.create()
        verification = SoftwareSecurePhotoVerification(user=user)
        verification.expiry_date = now() - timedelta(days=FAKE_SETTINGS['DAYS_GOOD_FOR'])
        verification.status = 'approved'
        verification.save()

        self.assertIsNone(verification.expiry_email_date)

        SoftwareSecurePhotoVerification.update_expiry_email_date_for_user(user, email_config)
        result = SoftwareSecurePhotoVerification.get_recent_verification(user=user)

        self.assertIsNotNone(result.expiry_email_date)
示例#24
0
    def test_get_recent_verification_expiry_null(self):
        """Test that method 'get_recent_verification' of model
        'SoftwareSecurePhotoVerification' will return None when expiry_date
        is NULL for 'approved' verifications based on updated_at value.
        """
        user = UserFactory.create()
        attempt = None

        for _ in range(2):
            # Make an approved verification
            attempt = SoftwareSecurePhotoVerification(user=user)
            attempt.status = PhotoVerification.STATUS.approved
            attempt.save()

        # Test method 'get_recent_verification' returns None
        # as attempts don't have an expiry_date
        recent_verification = SoftwareSecurePhotoVerification.get_recent_verification(
            user=user)
        self.assertIsNone(recent_verification)
示例#25
0
    def test_user_has_valid_or_pending(self):
        """
        Determine whether we have to prompt this user to verify, or if they've
        already at least initiated a verification submission.
        """
        user = UserFactory.create()
        attempt = SoftwareSecurePhotoVerification(user=user)

        # If it's any of these statuses, they don't have anything outstanding
        for status in ["created", "ready", "denied"]:
            attempt.status = status
            attempt.save()
            assert_false(SoftwareSecurePhotoVerification.user_has_valid_or_pending(user), status)

        # Any of these, and we are. Note the benefit of the doubt we're giving
        # -- must_retry, and submitted both count until we hear otherwise
        for status in ["submitted", "must_retry", "approved"]:
            attempt.status = status
            attempt.save()
            assert_true(SoftwareSecurePhotoVerification.user_has_valid_or_pending(user), status)
示例#26
0
    def test_get_recent_verification(self):
        """Test that method 'get_recent_verification' of model
        'SoftwareSecurePhotoVerification' always returns the most
        recent 'approved' verification based on updated_at set
        against a user.
        """
        user = UserFactory.create()
        attempt = None

        for _ in range(2):
            # Make an approved verification
            attempt = SoftwareSecurePhotoVerification(user=user)
            attempt.status = 'approved'
            attempt.save()

        # Test method 'get_recent_verification' returns the most recent
        # verification attempt based on updated_at
        recent_verification = SoftwareSecurePhotoVerification.get_recent_verification(user=user)
        self.assertIsNotNone(recent_verification)
        self.assertEqual(recent_verification.id, attempt.id)
示例#27
0
    def test_get_recent_verification(self):
        """Test that method 'get_recent_verification' of model
        'SoftwareSecurePhotoVerification' always returns the most
        recent 'approved' verification based on updated_at set
        against a user.
        """
        user = UserFactory.create()
        attempt = None

        for _ in range(2):
            # Make an approved verification
            attempt = SoftwareSecurePhotoVerification(user=user)
            attempt.status = PhotoVerification.STATUS.approved
            attempt.expiration_date = datetime.now()
            attempt.save()

        # Test method 'get_recent_verification' returns the most recent
        # verification attempt based on updated_at
        recent_verification = SoftwareSecurePhotoVerification.get_recent_verification(
            user=user)
        assert recent_verification is not None
        assert recent_verification.id == attempt.id
    def test_retire_user(self):
        user = UserFactory.create()
        user.profile.name = u"Enrique"

        attempt = SoftwareSecurePhotoVerification(user=user)
        attempt.mark_ready()
        attempt.status = "submitted"
        attempt.photo_id_image_url = "https://example.com/test/image/img.jpg"
        attempt.face_image_url = "https://example.com/test/face/img.jpg"
        attempt.approve()

        # Before Delete
        assert_equals(attempt.name, user.profile.name)
        assert_equals(attempt.photo_id_image_url,
                      'https://example.com/test/image/img.jpg')
        assert_equals(attempt.face_image_url,
                      'https://example.com/test/face/img.jpg')

        # Attempt
        self.assertTrue(
            SoftwareSecurePhotoVerification.delete_by_user_value(user, "user"))
        # Reattempt
        self.assertFalse(
            SoftwareSecurePhotoVerification.delete_by_user_value(user, "user"))