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_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 self.assertFalse(attempt.retire_user(user_id=user.id)) # No user self.assertFalse(attempt.retire_user(user_id=47))
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 self.assertFalse(attempt.retire_user(user_id=user.id)) # No user self.assertFalse(attempt.retire_user(user_id=47))
def test_retire_user(self): """ Retire user with record(s) in table """ user = UserFactory.create() user.profile.name = "Enrique" attempt = SoftwareSecurePhotoVerification(user=user) # Populate Record attempt.mark_ready() attempt.status = PhotoVerification.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.photo_id_key = 'there_was_an_attempt' attempt.approve() # Validate data before retirement assert attempt.name == user.profile.name assert attempt.photo_id_image_url == 'https://example.com/test/image/img.jpg' assert attempt.face_image_url == 'https://example.com/test/face/img.jpg' assert attempt.photo_id_key == 'there_was_an_attempt' # Retire User attempt_again = SoftwareSecurePhotoVerification(user=user) assert attempt_again.retire_user(user_id=user.id) # Validate data after retirement assert attempt_again.name == '' assert attempt_again.face_image_url == '' assert attempt_again.photo_id_image_url == '' assert attempt_again.photo_id_key == ''
def test_retire_user(self): """ Retire user with record(s) in table """ user = UserFactory.create() user.profile.name = u"Enrique" attempt = SoftwareSecurePhotoVerification(user=user) # Populate Record 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.photo_id_key = 'there_was_an_attempt' attempt.approve() # Validate data before retirement self.assertEqual(attempt.name, user.profile.name) self.assertEqual(attempt.photo_id_image_url, 'https://example.com/test/image/img.jpg') self.assertEqual(attempt.face_image_url, 'https://example.com/test/face/img.jpg') self.assertEqual(attempt.photo_id_key, 'there_was_an_attempt') # Retire User attempt_again = SoftwareSecurePhotoVerification(user=user) self.assertTrue(attempt_again.retire_user(user_id=user.id)) # Validate data after retirement self.assertEqual(attempt_again.name, '') self.assertEqual(attempt_again.face_image_url, '') self.assertEqual(attempt_again.photo_id_image_url, '') self.assertEqual(attempt_again.photo_id_key, '')
def test_retire_user(self): """ Retire user with record(s) in table """ user = UserFactory.create() user.profile.name = u"Enrique" attempt = SoftwareSecurePhotoVerification(user=user) # Populate Record 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.photo_id_key = 'there_was_an_attempt' attempt.approve() # Validate data before retirement self.assertEqual(attempt.name, user.profile.name) self.assertEqual(attempt.photo_id_image_url, 'https://example.com/test/image/img.jpg') self.assertEqual(attempt.face_image_url, 'https://example.com/test/face/img.jpg') self.assertEqual(attempt.photo_id_key, 'there_was_an_attempt') # Retire User attempt_again = SoftwareSecurePhotoVerification(user=user) self.assertTrue(attempt_again.retire_user(user_id=user.id)) # Validate data after retirement self.assertEqual(attempt_again.name, '') self.assertEqual(attempt_again.face_image_url, '') self.assertEqual(attempt_again.photo_id_image_url, '') self.assertEqual(attempt_again.photo_id_key, '')
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_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 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)