def test_update_validation_error_for_enterprise( self, field_name_value, is_enterprise_user, is_synch_learner_profile_data, mock_auth_provider, mock_customer, ): mock_customer.return_value = {} if is_enterprise_user: mock_customer.return_value.update({ 'uuid': 'real-ent-uuid', 'name': 'Dummy Enterprise', 'identity_provider': 'saml-ubc' }) mock_auth_provider.return_value.sync_learner_profile_data = is_synch_learner_profile_data update_data = {field_name_value[0]: field_name_value[1]} # prevent actual email change requests with patch('openedx.core.djangoapps.user_api.accounts.api.student_views.do_email_change_request'): # expect field un-editability only when both of the following conditions are met if is_enterprise_user and is_synch_learner_profile_data: with self.assertRaises(AccountValidationError) as validation_error: update_account_settings(self.user, update_data) field_errors = validation_error.exception.field_errors self.assertEqual( "This field is not editable via this API", field_errors[field_name_value[0]]["developer_message"], ) else: update_account_settings(self.user, update_data) account_settings = get_account_settings(self.default_request)[0] if field_name_value[0] != "email": self.assertEqual(field_name_value[1], account_settings[field_name_value[0]])
def verify_event_emitted(new_value, old_value): """ Confirm that the user setting event was properly emitted """ update_account_settings(self.user, {"language_proficiencies": new_value}) self.assert_user_setting_event_emitted(setting='language_proficiencies', old=old_value, new=new_value) self.reset_tracker()
def test_set_single_social_link(self): social_links = [ dict(platform="facebook", social_link="https://www.facebook.com/{}".format(self.user.username)) ] update_account_settings(self.user, {"social_links": social_links}) account_settings = get_account_settings(self.default_request)[0] self.assertEqual(account_settings['social_links'], social_links)
def test_update_non_existent_user(self): with self.assertRaises(UserNotAuthorized): update_account_settings(self.user, {}, username="******") self.user.username = "******" with self.assertRaises(UserNotFound): update_account_settings(self.user, {})
def test_update_user_not_found(self): """Test that UserNotFound is thrown if there is no user with username.""" with self.assertRaises(UserNotFound): update_account_settings(self.user, {}, username="******") self.user.username = "******" with self.assertRaises(UserNotFound): update_account_settings(self.user, {})
def test_email_changes_disabled(self): """ Test that email address changes are rejected when ALLOW_EMAIL_ADDRESS_CHANGE is not set. """ disabled_update = {"email": "*****@*****.**"} with self.assertRaises(AccountUpdateError) as context_manager: update_account_settings(self.user, disabled_update) self.assertIn("Email address changes have been disabled", context_manager.exception.developer_message)
def test_update_success_for_enterprise(self): EnterpriseCustomerUserFactory(user_id=self.user.id) level_of_education = "m" successful_update = { "level_of_education": level_of_education, } update_account_settings(self.user, successful_update) account_settings = get_account_settings(self.default_request)[0] self.assertEqual(level_of_education, account_settings["level_of_education"])
def test_remove_social_link(self): original_facebook_link = dict(platform="facebook", social_link="https://www.facebook.com/myself") original_twitter_link = dict(platform="twitter", social_link="https://www.twitter.com/myself") update_account_settings(self.user, {"social_links": [original_facebook_link, original_twitter_link]}) removed_facebook_link = dict(platform="facebook", social_link="") update_account_settings(self.user, {"social_links": [removed_facebook_link]}) account_settings = get_account_settings(self.default_request)[0] self.assertEqual(account_settings['social_links'], [original_twitter_link])
def test_update_validation_error_for_enterprise( self, field_name_value, is_enterprise_user, is_synch_learner_profile_data, has_user_social_auth_record, mock_auth_provider, mock_customer, ): idp_backend_name = 'tpa-saml' mock_customer.return_value = {} if is_enterprise_user: mock_customer.return_value.update({ 'uuid': 'real-ent-uuid', 'name': 'Dummy Enterprise', 'identity_provider': 'saml-ubc', 'identity_providers': [{ "provider_id": "saml-ubc", }], }) mock_auth_provider.return_value.sync_learner_profile_data = is_synch_learner_profile_data mock_auth_provider.return_value.backend_name = idp_backend_name update_data = {field_name_value[0]: field_name_value[1]} user_fullname_editable = False if has_user_social_auth_record: UserSocialAuth.objects.create(provider=idp_backend_name, user=self.user) else: UserSocialAuth.objects.all().delete() # user's fullname is editable if no `UserSocialAuth` record exists user_fullname_editable = field_name_value[0] == 'name' # prevent actual email change requests with patch( 'openedx.core.djangoapps.user_api.accounts.api.student_views.do_email_change_request' ): # expect field un-editability only when all of the following conditions are met if is_enterprise_user and is_synch_learner_profile_data and not user_fullname_editable: with pytest.raises(AccountValidationError) as validation_error: update_account_settings(self.user, update_data) field_errors = validation_error.value.field_errors assert 'This field is not editable via this API' ==\ field_errors[field_name_value[0]]['developer_message'] else: update_account_settings(self.user, update_data) account_settings = get_account_settings( self.default_request)[0] if field_name_value[0] != "email": assert field_name_value[1] == account_settings[ field_name_value[0]]
def form_valid(self, form): instance = form.save(commit=False) instance.user = self.request.user instance.course_key = self.get_course_key() instance.save() update_account_settings(self.request.user, { 'name': form.cleaned_data['full_name'], }) return super(UniversityIDView, self).form_valid(form)
def test_set_multiple_social_links(self): social_links = [ dict(platform="facebook", social_link="https://www.facebook.com/{}".format( self.user.username)), dict(platform="twitter", social_link="https://www.twitter.com/{}".format( self.user.username)), ] update_account_settings(self.user, {"social_links": social_links}) account_settings = get_account_settings(self.default_request)[0] self.assertEqual(account_settings['social_links'], social_links)
def test_update_sending_email_fails(self, send_mail): """Test what happens if all validation checks pass, but sending the email for email change fails.""" send_mail.side_effect = [Exception, None] less_naughty_update = { "name": "Mickey Mouse", "email": "*****@*****.**" } with self.assertRaises(AccountUpdateError) as context_manager: update_account_settings(self.user, less_naughty_update) self.assertIn("Error thrown from do_email_change_request", context_manager.exception.developer_message) # Verify that the name change happened, even though the attempt to send the email failed. account_settings = get_account_settings(self.default_request)[0] self.assertEqual("Mickey Mouse", account_settings["name"])
def test_name_update_requires_idv(self): """ Test that a name change is blocked through this API if it requires ID verification. """ with pytest.raises(AccountValidationError) as context_manager: update_account_settings(self.user, {'name': 'New Name'}) field_errors = context_manager.value.field_errors assert len(field_errors) == 1 assert field_errors['name'][ 'developer_message'] == 'This name change requires ID verification.' account_settings = get_account_settings(self.default_request)[0] assert account_settings['name'] != 'New Name'
def test_serializer_save_fails(self, serializer_save): """ Test the behavior of one of the serializers failing to save. Note that email request change won't be processed in this case. """ serializer_save.side_effect = [Exception, None] update_will_fail = {"name": "Mickey Mouse", "email": "*****@*****.**"} with pytest.raises(AccountUpdateError) as context_manager: update_account_settings(self.user, update_will_fail) assert 'Error thrown when saving account updates' in context_manager.value.developer_message # Verify that no email change request was initiated. pending_change = PendingEmailChange.objects.filter(user=self.user) assert 0 == len(pending_change)
def test_add_social_links(self): original_social_links = [ dict(platform="facebook", social_link="https://www.facebook.com/{}".format(self.user.username)) ] update_account_settings(self.user, {"social_links": original_social_links}) extra_social_links = [ dict(platform="twitter", social_link="https://www.twitter.com/{}".format(self.user.username)), dict(platform="linkedin", social_link="https://www.linkedin.com/in/{}".format(self.user.username)), ] update_account_settings(self.user, {"social_links": extra_social_links}) account_settings = get_account_settings(self.default_request)[0] assert account_settings['social_links'] == \ sorted((original_social_links + extra_social_links), key=(lambda s: s['platform']))
def test_remove_social_link(self): original_facebook_link = dict( platform="facebook", social_link="https://www.facebook.com/myself") original_twitter_link = dict( platform="twitter", social_link="https://www.twitter.com/myself") update_account_settings( self.user, {"social_links": [original_facebook_link, original_twitter_link]}) removed_facebook_link = dict(platform="facebook", social_link="") update_account_settings(self.user, {"social_links": [removed_facebook_link]}) account_settings = get_account_settings(self.default_request)[0] assert account_settings['social_links'] == [original_twitter_link]
def test_update_sending_email_fails(self, send_mail): """Test what happens if all validation checks pass, but sending the email for email change fails.""" send_mail.side_effect = [Exception, None] less_naughty_update = { "name": "Mickey Mouse", "email": "*****@*****.**" } with patch('crum.get_current_request', return_value=self.fake_request): with pytest.raises(AccountUpdateError) as context_manager: update_account_settings(self.user, less_naughty_update) assert 'Error thrown from do_email_change_request' in context_manager.value.developer_message # Verify that the name change happened, even though the attempt to send the email failed. account_settings = get_account_settings(self.default_request)[0] assert 'Mickey Mouse' == account_settings['name']
def test_change_country_removes_state(self): ''' Test that changing the country (to something other than a country with states) removes the state ''' # First set the country and state update_account_settings(self.user, {"country": UserProfile.COUNTRY_WITH_STATES, "state": "MA"}) account_settings = get_account_settings(self.default_request)[0] assert account_settings['country'] == UserProfile.COUNTRY_WITH_STATES assert account_settings['state'] == 'MA' # Change the country and check that state is removed update_account_settings(self.user, {"country": ""}) account_settings = get_account_settings(self.default_request)[0] assert account_settings['country'] is None assert account_settings['state'] is None
def test_replace_social_links(self): original_facebook_link = dict( platform="facebook", social_link="https://www.facebook.com/myself") original_twitter_link = dict( platform="twitter", social_link="https://www.twitter.com/myself") update_account_settings( self.user, {"social_links": [original_facebook_link, original_twitter_link]}) modified_facebook_link = dict( platform="facebook", social_link="https://www.facebook.com/new_me") update_account_settings(self.user, {"social_links": [modified_facebook_link]}) account_settings = get_account_settings(self.default_request)[0] self.assertEqual(account_settings['social_links'], [modified_facebook_link, original_twitter_link])
def test_add_social_links(self): original_social_links = [ dict(platform="facebook", social_link="https://www.facebook.com/{}".format(self.user.username)) ] update_account_settings(self.user, {"social_links": original_social_links}) extra_social_links = [ dict(platform="twitter", social_link="https://www.twitter.com/{}".format(self.user.username)), dict(platform="linkedin", social_link="https://www.linkedin.com/in/{}".format(self.user.username)), ] update_account_settings(self.user, {"social_links": extra_social_links}) account_settings = get_account_settings(self.default_request)[0] self.assertEqual( account_settings['social_links'], sorted(original_social_links + extra_social_links, key=lambda s: s['platform']), )
def form_valid(self, form): instance = form.save(commit=False) instance.user = self.request.user instance.course_key = self.get_course_key() instance.cohort = form.cleaned_data['cohort'] instance.save() update_account_settings(self.request.user, { 'name': form.cleaned_data['full_name'], }) try: add_user_to_cohort(instance.cohort, instance.user.email) except ValueError: # User already present in the cohort pass return super(UniversityIDView, self).form_valid(form)
def test_serializer_save_fails(self, serializer_save): """ Test the behavior of one of the serializers failing to save. Note that email request change won't be processed in this case. """ serializer_save.side_effect = [Exception, None] update_will_fail = { "name": "Mickey Mouse", "email": "*****@*****.**" } with self.assertRaises(AccountUpdateError) as context_manager: update_account_settings(self.user, update_will_fail) self.assertIn("Error thrown when saving account updates", context_manager.exception.developer_message) # Verify that no email change request was initiated. pending_change = PendingEmailChange.objects.filter(user=self.user) self.assertEqual(0, len(pending_change))
def test_update_multiple_validation_errors(self): """Test that all validation errors are built up and returned at once""" # Send a read-only error, serializer error, and email validation error. naughty_update = { "username": "******", "gender": "undecided", "email": "not an email address", "name": "<p style=\"font-size:300px; color:green;\"></br>Name<input type=\"text\"></br>Content spoof" } with pytest.raises(AccountValidationError) as context_manager: update_account_settings(self.user, naughty_update) field_errors = context_manager.value.field_errors assert 4 == len(field_errors) assert 'This field is not editable via this API' == field_errors['username']['developer_message'] assert "Value 'undecided' is not valid for field 'gender'" in field_errors['gender']['developer_message'] assert 'Valid e-mail address required.' in field_errors['email']['developer_message'] assert 'Full Name cannot contain the following characters: < >' in field_errors['name']['user_message']
def test_update_multiple_validation_errors(self): """Test that all validation errors are built up and returned at once""" # Send a read-only error, serializer error, and email validation error. naughty_update = { "username": "******", "gender": "undecided", "email": "not an email address" } with self.assertRaises(AccountValidationError) as context_manager: update_account_settings(self.user, naughty_update) field_errors = context_manager.exception.field_errors self.assertEqual(3, len(field_errors)) self.assertEqual("This field is not editable via this API", field_errors["username"]["developer_message"]) self.assertIn("Value \'undecided\' is not valid for field \'gender\'", field_errors["gender"]["developer_message"]) self.assertIn("Valid e-mail address required.", field_errors["email"]["developer_message"])
def test_update_multiple_validation_errors(self): """Test that all validation errors are built up and returned at once""" # Send a read-only error, serializer error, and email validation error. naughty_update = { "username": "******", "gender": "undecided", "email": "not an email address" } with self.assertRaises(AccountValidationError) as context_manager: update_account_settings(self.user, naughty_update) field_errors = context_manager.exception.field_errors self.assertEqual(3, len(field_errors)) self.assertEqual("This field is not editable via this API", field_errors["username"]["developer_message"]) self.assertIn( "Value \'undecided\' is not valid for field \'gender\'", field_errors["gender"]["developer_message"] ) self.assertIn("Valid e-mail address required.", field_errors["email"]["developer_message"])
def _update_full_name(self, user, full_name): """ Update the user's full name. Arguments: user (User): The user to update. full_name (unicode): The user's updated full name. Returns: HttpResponse or None """ try: update_account_settings(user, {"name": full_name}) except UserNotFound: return HttpResponseBadRequest(_("No profile found for user")) except AccountValidationError: msg = _("Name must be at least {min_length} characters long." ).format(min_length=NAME_MIN_LENGTH) return HttpResponseBadRequest(msg)
def test_email_changes_blocked_on_retired_email(self): """ Test that email address changes are rejected when an email associated with a *partially* retired account is specified. """ # First, record the original email addres of the primary user (the one seeking to update their email). original_email = self.user.email # Setup a partially retired user. This user recently submitted a deletion request, but it has not been # processed yet. partially_retired_email = '*****@*****.**' partially_retired_user = UserFactory(email=partially_retired_email) fake_requested_retirement(partially_retired_user) # Attempt to change email to the one of the partially retired user. rejected_update = {'email': partially_retired_email} update_account_settings(self.user, rejected_update) # No error should be thrown, and we need to check that the email update was skipped. assert self.user.email == original_email
def _update_full_name(self, user, full_name): """ Update the user's full name. Arguments: user (User): The user to update. full_name (unicode): The user's updated full name. Returns: HttpResponse or None """ try: update_account_settings(user, {"name": full_name}) except UserNotFound: return HttpResponseBadRequest(_("No profile found for user")) except AccountValidationError: msg = _( "Name must be at least {min_length} characters long." ).format(min_length=NAME_MIN_LENGTH) return HttpResponseBadRequest(msg)
def form_valid(self, form): """ A hook to set the course_key, set the cohort and the profile.name. """ if is_student_form_disabled(self.request.user, self.get_course_key()): # Don't allow saving the disabled form return self.form_invalid(form) instance = form.save(commit=False) instance.user = self.request.user instance.course_key = self.get_course_key() instance.save() update_account_settings(self.request.user, { 'name': form.cleaned_data['full_name'], }) cohort = CourseUserGroup.objects.get(pk=form.cleaned_data['cohort']) instance.set_cohort(cohort) return super(UniversityIDView, self).form_valid(form)
def test_update_validation_error_for_enterprise( self, field_name_value, is_enterprise_user, is_synch_learner_profile_data, mock_auth_provider, mock_customer, ): mock_customer.return_value = {} if is_enterprise_user: mock_customer.return_value.update({ 'uuid': 'real-ent-uuid', 'name': 'Dummy Enterprise', 'identity_provider': 'saml-ubc' }) mock_auth_provider.return_value.sync_learner_profile_data = is_synch_learner_profile_data update_data = {field_name_value[0]: field_name_value[1]} # prevent actual email change requests with patch( 'openedx.core.djangoapps.user_api.accounts.api.student_views.do_email_change_request' ): # expect field un-editability only when both of the following conditions are met if is_enterprise_user and is_synch_learner_profile_data: with self.assertRaises( AccountValidationError) as validation_error: update_account_settings(self.user, update_data) field_errors = validation_error.exception.field_errors self.assertEqual( "This field is not editable via this API", field_errors[field_name_value[0]]["developer_message"], ) else: update_account_settings(self.user, update_data) account_settings = get_account_settings( self.default_request)[0] if field_name_value[0] != "email": self.assertEqual(field_name_value[1], account_settings[field_name_value[0]])
def test_update_multiple_validation_errors(self): """Test that all validation errors are built up and returned at once""" # Send a read-only error, serializer error, and email validation error. naughty_update = { "username": "******", "gender": "undecided", "email": "not an email address", "name": "<p style=\"font-size:300px; color:green;\"></br>Name<input type=\"text\"></br>Content spoof" } with self.assertRaises(AccountValidationError) as context_manager: update_account_settings(self.user, naughty_update) field_errors = context_manager.exception.field_errors self.assertEqual(4, len(field_errors)) self.assertEqual("This field is not editable via this API", field_errors["username"]["developer_message"]) self.assertIn( "Value \'undecided\' is not valid for field \'gender\'", field_errors["gender"]["developer_message"] ) self.assertIn("Valid e-mail address required.", field_errors["email"]["developer_message"]) self.assertIn("Full Name cannot contain the following characters: < >", field_errors["name"]["user_message"])
def test_name_update_does_not_require_idv(self, has_passable_cert, enrolled_in_verified_mode): """ Test that the user can change their name if change does not require IDV. """ with patch('openedx.core.djangoapps.user_api.accounts.api.get_certificates_for_user') as mock_get_certs,\ patch('openedx.core.djangoapps.user_api.accounts.api.get_verified_enrollments') as \ mock_get_verified_enrollments: mock_get_certs.return_value = ([{ 'status': CertificateStatuses.downloadable }] if has_passable_cert else [{ 'status': CertificateStatuses.unverified }]) mock_get_verified_enrollments.return_value = [{ 'name': 'Bob' }] if enrolled_in_verified_mode else [] update_account_settings(self.user, {'name': 'New Name'}) account_settings = get_account_settings(self.default_request)[0] assert account_settings['name'] == 'New Name'
def test_add_account_recovery(self): test_email = "*****@*****.**" pending_secondary_email_changes = PendingSecondaryEmailChange.objects.filter(user=self.user) self.assertEqual(0, len(pending_secondary_email_changes)) account_recovery_objects = AccountRecovery.objects.filter(user=self.user) self.assertEqual(0, len(account_recovery_objects)) with patch('crum.get_current_request', return_value=self.fake_request): update = {"secondary_email": test_email} update_account_settings(self.user, update) pending_secondary_email_change = PendingSecondaryEmailChange.objects.get(user=self.user) self.assertIsNot(pending_secondary_email_change, None) self.assertEqual(pending_secondary_email_change.new_secondary_email, test_email) activate_secondary_email(self.fake_request, pending_secondary_email_change.activation_key) pending_secondary_email_changes = PendingSecondaryEmailChange.objects.filter(user=self.user) self.assertEqual(0, len(pending_secondary_email_changes)) account_recovery = AccountRecovery.objects.get(user=self.user) self.assertIsNot(account_recovery, None) self.assertEqual(account_recovery.secondary_email, test_email)
def test_add_account_recovery(self): test_email = "*****@*****.**" pending_secondary_email_changes = PendingSecondaryEmailChange.objects.filter(user=self.user) assert 0 == len(pending_secondary_email_changes) account_recovery_objects = AccountRecovery.objects.filter(user=self.user) assert 0 == len(account_recovery_objects) with patch('crum.get_current_request', return_value=self.fake_request): update = {"secondary_email": test_email} update_account_settings(self.user, update) pending_secondary_email_change = PendingSecondaryEmailChange.objects.get(user=self.user) assert pending_secondary_email_change is not None assert pending_secondary_email_change.new_secondary_email == test_email activate_secondary_email(self.fake_request, pending_secondary_email_change.activation_key) pending_secondary_email_changes = PendingSecondaryEmailChange.objects.filter(user=self.user) assert 0 == len(pending_secondary_email_changes) account_recovery = AccountRecovery.objects.get(user=self.user) assert account_recovery is not None assert account_recovery.secondary_email == test_email
def test_update_username_provided(self): """Test the difference in behavior when a username is supplied to update_account_settings.""" update_account_settings(self.user, {"name": "Mickey Mouse"}) account_settings = get_account_settings(self.default_request)[0] assert 'Mickey Mouse' == account_settings['name'] update_account_settings(self.user, {"name": "Donald Duck"}, username=self.user.username) account_settings = get_account_settings(self.default_request)[0] assert 'Donald Duck' == account_settings['name'] with pytest.raises(UserNotAuthorized): update_account_settings(self.different_user, {"name": "Pluto"}, username=self.user.username)
def test_update_username_provided(self): """Test the difference in behavior when a username is supplied to update_account_settings.""" update_account_settings(self.user, {"name": "Mickey Mouse"}) account_settings = get_account_settings(self.default_request)[0] self.assertEqual("Mickey Mouse", account_settings["name"]) update_account_settings(self.user, {"name": "Donald Duck"}, username=self.user.username) account_settings = get_account_settings(self.default_request)[0] self.assertEqual("Donald Duck", account_settings["name"]) with self.assertRaises(UserNotAuthorized): update_account_settings(self.different_user, {"name": "Pluto"}, username=self.user.username)
def test_update_error_validating(self): """Test that AccountValidationError is thrown if incorrect values are supplied.""" with self.assertRaises(AccountValidationError): update_account_settings(self.user, {"username": "******"}) with self.assertRaises(AccountValidationError): update_account_settings(self.user, {"gender": "undecided"}) with self.assertRaises(AccountValidationError): update_account_settings( self.user, {"profile_image": {"has_image": "not_allowed", "image_url": "not_allowed"}} ) # Check the various language_proficiencies validation failures. # language_proficiencies must be a list of dicts, each containing a # unique 'code' key representing the language code. with self.assertRaises(AccountValidationError): update_account_settings( self.user, {"language_proficiencies": "not_a_list"} ) with self.assertRaises(AccountValidationError): update_account_settings( self.user, {"language_proficiencies": [{}]} ) with self.assertRaises(AccountValidationError): update_account_settings(self.user, {"account_privacy": ""})
def test_unsupported_social_link_platform(self): social_links = [ dict(platform="unsupported", social_link="https://www.unsupported.com/{}".format(self.user.username)) ] with self.assertRaises(AccountUpdateError): update_account_settings(self.user, {"social_links": social_links})
def test_unsupported_social_link_platform(self): social_links = [ dict(platform="unsupported", social_link=f"https://www.unsupported.com/{self.user.username}") ] with pytest.raises(AccountValidationError): update_account_settings(self.user, {"social_links": social_links})
def submit_photos_for_verification(request): """Submit a photo verification attempt. Arguments: request (HttpRequest): The request to submit photos. Returns: HttpResponse: 200 on success, 400 if there are errors. """ # Check the required parameters missing_params = set(['face_image', 'photo_id_image']) - set(request.POST.keys()) if len(missing_params) > 0: msg = _("Missing required parameters: {missing}").format(missing=", ".join(missing_params)) return HttpResponseBadRequest(msg) # If the user already has valid or pending request, the UI will hide # the verification steps. For this reason, we reject any requests # for users that already have a valid or pending verification. if SoftwareSecurePhotoVerification.user_has_valid_or_pending(request.user): return HttpResponseBadRequest(_("You already have a valid or pending verification.")) # If the user wants to change his/her full name, # then try to do that before creating the attempt. if request.POST.get('full_name'): try: update_account_settings(request.user, {"name": request.POST.get('full_name')}) except UserNotFound: return HttpResponseBadRequest(_("No profile found for user")) except AccountValidationError: msg = _( "Name must be at least {min_length} characters long." ).format(min_length=NAME_MIN_LENGTH) return HttpResponseBadRequest(msg) # Create the attempt attempt = SoftwareSecurePhotoVerification(user=request.user) try: b64_face_image = request.POST['face_image'].split(",")[1] b64_photo_id_image = request.POST['photo_id_image'].split(",")[1] except IndexError: msg = _("Image data is not valid.") return HttpResponseBadRequest(msg) attempt.upload_face_image(b64_face_image.decode('base64')) attempt.upload_photo_id_image(b64_photo_id_image.decode('base64')) attempt.mark_ready() attempt.submit() account_settings = get_account_settings(request.user) # Send a confirmation email to the user context = { 'full_name': account_settings['name'], 'platform_name': settings.PLATFORM_NAME } subject = _("Verification photos received") message = render_to_string('emails/photo_submission_confirmation.txt', context) from_address = microsite.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL) to_address = account_settings['email'] send_mail(subject, message, from_address, [to_address], fail_silently=False) return HttpResponse(200)