Merge pull request #28688 from edx/ashultz0/idv-submitted-name

Do not immediately update profile name from IDV when name affirmation is on
This commit is contained in:
Andrew Shultz
2021-09-10 09:07:22 -04:00
committed by GitHub
4 changed files with 53 additions and 21 deletions

View File

@@ -398,10 +398,10 @@ class PhotoVerification(IDVerificationAttempt):
they uploaded are good. Note that we don't actually do a submission
anywhere yet.
"""
# At any point prior to this, they can change their names via their
# student dashboard. But at this point, we lock the value into the
# attempt.
self.name = self.user.profile.name # pylint: disable=no-member
# If a name is not already set via the verified_name flow,
# pick up the profile name at this time.
if not self.name:
self.name = self.user.profile.name # pylint: disable=no-member
self.status = self.STATUS.ready
self.save()

View File

@@ -185,6 +185,20 @@ class TestPhotoVerification(TestVerificationBase, MockS3BotoMixin, ModuleStoreTe
assert 'Clyde ƴ' == attempt.name
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
def test_submissions(self):
"""Test that we set our status correctly after a submission."""
# Basic case, things go well.

View File

@@ -21,8 +21,9 @@ from django.test.client import Client, RequestFactory
from django.test.utils import override_settings
from django.urls import reverse
from django.utils.timezone import now
from edx_name_affirmation.toggles import VERIFIED_NAME_FLAG
from opaque_keys.edx.locator import CourseLocator
from waffle.testutils import override_switch
from waffle.testutils import override_flag, override_switch
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
@@ -1256,16 +1257,22 @@ class TestSubmitPhotosForVerification(MockS3BotoMixin, TestVerificationBase):
# Verify that the user's name wasn't changed
self._assert_user_name(self.user.profile.name)
def test_submit_photos_and_change_name(self):
# Submit the photos, along with a name change
self._submit_photos(
face_image=self.IMAGE_DATA,
photo_id_image=self.IMAGE_DATA,
full_name=self.FULL_NAME
)
@ddt.data(True, False)
def test_submit_photos_and_change_name(self, flag_on):
with override_flag(VERIFIED_NAME_FLAG.name, flag_on):
# Submit the photos, along with a name change
self._submit_photos(
face_image=self.IMAGE_DATA,
photo_id_image=self.IMAGE_DATA,
full_name=self.FULL_NAME
)
# Check that the user's name was changed in the database
self._assert_user_name(self.FULL_NAME)
# Check that the user's name was changed in the database if verified_name is off
self._assert_user_name(self.FULL_NAME, equality=not flag_on)
# Since we are giving a full name, it should be written into the attempt
# whether or not the user name was updated
attempt = SoftwareSecurePhotoVerification.objects.get(user=self.user)
self.assertEqual(attempt.name, self.FULL_NAME)
def test_submit_photos_sends_confirmation_email(self):
self._submit_photos(
@@ -1479,7 +1486,7 @@ class TestSubmitPhotosForVerification(MockS3BotoMixin, TestVerificationBase):
# Verify that photo submission confirmation email was not sent
assert len(mail.outbox) == 0
def _assert_user_name(self, full_name):
def _assert_user_name(self, full_name, equality=True):
"""Check the user's name.
Arguments:
@@ -1492,7 +1499,10 @@ class TestSubmitPhotosForVerification(MockS3BotoMixin, TestVerificationBase):
request = RequestFactory().get('/url')
request.user = self.user
account_settings = get_account_settings(request)[0]
assert account_settings['name'] == full_name
if equality:
assert account_settings['name'] == full_name
else:
assert not account_settings['name'] == full_name
def _get_post_data(self):
"""Retrieve POST data from the last request. """

View File

@@ -21,6 +21,7 @@ from django.utils.translation import ugettext_lazy
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.views.generic.base import View
from edx_name_affirmation.toggles import is_verified_name_enabled
from edx_rest_api_client.exceptions import SlumberBaseException
from ipware.ip import get_client_ip
from opaque_keys.edx.keys import CourseKey
@@ -845,9 +846,13 @@ class SubmitPhotosView(View):
if response is not None:
return response
# If necessary, update the user's full name
full_name = None
if "full_name" in params:
response = self._update_full_name(request, params["full_name"])
full_name = params["full_name"]
# If necessary, update the user's full name
if full_name is not None and not is_verified_name_enabled():
response = self._update_full_name(request, full_name)
if response is not None:
return response
@@ -866,7 +871,7 @@ class SubmitPhotosView(View):
return response
# Submit the attempt
attempt = self._submit_attempt(request.user, face_image, photo_id_image, initial_verification)
attempt = self._submit_attempt(request.user, face_image, photo_id_image, initial_verification, full_name)
# Send event to segment for analyzing A/B testing data
data = {
@@ -948,7 +953,7 @@ class SubmitPhotosView(View):
full_name (unicode): The user's updated full name.
Returns:
HttpResponse or None
error encoded as an HttpResponse or None indicating success
"""
try:
@@ -1018,7 +1023,7 @@ class SubmitPhotosView(View):
log.error(("Image data for user {user_id} is not valid").format(user_id=request.user.id))
return None, None, HttpResponseBadRequest(msg)
def _submit_attempt(self, user, face_image, photo_id_image=None, initial_verification=None):
def _submit_attempt(self, user, face_image, photo_id_image=None, initial_verification=None, provided_name=None):
"""
Submit a verification attempt.
@@ -1029,8 +1034,11 @@ class SubmitPhotosView(View):
Keyword Arguments:
photo_id_image (str or None): Decoded photo ID image data.
initial_verification (SoftwareSecurePhotoVerification): The initial verification attempt.
provided_name (str or None): full name given by user for this attempt
"""
attempt = SoftwareSecurePhotoVerification(user=user)
if provided_name:
attempt.name = provided_name
# We will always have face image data, so upload the face image
attempt.upload_face_image(face_image)