def test_change_email(self): response = self._change_email(self.NEW_EMAIL, self.OLD_PASSWORD) self.assertEquals(response.status_code, 200) # Verify that the email associated with the account remains unchanged profile_info = profile_api.profile_info(self.USERNAME) self.assertEquals(profile_info['email'], self.OLD_EMAIL) # Check that an email was sent with the activation key self.assertEqual(len(mail.outbox), 1) self._assert_email( mail.outbox[0], [self.NEW_EMAIL], u"Email Change Request", u"There was recently a request to change the email address") # Retrieve the activation key from the email email_body = mail.outbox[0].body result = re.search('/email/confirmation/([^ \n]+)', email_body) self.assertIsNot(result, None) activation_key = result.group(1) # Attempt to activate the email response = self.client.get( reverse('email_change_confirm', kwargs={'key': activation_key})) self.assertEqual(response.status_code, 200) # Verify that the email was changed profile_info = profile_api.profile_info(self.USERNAME) self.assertEquals(profile_info['email'], self.NEW_EMAIL) # Verify that notification emails were sent self.assertEqual(len(mail.outbox), 2) self._assert_email(mail.outbox[1], [self.OLD_EMAIL, self.NEW_EMAIL], u"Email Change Successful", u"You successfully changed the email address")
def test_name_change(self): # Verify that the name on the account is blank profile_info = profile_api.profile_info(self.USERNAME) self.assertEqual(profile_info['full_name'], '') response = self._change_name(self.FULL_NAME) self.assertEqual(response.status_code, 204) # Verify that the name on the account has been changed profile_info = profile_api.profile_info(self.USERNAME) self.assertEqual(profile_info['full_name'], self.FULL_NAME)
def test_email_change_confirmation_invalid_key(self): # Visit the confirmation page with an invalid key response = self.client.get(reverse('email_change_confirm', kwargs={'key': self.INVALID_KEY})) self.assertContains(response, "Something went wrong") # Verify that the email associated with the account has not changed profile_info = profile_api.profile_info(self.USERNAME) self.assertEquals(profile_info['email'], self.OLD_EMAIL)
def test_email_change_confirmation_invalid_key(self): # Visit the confirmation page with an invalid key response = self.client.get( reverse('email_change_confirm', kwargs={'key': self.INVALID_KEY})) self.assertContains(response, "Something went wrong") # Verify that the email associated with the account has not changed profile_info = profile_api.profile_info(self.USERNAME) self.assertEquals(profile_info['email'], self.OLD_EMAIL)
def test_email_change_confirmation(self): # Get an email change activation key activation_key = account_api.request_email_change(self.USERNAME, self.NEW_EMAIL, self.OLD_PASSWORD) # Follow the link sent in the confirmation email response = self.client.get(reverse('email_change_confirm', kwargs={'key': activation_key})) self.assertContains(response, "Email change successful") # Verify that the email associated with the account has changed profile_info = profile_api.profile_info(self.USERNAME) self.assertEquals(profile_info['email'], self.NEW_EMAIL)
def test_change_email(self): response = self._change_email(self.NEW_EMAIL, self.OLD_PASSWORD) self.assertEquals(response.status_code, 200) # Verify that the email associated with the account remains unchanged profile_info = profile_api.profile_info(self.USERNAME) self.assertEquals(profile_info['email'], self.OLD_EMAIL) # Check that an email was sent with the activation key self.assertEqual(len(mail.outbox), 1) self._assert_email( mail.outbox[0], [self.NEW_EMAIL], u"Email Change Request", u"There was recently a request to change the email address" ) # Retrieve the activation key from the email email_body = mail.outbox[0].body result = re.search('/email/confirmation/([^ \n]+)', email_body) self.assertIsNot(result, None) activation_key = result.group(1) # Attempt to activate the email response = self.client.get(reverse('email_change_confirm', kwargs={'key': activation_key})) self.assertEqual(response.status_code, 200) # Verify that the email was changed profile_info = profile_api.profile_info(self.USERNAME) self.assertEquals(profile_info['email'], self.NEW_EMAIL) # Verify that notification emails were sent self.assertEqual(len(mail.outbox), 2) self._assert_email( mail.outbox[1], [self.OLD_EMAIL, self.NEW_EMAIL], u"Email Change Successful", u"You successfully changed the email address" )
def test_email_change_confirmation(self): # Get an email change activation key activation_key = account_api.request_email_change( self.USERNAME, self.NEW_EMAIL, self.OLD_PASSWORD) # Follow the link sent in the confirmation email response = self.client.get( reverse('email_change_confirm', kwargs={'key': activation_key})) self.assertContains(response, "Email change successful") # Verify that the email associated with the account has changed profile_info = profile_api.profile_info(self.USERNAME) self.assertEquals(profile_info['email'], self.NEW_EMAIL)
def test_email_change_confirmation_email_already_exists(self): # Get an email change activation key email_activation_key = account_api.request_email_change(self.USERNAME, self.NEW_EMAIL, self.OLD_PASSWORD) # Create/activate a second user with the new email account_activation_key = account_api.create_account(self.ALTERNATE_USERNAME, self.OLD_PASSWORD, self.NEW_EMAIL) account_api.activate_account(account_activation_key) # Follow the link sent to the original user response = self.client.get(reverse('email_change_confirm', kwargs={'key': email_activation_key})) self.assertContains(response, "address you wanted to use is already used") # Verify that the email associated with the original account has not changed profile_info = profile_api.profile_info(self.USERNAME) self.assertEquals(profile_info['email'], self.OLD_EMAIL)
def test_email_change_confirmation_email_already_exists(self): # Get an email change activation key email_activation_key = account_api.request_email_change( self.USERNAME, self.NEW_EMAIL, self.OLD_PASSWORD) # Create/activate a second user with the new email account_activation_key = account_api.create_account( self.ALTERNATE_USERNAME, self.OLD_PASSWORD, self.NEW_EMAIL) account_api.activate_account(account_activation_key) # Follow the link sent to the original user response = self.client.get( reverse('email_change_confirm', kwargs={'key': email_activation_key})) self.assertContains(response, "address you wanted to use is already used") # Verify that the email associated with the original account has not changed profile_info = profile_api.profile_info(self.USERNAME) self.assertEquals(profile_info['email'], self.OLD_EMAIL)
def email_change_request_handler(request): """Handle a request to change the user's email address. Sends an email to the newly specified address containing a link to a confirmation page. Args: request (HttpRequest) Returns: HttpResponse: 200 if the confirmation email was sent successfully HttpResponse: 302 if not logged in (redirect to login page) HttpResponse: 400 if the format of the new email is incorrect, or if an email change is requested for a user which does not exist HttpResponse: 401 if the provided password (in the form) is incorrect HttpResponse: 405 if using an unsupported HTTP method HttpResponse: 409 if the provided email is already in use Example usage: POST /account/email """ username = request.user.username password = request.POST.get('password') new_email = request.POST.get('email') if new_email is None: return HttpResponseBadRequest("Missing param 'email'") if password is None: return HttpResponseBadRequest("Missing param 'password'") old_email = profile_api.profile_info(username)['email'] try: key = account_api.request_email_change(username, new_email, password) except (account_api.AccountEmailInvalid, account_api.AccountUserNotFound): return HttpResponseBadRequest() except account_api.AccountEmailAlreadyExists: return HttpResponse(status=409) except account_api.AccountNotAuthorized: return HttpResponse(status=401) context = { 'key': key, 'old_email': old_email, 'new_email': new_email, } subject = render_to_string('student_account/emails/email_change_request/subject_line.txt', context) subject = ''.join(subject.splitlines()) message = render_to_string('student_account/emails/email_change_request/message_body.txt', context) from_address = microsite.get_value( 'email_from_address', settings.DEFAULT_FROM_EMAIL ) # Send a confirmation email to the new address containing the activation key send_mail(subject, message, from_address, [new_email]) return HttpResponse(status=200)
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.")) username = request.user.username # 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: profile_api.update_profile( username, full_name=request.POST.get('full_name') ) except profile_api.ProfileUserNotFound: return HttpResponseBadRequest(_("No profile found for user")) except profile_api.ProfileInvalidField: msg = _( "Name must be at least {min_length} characters long." ).format(min_length=profile_api.FULL_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() profile_dict = profile_api.profile_info(username) if profile_dict: # Send a confirmation email to the user context = { 'full_name': profile_dict.get('full_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 = profile_dict.get('email') send_mail(subject, message, from_address, [to_address], fail_silently=False) return HttpResponse(200)
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.")) username = request.user.username # 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: profile_api.update_profile(username, full_name=request.POST.get('full_name')) except profile_api.ProfileUserNotFound: return HttpResponseBadRequest(_("No profile found for user")) except profile_api.ProfileInvalidField: msg = _("Name must be at least {min_length} characters long." ).format(min_length=profile_api.FULL_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() profile_dict = profile_api.profile_info(username) if profile_dict: # Send a confirmation email to the user context = { 'full_name': profile_dict.get('full_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 = profile_dict.get('email') send_mail(subject, message, from_address, [to_address], fail_silently=False) return HttpResponse(200)