def test_one_story_is_pseudonymized_when_the_deletion_is_repeated(self): wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) # Return metadata model to the original user ID. metadata_model = story_models.StorySnapshotMetadataModel.get_by_id( '%s-1' % self.STORY_1_ID) metadata_model.committer_id = self.user_1_id metadata_model.put() # Run the user deletion again. wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) # Verify that both the commit and the metadata have the same # pseudonymous user ID. pending_deletion_model = ( user_models.PendingDeletionRequestModel.get_by_id(self.user_1_id)) metadata_model = story_models.StorySnapshotMetadataModel.get_by_id( '%s-1' % self.STORY_1_ID) self.assertEqual( metadata_model.committer_id, pending_deletion_model.story_mappings[self.STORY_1_ID]) commit_log_model = story_models.StoryCommitLogEntryModel.get_by_id( 'story-%s-1' % self.STORY_1_ID) self.assertEqual( commit_log_model.user_id, pending_deletion_model.story_mappings[self.STORY_1_ID])
def test_one_story_with_multiple_users_is_pseudonymized(self): story_services.update_story(self.user_2_id, self.STORY_1_ID, [ story_domain.StoryChange({ 'cmd': story_domain.CMD_ADD_STORY_NODE, 'node_id': 'node_1', 'title': 'Title 2' }) ], 'Add node.') wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) # Verify first user is deleted. pending_deletion_model = ( user_models.PendingDeletionRequestModel.get_by_id(self.user_1_id)) metadata_model = story_models.StorySnapshotMetadataModel.get_by_id( '%s-1' % self.STORY_1_ID) self.assertEqual( metadata_model.committer_id, pending_deletion_model.story_mappings[self.STORY_1_ID]) commit_log_model = story_models.StoryCommitLogEntryModel.get_by_id( 'story-%s-1' % self.STORY_1_ID) self.assertEqual( commit_log_model.user_id, pending_deletion_model.story_mappings[self.STORY_1_ID]) # Verify second user is not yet deleted. metadata_model = story_models.StorySnapshotMetadataModel.get_by_id( '%s-2' % self.STORY_1_ID) self.assertEqual(metadata_model.committer_id, self.user_2_id) commit_log_model = story_models.StoryCommitLogEntryModel.get_by_id( 'story-%s-2' % self.STORY_1_ID) self.assertEqual(commit_log_model.user_id, self.user_2_id) wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_2_id)) # Verify second user is deleted. pending_deletion_model = ( user_models.PendingDeletionRequestModel.get_by_id(self.user_2_id)) metadata_model = story_models.StorySnapshotMetadataModel.get_by_id( '%s-2' % self.STORY_1_ID) self.assertEqual( metadata_model.committer_id, pending_deletion_model.story_mappings[self.STORY_1_ID]) commit_log_model = story_models.StoryCommitLogEntryModel.get_by_id( 'story-%s-2' % self.STORY_1_ID) self.assertEqual( commit_log_model.user_id, pending_deletion_model.story_mappings[self.STORY_1_ID])
def test_delete_user_collection_exploration_single(self): self.save_new_valid_exploration(self.EXPLORATION_1_ID, self.user_1_id) self.save_new_valid_collection(self.COLLECTION_1_ID, self.user_1_id, exploration_id=self.EXPLORATION_1_ID) wipeout_service.pre_delete_user(self.user_1_id) self.assertIsNotNone( user_models.UserSettingsModel.get_by_id(self.user_1_id)) self.assertIsNotNone( user_models.UserEmailPreferencesModel.get_by_id(self.user_1_id)) self.assertIsNotNone( collection_models.CollectionModel.get_by_id(self.COLLECTION_1_ID)) self.assertIsNotNone( exp_models.ExplorationModel.get_by_id(self.EXPLORATION_1_ID)) wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) self.assertIsNone( user_models.UserSettingsModel.get_by_id(self.user_1_id)) self.assertIsNone( user_models.UserEmailPreferencesModel.get_by_id(self.user_1_id)) self.assertIsNone( collection_models.CollectionModel.get_by_id(self.COLLECTION_1_ID)) self.assertIsNone( exp_models.ExplorationModel.get_by_id(self.EXPLORATION_1_ID))
def test_verification_when_user_is_wrongly_deleted_fails(self): pending_deletion_request = ( wipeout_service.get_pending_deletion_request(self.user_1_id)) wipeout_service.delete_user(pending_deletion_request) pending_deletion_request.deletion_complete = True wipeout_service.save_pending_deletion_requests( [pending_deletion_request]) email_content = ( 'The Wipeout process failed for the user with ID \'%s\' ' 'and email \'%s\'.' % (self.user_1_id, self.USER_1_EMAIL) ) send_email_swap = self.swap_with_checks( email_manager, 'send_mail_to_admin', lambda x, y: None, expected_args=[('WIPEOUT: Account deletion failed', email_content)] ) user_models.CompletedActivitiesModel( id=self.user_1_id, exploration_ids=[], collection_ids=[], story_ids=[], learnt_topic_ids=[] ).put() with send_email_swap: output = self._run_one_off_job() self.assertIn(['FAILURE', [self.user_1_id]], output)
def test_delete_user_multiple(self): wipeout_service.pre_delete_user(self.user_2_id) self.assertIsNotNone( user_models.UserSettingsModel.get_by_id(self.user_2_id)) self.assertIsNotNone( user_models.UserEmailPreferencesModel.get_by_id(self.user_2_id)) self.assertIsNotNone( user_models.CompletedActivitiesModel.get_by_id(self.user_2_id)) self.assertIsNotNone( user_models.IncompleteActivitiesModel.get_by_id(self.user_2_id)) self.assertIsNotNone( user_models.LearnerPlaylistModel.get_by_id(self.user_2_id)) wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_2_id)) self.assertIsNone( user_models.UserSettingsModel.get_by_id(self.user_2_id)) self.assertIsNone( user_models.UserEmailPreferencesModel.get_by_id(self.user_2_id)) self.assertIsNone( user_models.CompletedActivitiesModel.get_by_id(self.user_2_id)) self.assertIsNone( user_models.IncompleteActivitiesModel.get_by_id(self.user_2_id)) self.assertIsNone( user_models.LearnerPlaylistModel.get_by_id(self.user_2_id))
def test_multiple_stories_are_pseudonymized(self): self.save_new_topic(self.TOPIC_1_ID, self.user_1_id, name='Topic 2') self.save_new_story(self.STORY_2_ID, self.user_1_id, self.TOPIC_1_ID) wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) pending_deletion_model = ( user_models.PendingDeletionRequestModel.get_by_id(self.user_1_id)) metadata_model = story_models.StorySnapshotMetadataModel.get_by_id( '%s-1' % self.STORY_1_ID) self.assertEqual( metadata_model.committer_id, pending_deletion_model.story_mappings[self.STORY_1_ID]) commit_log_model = story_models.StoryCommitLogEntryModel.get_by_id( 'story-%s-1' % self.STORY_1_ID) self.assertEqual( commit_log_model.user_id, pending_deletion_model.story_mappings[self.STORY_1_ID]) metadata_model = story_models.StorySnapshotMetadataModel.get_by_id( '%s-1' % self.STORY_2_ID) self.assertEqual( metadata_model.committer_id, pending_deletion_model.story_mappings[self.STORY_2_ID]) commit_log_model = story_models.StoryCommitLogEntryModel.get_by_id( 'story-%s-1' % self.STORY_2_ID) self.assertEqual( commit_log_model.user_id, pending_deletion_model.story_mappings[self.STORY_2_ID])
def map(pending_deletion_request_model): """Implements the map function for this job.""" pending_deletion_request = wipeout_service.get_pending_deletion_request( pending_deletion_request_model.id) # The final status of the deletion. Either 'SUCCESS' or 'ALREADY DONE'. deletion_status = wipeout_service.run_user_deletion( pending_deletion_request) yield (deletion_status, pending_deletion_request.user_id)
def map(pending_deletion_request_model): """Implements the map function for this job.""" pending_deletion_request = wipeout_service.get_pending_deletion_request( pending_deletion_request_model.id) # The final status of the completion. Either 'NOT DELETED', 'SUCCESS', # or 'FAILURE'. completion_status = wipeout_service.run_user_deletion_completion( pending_deletion_request) yield (completion_status, pending_deletion_request.user_id)
def test_verification_when_user_is_deleted_is_successful(self): pending_deletion_request = ( wipeout_service.get_pending_deletion_request(self.user_1_id)) wipeout_service.delete_user(pending_deletion_request) pending_deletion_request.deletion_complete = True wipeout_service.save_pending_deletion_request(pending_deletion_request) output = self._run_one_off_job() self.assertIn(['SUCCESS', [self.user_1_id]], output)
def test_after_deletion_user_cannot_do_anything(self): wipeout_service.pre_delete_user(self.user_1_id) wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) self.assertIsNone(user_services.get_user_settings(self.user_1_id)) with self.assertRaisesRegexp(Exception, 'User not found.'): # Try to do some action with the deleted user. user_services.update_preferred_language_codes( self.user_1_id, ['en'])
def test_verification_when_user_is_wrongly_deleted_fails(self): pending_deletion_request = ( wipeout_service.get_pending_deletion_request(self.user_1_id)) wipeout_service.delete_user(pending_deletion_request) pending_deletion_request.deletion_complete = True wipeout_service.save_pending_deletion_request(pending_deletion_request) user_models.CompletedActivitiesModel(id=self.user_1_id, exploration_ids=[], collection_ids=[]).put() output = self._run_one_off_job() self.assertIn(['FAILURE', [self.user_1_id]], output)
def map(pending_deletion_request_model): """Implements the map function for this job.""" # If deletion_complete is False the UserDeletionOneOffJob wasn't yet run # for the user. The verification will be done in the next run of # FullyCompleteUserDeletionOneOffJob. pending_deletion_request = wipeout_service.get_pending_deletion_request( pending_deletion_request_model.id) # The final status of the completion. Either 'NOT DELETED', 'SUCCESS', # or 'FAILURE'. completion_status = wipeout_service.run_user_deletion_completion( pending_deletion_request) yield (completion_status, pending_deletion_request.user_id)
def map(pending_deletion_request_model): """Implements the map function for this job.""" pending_deletion_request = wipeout_service.get_pending_deletion_request( pending_deletion_request_model.id) if pending_deletion_request.deletion_complete: yield ('ALREADY DONE', pending_deletion_request.user_id) else: wipeout_service.delete_user(pending_deletion_request) pending_deletion_request.deletion_complete = True wipeout_service.save_pending_deletion_requests( [pending_deletion_request]) yield ('SUCCESS', pending_deletion_request.user_id)
def test_verification_is_unsuccessful_when_deletion_failed(self): wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_2_id)) story_services.update_story(self.user_2_id, self.STORY_2_ID, [ story_domain.StoryChange({ 'cmd': story_domain.CMD_ADD_STORY_NODE, 'node_id': 'node_1', 'title': 'Title 2' }) ], 'Add node.') self.assertFalse( wipeout_service.verify_user_deleted( wipeout_service.get_pending_deletion_request(self.user_2_id))) wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_2_id)) self.assertTrue( wipeout_service.verify_user_deleted( wipeout_service.get_pending_deletion_request(self.user_2_id)))
def test_delete_user_broken(self): wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_2_id)) user_models.CompletedActivitiesModel(id=self.user_2_id, exploration_ids=[], collection_ids=[]).put() user_models.IncompleteActivitiesModel(id=self.user_2_id, exploration_ids=[], collection_ids=[]).put() user_models.LearnerPlaylistModel(id=self.user_2_id, exploration_ids=[], collection_ids=[]).put() self.assertFalse( wipeout_service.verify_user_deleted( wipeout_service.get_pending_deletion_request(self.user_2_id))) wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_2_id)) self.assertTrue( wipeout_service.verify_user_deleted( wipeout_service.get_pending_deletion_request(self.user_2_id)))
def test_delete_user_simple(self): wipeout_service.pre_delete_user(self.user_1_id) self.assertIsNotNone( user_models.UserSettingsModel.get_by_id(self.user_1_id)) self.assertIsNotNone( user_models.UserEmailPreferencesModel.get_by_id(self.user_1_id)) wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) self.assertIsNone( user_models.UserSettingsModel.get_by_id(self.user_1_id)) self.assertIsNone( user_models.UserEmailPreferencesModel.get_by_id(self.user_1_id))
def test_one_story_is_pseudonymized(self): wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) # Verify user is deleted. pending_deletion_model = ( user_models.PendingDeletionRequestModel.get_by_id(self.user_1_id)) metadata_model = story_models.StorySnapshotMetadataModel.get_by_id( '%s-1' % self.STORY_1_ID) self.assertEqual( metadata_model.committer_id, pending_deletion_model.story_mappings[self.STORY_1_ID]) commit_log_model = story_models.StoryCommitLogEntryModel.get_by_id( 'story-%s-1' % self.STORY_1_ID) self.assertEqual( commit_log_model.user_id, pending_deletion_model.story_mappings[self.STORY_1_ID])
def test_one_story_with_missing_snapshot_is_pseudonymized(self): observed_log_messages = [] def _mock_logging_function(msg, *args): """Mocks logging.warning().""" observed_log_messages.append(msg % args) logging_swap = self.swap(logging, 'error', _mock_logging_function) story_models.StoryCommitLogEntryModel( id='story-%s-1' % self.STORY_2_ID, story_id=self.STORY_2_ID, user_id=self.user_1_id, commit_type='create_new', commit_cmds=[{}], post_commit_status=constants.ACTIVITY_STATUS_PUBLIC, version=1).put() with logging_swap: wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) self.assertEqual(observed_log_messages, [ 'The commit log and snapshot story IDs differ. ' 'Snapshots without commit logs: [], ' 'Commit logs without snapshots: [u\'%s\'].' % self.STORY_2_ID ]) # Verify user is deleted. pending_deletion_model = ( user_models.PendingDeletionRequestModel.get_by_id(self.user_1_id)) metadata_model = story_models.StorySnapshotMetadataModel.get_by_id( '%s-1' % self.STORY_1_ID) self.assertEqual( metadata_model.committer_id, pending_deletion_model.story_mappings[self.STORY_1_ID]) commit_log_model_1 = story_models.StoryCommitLogEntryModel.get_by_id( 'story-%s-1' % self.STORY_1_ID) self.assertEqual( commit_log_model_1.user_id, pending_deletion_model.story_mappings[self.STORY_1_ID]) commit_log_model_2 = story_models.StoryCommitLogEntryModel.get_by_id( 'story-%s-1' % self.STORY_2_ID) self.assertEqual( commit_log_model_2.user_id, pending_deletion_model.story_mappings[self.STORY_2_ID])
def test_gets_pending_deletion_request(self): pending_deletion_request_model = ( user_models.PendingDeletionRequestModel( id=self.user_1_id, email=self.USER_1_EMAIL, deletion_complete=False, exploration_ids=['exp1', 'exp2'], collection_ids=['col1'], story_mappings=None)) pending_deletion_request_model.put() pending_deletion_request = ( wipeout_service.get_pending_deletion_request(self.user_1_id)) self.assertEqual(pending_deletion_request.user_id, self.user_1_id) self.assertEqual(pending_deletion_request.email, self.USER_1_EMAIL) self.assertEqual(pending_deletion_request.deletion_complete, False) self.assertEqual(pending_deletion_request.exploration_ids, ['exp1', 'exp2']) self.assertEqual(pending_deletion_request.collection_ids, ['col1']) self.assertEqual(pending_deletion_request.story_mappings, None)
def map(pending_deletion_request_model): """Implements the map function for this job.""" # If deletion_complete is False the UserDeletionOneOffJob wasn't yet run # for the user. The verification will be done in the next run of # FullyCompleteUserDeletionOneOffJob. pending_deletion_request = wipeout_service.get_pending_deletion_request( pending_deletion_request_model.id) if not pending_deletion_request.deletion_complete: yield ('NOT DELETED', pending_deletion_request.user_id) elif wipeout_service.verify_user_deleted(pending_deletion_request): wipeout_service.delete_pending_deletion_request( pending_deletion_request.user_id) email_manager.send_account_deleted_email( pending_deletion_request.user_id, pending_deletion_request.email) yield ('SUCCESS', pending_deletion_request.user_id) else: pending_deletion_request.deletion_complete = False wipeout_service.save_pending_deletion_requests( [pending_deletion_request]) yield ('FAILURE', pending_deletion_request.user_id)
def test_delete_user_simple(self): wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) self.assertTrue( wipeout_service.verify_user_deleted( wipeout_service.get_pending_deletion_request(self.user_1_id)))
def wipeout(self): """Runs wipeout on the user created by this test.""" wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_id))
def test_verification_is_successful(self): wipeout_service.delete_user( wipeout_service.get_pending_deletion_request(self.user_1_id)) self.assertTrue( wipeout_service.verify_user_deleted( wipeout_service.get_pending_deletion_request(self.user_1_id)))