def create_retirement(cls, user): """ Creates a UserRetirementStatus for the given user, in the correct initial state. Will fail if the user already has a UserRetirementStatus row or if states are not yet populated. """ try: pending = RetirementState.objects.all().order_by('state_execution_order')[0] except IndexError: raise RetirementStateError('Default state does not exist! Populate retirement states to retire users.') if cls.objects.filter(user=user).exists(): raise RetirementStateError('User {} already has a retirement status row!'.format(user)) retired_username = get_retired_username_by_username(user.username) retired_email = get_retired_email_by_email(user.email) UserRetirementRequest.create_retirement_request(user) return cls.objects.create( user=user, original_username=user.username, original_email=user.email, original_name=user.profile.name, retired_username=retired_username, retired_email=retired_email, current_state=pending, last_state=pending, responses='Created in state {} by create_retirement'.format(pending) )
def test_get_retired_email(): """ Basic testing of retired emails. """ user = UserFactory() hashed_email = get_retired_email_by_email(user.email) check_email_against_fmt(hashed_email)
def post(self, request): """ POST /api/user/v1/accounts/deactivate_logout Marks the user as having no password set for deactivation purposes, and logs the user out. """ username = request.data.get('user', None) if not username: return Response(status=status.HTTP_404_NOT_FOUND, data={'message': u'The user was not specified.'}) user_model = get_user_model() try: # make sure the specified user exists user = user_model.objects.get(username=username) with transaction.atomic(): # 1. Unlink LMS social auth accounts UserSocialAuth.objects.filter(user_id=user.id).delete() # 2. Change LMS password & email user.email = get_retired_email_by_email(user.email) user.save() _set_unusable_password(user) # 3. Unlink social accounts & change password on each IDA, still to be implemented except user_model.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR) return Response(status=status.HTTP_204_NO_CONTENT)
def test_get_retired_email(): """ Basic testing of retired emails. """ user = UserFactory() hashed_email = get_retired_email_by_email(user.email) check_email_against_fmt(hashed_email)
def post(self, request): """ POST /api/user/v1/accounts/retire/ { 'username': '******' } Retires the user with the given username. This includes retiring this username, the associates email address, and any other PII associated with this user. """ username = request.data['username'] if is_username_retired(username): return Response(status=status.HTTP_404_NOT_FOUND) try: retirement_status = UserRetirementStatus.get_retirement_for_retirement_action(username) user = retirement_status.user retired_username = retirement_status.retired_username or get_retired_username_by_username(username) retired_email = retirement_status.retired_email or get_retired_email_by_email(user.email) original_email = retirement_status.original_email # Retire core user/profile information self.clear_pii_from_userprofile(user) self.delete_users_profile_images(user) self.delete_users_country_cache(user) # Retire data from Enterprise models self.retire_users_data_sharing_consent(username, retired_username) self.retire_sapsf_data_transmission(user) self.retire_user_from_pending_enterprise_customer_user(user, retired_email) self.retire_entitlement_support_detail(user) # Retire misc. models that may contain PII of this user SoftwareSecurePhotoVerification.retire_user(user.id) PendingEmailChange.delete_by_user_value(user, field='user') UserOrgTag.delete_by_user_value(user, field='user') # Retire any objects linked to the user via their original email CourseEnrollmentAllowed.delete_by_user_value(original_email, field='email') UnregisteredLearnerCohortAssignments.delete_by_user_value(original_email, field='email') # TODO: Password Reset links - https://openedx.atlassian.net/browse/PLAT-2104 # TODO: Delete OAuth2 records - https://openedx.atlassian.net/browse/EDUCATOR-2703 user.first_name = '' user.last_name = '' user.is_active = False user.username = retired_username user.save() except UserRetirementStatus.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) except RetirementStateError as exc: return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR) return Response(status=status.HTTP_204_NO_CONTENT)
def post(self, request): """ POST /api/user/v1/accounts/retire/ { 'username': '******' } Retires the user with the given username. This includes retiring this username, the associates email address, and any other PII associated with this user. """ username = request.data['username'] if is_username_retired(username): return Response(status=status.HTTP_404_NOT_FOUND) try: retirement_status = UserRetirementStatus.get_retirement_for_retirement_action(username) user = retirement_status.user retired_username = retirement_status.retired_username or get_retired_username_by_username(username) retired_email = retirement_status.retired_email or get_retired_email_by_email(user.email) original_email = retirement_status.original_email # Retire core user/profile information self.clear_pii_from_userprofile(user) self.delete_users_profile_images(user) self.delete_users_country_cache(user) # Retire data from Enterprise models self.retire_users_data_sharing_consent(username, retired_username) self.retire_sapsf_data_transmission(user) self.retire_user_from_pending_enterprise_customer_user(user, retired_email) self.retire_entitlement_support_detail(user) # Retire misc. models that may contain PII of this user SoftwareSecurePhotoVerification.retire_user(user.id) PendingEmailChange.delete_by_user_value(user, field='user') UserOrgTag.delete_by_user_value(user, field='user') # Retire any objects linked to the user via their original email CourseEnrollmentAllowed.delete_by_user_value(original_email, field='email') UnregisteredLearnerCohortAssignments.delete_by_user_value(original_email, field='email') # TODO: Password Reset links - https://openedx.atlassian.net/browse/PLAT-2104 # TODO: Delete OAuth2 records - https://openedx.atlassian.net/browse/EDUCATOR-2703 user.first_name = '' user.last_name = '' user.is_active = False user.username = retired_username user.save() except UserRetirementStatus.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) except RetirementStateError as exc: return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR) return Response(status=status.HTTP_204_NO_CONTENT)
def test_get_retired_email_status_exists(retirement_user, retirement_status): # pylint: disable=redefined-outer-name """ Checks that a retired email is gotten from a UserRetirementStatus object when one already exists for a user. """ hashed_email = get_retired_email_by_email(retirement_user.email) check_email_against_fmt(hashed_email) assert retirement_status.retired_email == hashed_email
def test_get_retired_email_status_exists(retirement_user, retirement_status): # pylint: disable=redefined-outer-name """ Checks that a retired email is gotten from a UserRetirementStatus object when one already exists for a user. """ hashed_email = get_retired_email_by_email(retirement_user.email) check_email_against_fmt(hashed_email) assert retirement_status.retired_email == hashed_email
def test_retired_email(self): """ Assert the expected error message from the email validation method for an email address that corresponds with an already-retired account. """ user = UserFactory.create(email=self.new_email) user.email = get_retired_email_by_email(self.new_email) user.save() self.assertEqual(self.do_email_validation(self.new_email), 'An account with this e-mail already exists.')
def post(self, request): """ POST /api/user/v1/accounts/retire/ { 'username': '******' } Retires the user with the given username. This includes retiring this username, the associated email address, and any other PII associated with this user. """ username = request.data['username'] try: retirement_status = UserRetirementStatus.get_retirement_for_retirement_action(username) user = retirement_status.user retired_username = retirement_status.retired_username or get_retired_username_by_username(username) retired_email = retirement_status.retired_email or get_retired_email_by_email(user.email) original_email = retirement_status.original_email # Retire core user/profile information self.clear_pii_from_userprofile(user) self.delete_users_profile_images(user) self.delete_users_country_cache(user) # Retire data from Enterprise models self.retire_users_data_sharing_consent(username, retired_username) self.retire_sapsf_data_transmission(user) self.retire_degreed_data_transmission(user) self.retire_user_from_pending_enterprise_customer_user(user, retired_email) self.retire_entitlement_support_detail(user) # Retire misc. models that may contain PII of this user PendingEmailChange.delete_by_user_value(user, field='user') UserOrgTag.delete_by_user_value(user, field='user') # Retire any objects linked to the user via their original email CourseEnrollmentAllowed.delete_by_user_value(original_email, field='email') UnregisteredLearnerCohortAssignments.delete_by_user_value(original_email, field='email') # This signal allows code in higher points of LMS to retire the user as necessary USER_RETIRE_LMS_CRITICAL.send(sender=self.__class__, user=user) user.first_name = '' user.last_name = '' user.is_active = False user.username = retired_username user.save() except UserRetirementStatus.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) except RetirementStateError as exc: return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR) return Response(status=status.HTTP_204_NO_CONTENT)
def test_retired_email(self): """ Assert the expected error message from the email validation method for an email address that corresponds with an already-retired account. """ user = UserFactory.create(email=self.new_email) user.email = get_retired_email_by_email(self.new_email) user.save() self.assertEqual(self.do_email_validation(self.new_email), 'An account with this e-mail already exists.')
def post(self, request): """ POST /api/user/v1/accounts/deactivate_logout/ Marks the user as having no password set for deactivation purposes, and logs the user out. """ user_model = get_user_model() try: # Get the username from the request and check that it exists verify_user_password_response = self._verify_user_password(request) if verify_user_password_response.status_code != status.HTTP_204_NO_CONTENT: return verify_user_password_response with transaction.atomic(): UserRetirementStatus.create_retirement(request.user) # Unlink LMS social auth accounts UserSocialAuth.objects.filter(user_id=request.user.id).delete() # Change LMS password & email user_email = request.user.email request.user.email = get_retired_email_by_email(request.user.email) request.user.save() _set_unusable_password(request.user) # TODO: Unlink social accounts & change password on each IDA. # Remove the activation keys sent by email to the user for account activation. Registration.objects.filter(user=request.user).delete() # Add user to retirement queue. # Delete OAuth tokens associated with the user. retire_dop_oauth2_models(request.user) retire_dot_oauth2_models(request.user) try: # Send notification email to user site = Site.objects.get_current() notification_context = get_base_template_context(site) notification_context.update({'full_name': request.user.profile.name}) notification = DeletionNotificationMessage().personalize( recipient=Recipient(username='', email_address=user_email), language=request.user.profile.language, user_context=notification_context, ) ace.send(notification) except Exception as exc: log.exception('Error sending out deletion notification email') raise # Log the user out. logout(request) return Response(status=status.HTTP_204_NO_CONTENT) except KeyError: return Response(u'Username not specified.', status=status.HTTP_404_NOT_FOUND) except user_model.DoesNotExist: return Response( u'The user "{}" does not exist.'.format(request.user.username), status=status.HTTP_404_NOT_FOUND ) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def test_is_email_retired_is_retired(retirement_user): """ Check functionality of is_email_retired when email is retired """ original_email = retirement_user.email retired_email = get_retired_email_by_email(retirement_user.email) # Fake email retirement. retirement_user.email = retired_email retirement_user.save() assert is_email_retired(original_email)
def _fake_logged_out_user(user, retire_username=False): """ Simulate the initial logout retirement endpoint. """ # By default, do not change the username to the retired hash version because # that is not what happens upon actual retirement requests immediately after # logout. if retire_username: user.username = get_retired_username_by_username(user.username) user.email = get_retired_email_by_email(user.email) user.set_unusable_password() user.save()
def test_is_email_retired_is_retired(retirement_user): """ Check functionality of is_email_retired when email is retired """ original_email = retirement_user.email retired_email = get_retired_email_by_email(retirement_user.email) # Fake email retirement. retirement_user.email = retired_email retirement_user.save() assert is_email_retired(original_email)
def _fake_logged_out_user(user, retire_username=False): """ Simulate the initial logout retirement endpoint. """ # By default, do not change the username to the retired hash version because # that is not what happens upon actual retirement requests immediately after # logout. if retire_username: user.username = get_retired_username_by_username(user.username) user.email = get_retired_email_by_email(user.email) user.set_unusable_password() user.save()
def deactivate_user(user): """ Deactivate and retire the given user """ user_model = get_user_model() try: with transaction.atomic(): UserRetirementStatus.create_retirement(user) # Unlink LMS social auth accounts UserSocialAuth.objects.filter(user_id=user.id).delete() # Change LMS password & email user_email = user.email user.email = get_retired_email_by_email(user.email) user.save() _set_unusable_password(user) # TODO: Unlink social accounts & change password on each IDA. # Remove the activation keys sent by email to the user for account activation. Registration.objects.filter(user=user).delete() # Add user to retirement queue. # Delete OAuth tokens associated with the user. retire_dop_oauth2_models(user) retire_dot_oauth2_models(user) try: # Send notification email to user site = Site.objects.get_current() notification_context = get_base_template_context(site) notification_context.update({'full_name': user.profile.name}) notification_context.update({ 'reset_password_link': urlparse.urljoin( settings.PROGS_URLS.get("ROOT"), settings.PROGS_URLS.get("PROG_RESET_PASSWORD", "reset_password")) }) notification = DeletionNotificationMessage().personalize( recipient=Recipient(username='', email_address=user_email), language=user.profile.language, user_context=notification_context, ) ace.send(notification) except Exception as exc: log.exception('Error sending out deletion notification email') raise return Response(status=status.HTTP_204_NO_CONTENT) except KeyError: return Response(u'Username not specified.', status=status.HTTP_404_NOT_FOUND) except user_model.DoesNotExist: return Response(u'The user "{}" does not exist.'.format(user.username), status=status.HTTP_404_NOT_FOUND) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def test_is_email_retired_is_retired(): """ Check functionality of is_email_retired when email is retired """ user = UserFactory() original_email = user.email retired_email = get_retired_email_by_email(user.email) # Fake email retirement. user.email = retired_email user.save() assert is_email_retired(original_email)
def test_is_email_retired_is_retired(): """ Check functionality of is_email_retired when email is retired """ user = UserFactory() original_email = user.email retired_email = get_retired_email_by_email(user.email) # Fake email retirement. user.email = retired_email user.save() assert is_email_retired(original_email)
def post(self, request): """ POST /api/user/v1/accounts/retire/ { 'username': '******' } Retires the user with the given username. This includes retiring this username, the associates email address, and any other PII associated with this user. """ username = request.data['username'] if is_username_retired(username): return Response(status=status.HTTP_404_NOT_FOUND) try: retirement_status = UserRetirementStatus.get_retirement_for_retirement_action( username) user = retirement_status.user retired_username = retirement_status.retired_username or get_retired_username_by_username( username) retired_email = retirement_status.retired_email or get_retired_email_by_email( user.email) self.clear_pii_from_userprofile(user) self.delete_users_profile_images(user) self.delete_users_country_cache(user) self.retire_users_data_sharing_consent(username, retired_username) self.retire_sapsf_data_transmission(user) self.retire_user_from_pending_enterprise_customer_user( user, retired_email) self.retire_entitlement_support_detail(user) # TODO: Password Reset links - https://openedx.atlassian.net/browse/PLAT-2104 # TODO: Delete OAuth2 records - https://openedx.atlassian.net/browse/EDUCATOR-2703 user.first_name = '' user.last_name = '' user.is_active = False user.username = retired_username user.save() except UserRetirementStatus.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) except RetirementStateError as exc: return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR) return Response(status=status.HTTP_204_NO_CONTENT)
def _assert_retirementstatus_is_user(retirement, user): """ Helper function to compare a newly created UserRetirementStatus object to expected values for the given user. """ pending = RetirementState.objects.all().order_by('state_execution_order')[0] retired_username = get_retired_username_by_username(user.username) retired_email = get_retired_email_by_email(user.email) assert retirement.user == user assert retirement.original_username == user.username assert retirement.original_email == user.email assert retirement.original_name == user.profile.name assert retirement.retired_username == retired_username assert retirement.retired_email == retired_email assert retirement.current_state == pending assert retirement.last_state == pending assert pending.state_name in retirement.responses
def _assert_retirementstatus_is_user(retirement, user): """ Helper function to compare a newly created UserRetirementStatus object to expected values for the given user. """ pending = RetirementState.objects.all().order_by( 'state_execution_order')[0] retired_username = get_retired_username_by_username(user.username) retired_email = get_retired_email_by_email(user.email) assert retirement.user == user assert retirement.original_username == user.username assert retirement.original_email == user.email assert retirement.original_name == user.profile.name assert retirement.retired_username == retired_username assert retirement.retired_email == retired_email assert retirement.current_state == pending assert retirement.last_state == pending assert pending.state_name in retirement.responses
def post(self, request): """ POST /api/user/v1/accounts/deactivate_logout/ Marks the user as having no password set for deactivation purposes, and logs the user out. """ user_model = get_user_model() try: # Get the username from the request and check that it exists verify_user_password_response = self._verify_user_password(request) if verify_user_password_response.status_code != status.HTTP_204_NO_CONTENT: return verify_user_password_response with transaction.atomic(): UserRetirementStatus.create_retirement(request.user) # Unlink LMS social auth accounts UserSocialAuth.objects.filter(user_id=request.user.id).delete() # Change LMS password & email request.user.email = get_retired_email_by_email( request.user.email) request.user.save() _set_unusable_password(request.user) # TODO: Unlink social accounts & change password on each IDA. # Remove the activation keys sent by email to the user for account activation. Registration.objects.filter(user=request.user).delete() # Add user to retirement queue. # Delete OAuth tokens associated with the user. retire_dop_oauth2_models(request.user) retire_dot_oauth2_models(request.user) # Log the user out. logout(request) return Response(status=status.HTTP_204_NO_CONTENT) except KeyError: return Response(u'Username not specified.', status=status.HTTP_404_NOT_FOUND) except user_model.DoesNotExist: return Response(u'The user "{}" does not exist.'.format( request.user.username), status=status.HTTP_404_NOT_FOUND) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def _create_retirement(self, state, create_datetime=None): """ Helper method to create a RetirementStatus with useful defaults """ if create_datetime is None: create_datetime = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=8) user = UserFactory() return UserRetirementStatus.objects.create( user=user, original_username=user.username, original_email=user.email, original_name=user.profile.name, retired_username=get_retired_username_by_username(user.username), retired_email=get_retired_email_by_email(user.email), current_state=state, last_state=state, responses="", created=create_datetime, modified=create_datetime )
def post(self, request): """ POST /api/user/v1/accounts/deactivate_logout/ Marks the user as having no password set for deactivation purposes, and logs the user out. """ user_model = get_user_model() try: # Get the username from the request and check that it exists verify_user_password_response = self._verify_user_password(request) if verify_user_password_response.status_code != status.HTTP_204_NO_CONTENT: return verify_user_password_response with transaction.atomic(): UserRetirementStatus.create_retirement(request.user) # Unlink LMS social auth accounts UserSocialAuth.objects.filter(user_id=request.user.id).delete() # Change LMS password & email request.user.email = get_retired_email_by_email(request.user.email) request.user.save() _set_unusable_password(request.user) # TODO: Unlink social accounts & change password on each IDA. # Remove the activation keys sent by email to the user for account activation. Registration.objects.filter(user=request.user).delete() # Add user to retirement queue. # Delete OAuth tokens associated with the user. retire_dop_oauth2_models(request.user) retire_dot_oauth2_models(request.user) # Log the user out. logout(request) return Response(status=status.HTTP_204_NO_CONTENT) except KeyError: return Response(u'Username not specified.', status=status.HTTP_404_NOT_FOUND) except user_model.DoesNotExist: return Response( u'The user "{}" does not exist.'.format(request.user.username), status=status.HTTP_404_NOT_FOUND ) except Exception as exc: # pylint: disable=broad-except return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def fake_retirement(user): """ Makes an attempt to put user for the given user into a "COMPLETED" retirement state by faking important parts of retirement. Use to test idempotency for retirement API calls. Since there are many configurable retirement steps this is only a "best guess" and may need additional changes added to more accurately reflect post-retirement state. """ # Deactivate / logout and hash username & email UserSocialAuth.objects.filter(user_id=user.id).delete() user.first_name = '' user.last_name = '' user.is_active = False user.username = get_retired_username_by_username(user.username) user.email = get_retired_email_by_email(user.email) user.set_unusable_password() user.save() # Clear profile AccountRetirementView.clear_pii_from_userprofile(user) # Unenroll from all courses api.unenroll_user_from_all_courses(user.username)
def delete_edxapp_user(*args, **kwargs): """ Deletes a user from the platform. """ msg = None user = kwargs.get("user") case_id = kwargs.get("case_id") site = kwargs.get("site") is_support_user = kwargs.get("is_support_user") user_response = "The user {username} <{email}> ".format( username=user.username, email=user.email) signup_sources = user.usersignupsource_set.all() sources = [signup_source.site for signup_source in signup_sources] if site and site.name.upper() in (source.upper() for source in sources): if len(sources) == 1: with transaction.atomic(): support_label = "_support" if is_support_user else "" user.email = "{email}{case}.ednx{support}_retired".format( email=user.email, case=case_id, support=support_label, ) user.save() # Add user to retirement queue. UserRetirementStatus.create_retirement(user) # Unlink LMS social auth accounts UserSocialAuth.objects.filter(user_id=user.id).delete() # Change LMS password & email user.email = get_retired_email_by_email(user.email) user.save() _set_unusable_password(user) # Remove the activation keys sent by email to the user for account activation. Registration.objects.filter(user=user).delete() # Delete OAuth tokens associated with the user. retire_dot_oauth2_models(user) # Delete user signup source object signup_sources[0].delete() msg = "{user} has been removed".format(user=user_response) else: for signup_source in signup_sources: if signup_source.site.upper() == site.name.upper(): signup_source.delete() msg = "{user} has more than one signup source. The signup source from the site {site} has been deleted".format( user=user_response, site=site, ) return msg, status.HTTP_200_OK raise NotFound( "{user} does not have a signup source on the site {site}".format( user=user_response, site=site))
def _fake_logged_out_user(user): # Simulate the initial logout retirement endpoint. user.username = get_retired_username_by_username(user.username) user.email = get_retired_email_by_email(user.email) user.set_unusable_password() user.save()
def password_change_request_handler(request): """Handle password change requests originating from the account page. Uses the Account API to email the user a link to the password reset page. Note: The next step in the password reset process (confirmation) is currently handled by student.views.password_reset_confirm_wrapper, a custom wrapper around Django's password reset confirmation view. Args: request (HttpRequest) Returns: HttpResponse: 200 if the email was sent successfully HttpResponse: 400 if there is no 'email' POST parameter HttpResponse: 403 if the client has been rate limited HttpResponse: 405 if using an unsupported HTTP method Example usage: POST /account/password """ limiter = BadRequestRateLimiter() if limiter.is_rate_limit_exceeded(request): AUDIT_LOG.warning("Password reset rate limit exceeded") return HttpResponseForbidden() user = request.user # Prefer logged-in user's email email = user.email if user.is_authenticated else request.POST.get('email') if email: try: request_password_change(email, request.is_secure()) if is_email_retired(email): email = get_retired_email_by_email(email) user = user if user.is_authenticated else User.objects.get( email=email) destroy_oauth_tokens(user) except UserNotFound: AUDIT_LOG.info("Invalid password reset attempt") # Increment the rate limit counter limiter.tick_bad_request_counter(request) # If enabled, send an email saying that a password reset was attempted, but that there is # no user associated with the email if configuration_helpers.get_value( 'ENABLE_PASSWORD_RESET_FAILURE_EMAIL', settings.FEATURES['ENABLE_PASSWORD_RESET_FAILURE_EMAIL']): site = get_current_site() message_context = get_base_template_context(site) message_context.update({ 'failed': True, 'request': request, # Used by google_analytics_tracking_pixel 'email_address': email, }) msg = PasswordReset().personalize( recipient=Recipient(username='', email_address=email), language=settings.LANGUAGE_CODE, user_context=message_context, ) ace.send(msg) except UserAPIInternalError as err: log.exception( 'Error occured during password change for user {email}: {error}' .format(email=email, error=err)) return HttpResponse(_( "Some error occured during password change. Please try again"), status=500) return HttpResponse(status=200) else: return HttpResponseBadRequest(_("No email address provided."))
def test_get_retired_email(retirement_user): """ Basic testing of retired emails. """ hashed_email = get_retired_email_by_email(retirement_user.email) check_email_against_fmt(hashed_email)
def test_get_retired_email(retirement_user): """ Basic testing of retired emails. """ hashed_email = get_retired_email_by_email(retirement_user.email) check_email_against_fmt(hashed_email)