Exemplo n.º 1
0
 def test_export_nonexistent_user(self):
     """Setup for nonexistent user test of export_data functionality."""
     with self.assertRaisesRegexp(
             user_models.UserSettingsModel.EntityNotFoundError,
             'Entity for class UserSettingsModel with id fake_user_id '
             'not found'):
         takeout_service.export_data_for_user('fake_user_id')
Exemplo n.º 2
0
    def get(self):
        """Handles GET requests."""
        # Retrieve user data.
        user_takeout_object = takeout_service.export_data_for_user(
            self.user_id)
        user_data = user_takeout_object.user_data
        user_images = user_takeout_object.user_images

        # Ensure that the exported data does not contain a user ID.
        user_data_json_string = json.dumps(user_data)
        if re.search(feconf.USER_ID_REGEX, user_data_json_string):
            logging.error(
                '[TAKEOUT] User ID found in the JSON generated for user %s'
                % self.user_id)
            user_data_json_string = (
                'There was an error while exporting ' +
                'data. Please contact %s to export your data.'
                % feconf.ADMIN_EMAIL_ADDRESS)
            user_images = []

        # Create zip file.
        temp_file = io.BytesIO()
        with zipfile.ZipFile(
            temp_file, mode='w', compression=zipfile.ZIP_DEFLATED
        ) as zfile:
            zfile.writestr('oppia_takeout_data.json', user_data_json_string)
            for image in user_images:
                decoded_png = utils.convert_png_data_url_to_binary(
                    image.b64_image_data)
                zfile.writestr('images/' + image.image_export_path, decoded_png)

        # Render file for download.
        self.render_downloadable_file(
            temp_file, 'oppia_takeout_data.zip', 'text/plain')
Exemplo n.º 3
0
    def get(self):
        """Handles GET requests."""
        if not constants.ENABLE_ACCOUNT_EXPORT:
            raise self.PageNotFoundException

        # Retrieve user data.
        user_takeout_object = takeout_service.export_data_for_user(
            self.user_id)
        user_data = user_takeout_object.user_data
        user_images = user_takeout_object.user_images

        # Create zip file.
        temp_file = python_utils.string_io()
        with zipfile.ZipFile(temp_file,
                             mode='w',
                             compression=zipfile.ZIP_DEFLATED) as zfile:
            zfile.writestr('oppia_takeout_data.json', json.dumps(user_data))
            for image in user_images:
                b64_png_no_header = image.b64_image_data.split(',')[1]
                decoded_png = base64.b64decode(
                    python_utils.url_unquote_plus(b64_png_no_header))
                zfile.writestr('images/' + image.image_export_path,
                               decoded_png)

        # Render file for download.
        self.render_downloadable_file(temp_file.getvalue(),
                                      'oppia_takeout_data.zip', 'text/plain')
Exemplo n.º 4
0
    def get(self):
        """Handles GET requests."""
        if not constants.ENABLE_ACCOUNT_EXPORT:
            raise self.PageNotFoundException

        user_data = takeout_service.export_data_for_user(self.user_id)
        self.render_json(user_data)
Exemplo n.º 5
0
    def test_export_data_nontrivial(self):
        """Nontrivial test of export_data functionality."""
        self.set_up_non_trivial()

        # We set up the feedback_thread_model here so that we can easily
        # access it when computing the expected data later.
        feedback_thread_model = feedback_models.GeneralFeedbackThreadModel(
            entity_type=self.THREAD_ENTITY_TYPE,
            entity_id=self.THREAD_ENTITY_ID,
            original_author_id=self.USER_ID_1,
            status=self.THREAD_STATUS,
            subject=self.THREAD_SUBJECT,
            has_suggestion=self.THREAD_HAS_SUGGESTION,
            summary=self.THREAD_SUMMARY,
            message_count=self.THREAD_MESSAGE_COUNT)
        feedback_thread_model.put()

        expected_stats_data = {
            'impact_score': self.USER_1_IMPACT_SCORE,
            'total_plays': self.USER_1_TOTAL_PLAYS,
            'average_ratings': self.USER_1_AVERAGE_RATINGS,
            'num_ratings': self.USER_1_NUM_RATINGS,
            'weekly_creator_stats_list': self.USER_1_WEEKLY_CREATOR_STATS_LIST
        }
        expected_skill_data = {
            self.SKILL_ID_1: self.DEGREE_OF_MASTERY,
            self.SKILL_ID_2: self.DEGREE_OF_MASTERY
        }
        expected_contribution_data = {
            'created_exploration_ids': [self.EXPLORATION_IDS[0]],
            'edited_exploration_ids': [self.EXPLORATION_IDS[0]]
        }
        expected_exploration_data = {
            self.EXPLORATION_IDS[0]: {
                'rating':
                2,
                'rated_on':
                self.GENERIC_DATE,
                'draft_change_list': {
                    'new_content': {}
                },
                'draft_change_list_last_updated':
                self.GENERIC_DATE,
                'draft_change_list_exp_version':
                3,
                'draft_change_list_id':
                1,
                'mute_suggestion_notifications':
                (feconf.DEFAULT_SUGGESTION_NOTIFICATIONS_MUTED_PREFERENCE),
                'mute_feedback_notifications':
                (feconf.DEFAULT_SUGGESTION_NOTIFICATIONS_MUTED_PREFERENCE)
            }
        }
        expected_completed_activities_data = {
            'completed_exploration_ids': self.EXPLORATION_IDS,
            'completed_collection_ids': self.COLLECTION_IDS
        }
        expected_incomplete_activities_data = {
            'incomplete_exploration_ids': self.EXPLORATION_IDS,
            'incomplete_collection_ids': self.COLLECTION_IDS
        }
        expected_last_playthrough_data = {
            self.EXPLORATION_IDS[0]: {
                'exp_version': self.EXP_VERSION,
                'state_name': self.STATE_NAME
            }
        }
        expected_learner_playlist_data = {
            'playlist_exploration_ids': self.EXPLORATION_IDS,
            'playlist_collection_ids': self.COLLECTION_IDS
        }
        expected_collection_progress_data = {
            self.COLLECTION_IDS[0]: self.EXPLORATION_IDS
        }
        expected_story_progress_data = {
            self.STORY_ID_1: self.COMPLETED_NODE_IDS_1
        }
        thread_id = feedback_services.create_thread(self.THREAD_ENTITY_TYPE,
                                                    self.THREAD_ENTITY_ID,
                                                    self.USER_ID_1,
                                                    self.THREAD_SUBJECT,
                                                    self.MESSAGE_TEXT)
        feedback_services.create_message(thread_id, self.USER_ID_1,
                                         self.THREAD_STATUS,
                                         self.THREAD_SUBJECT,
                                         self.MESSAGE_TEXT)
        expected_general_feedback_thread_data = {
            feedback_thread_model.id: {
                'entity_type': self.THREAD_ENTITY_TYPE,
                'entity_id': self.THREAD_ENTITY_ID,
                'status': self.THREAD_STATUS,
                'subject': self.THREAD_SUBJECT,
                'has_suggestion': self.THREAD_HAS_SUGGESTION,
                'summary': self.THREAD_SUMMARY,
                'message_count': self.THREAD_MESSAGE_COUNT,
                'last_updated': feedback_thread_model.last_updated
            },
            thread_id: {
                'entity_type':
                self.THREAD_ENTITY_TYPE,
                'entity_id':
                self.THREAD_ENTITY_ID,
                'status':
                self.THREAD_STATUS,
                'subject':
                self.THREAD_SUBJECT,
                'has_suggestion':
                False,
                'summary':
                None,
                'message_count':
                2,
                'last_updated':
                (feedback_models.GeneralFeedbackThreadModel.get(
                    thread_id).last_updated)
            }
        }
        expected_general_feedback_thread_user_data = {
            thread_id: self.MESSAGE_IDS_READ_BY_USER
        }
        expected_general_feedback_message_data = {
            thread_id + '.0': {
                'thread_id': thread_id,
                'message_id': 0,
                'updated_status': self.THREAD_STATUS,
                'updated_subject': self.THREAD_SUBJECT,
                'text': self.MESSAGE_TEXT,
                'received_via_email': self.MESSAGE_RECEIEVED_VIA_EMAIL
            },
            thread_id + '.1': {
                'thread_id': thread_id,
                'message_id': 1,
                'updated_status': self.THREAD_STATUS,
                'updated_subject': self.THREAD_SUBJECT,
                'text': self.MESSAGE_TEXT,
                'received_via_email': self.MESSAGE_RECEIEVED_VIA_EMAIL
            }
        }
        expected_collection_rights_data = {
            'owned_collection_ids': ([self.COLLECTION_IDS[0]]),
            'editable_collection_ids': ([self.COLLECTION_IDS[0]]),
            'voiced_collection_ids': ([self.COLLECTION_IDS[0]]),
            'viewable_collection_ids': [self.COLLECTION_IDS[0]]
        }
        expected_general_suggestion_data = {
            'exploration.exp1.thread_1': {
                'suggestion_type':
                (suggestion_models.SUGGESTION_TYPE_EDIT_STATE_CONTENT),
                'target_type':
                suggestion_models.TARGET_TYPE_EXPLORATION,
                'target_id':
                self.EXPLORATION_IDS[0],
                'target_version_at_submission':
                1,
                'status':
                suggestion_models.STATUS_IN_REVIEW,
                'change_cmd':
                self.CHANGE_CMD
            }
        }
        expected_exploration_rights_data = {
            'owned_exploration_ids': ([self.EXPLORATION_IDS[0]]),
            'editable_exploration_ids': ([self.EXPLORATION_IDS[0]]),
            'voiced_exploration_ids': ([self.EXPLORATION_IDS[0]]),
            'viewable_exploration_ids': [self.EXPLORATION_IDS[0]]
        }
        expected_settings_data = {
            'email': self.USER_1_EMAIL,
            'role': feconf.ROLE_ID_ADMIN,
            'username': self.GENERIC_USERNAME,
            'normalized_username': self.GENERIC_USERNAME,
            'last_agreed_to_terms': self.GENERIC_DATE,
            'last_started_state_editor_tutorial': self.GENERIC_DATE,
            'last_started_state_translation_tutorial': self.GENERIC_DATE,
            'last_logged_in': self.GENERIC_DATE,
            'last_edited_an_exploration': self.GENERIC_DATE,
            'profile_picture_data_url': self.GENERIC_IMAGE_URL,
            'default_dashboard': 'learner',
            'creator_dashboard_display_pref': 'card',
            'user_bio': self.GENERIC_USER_BIO,
            'subject_interests': self.GENERIC_SUBJECT_INTERESTS,
            'first_contribution_msec': 1,
            'preferred_language_codes': self.GENERIC_LANGUAGE_CODES,
            'preferred_site_language_code': self.GENERIC_LANGUAGE_CODES[0],
            'preferred_audio_language_code': self.GENERIC_LANGUAGE_CODES[0]
        }

        expected_reply_to_data = {
            self.THREAD_ID_1: self.USER_1_REPLY_TO_ID_1,
            self.THREAD_ID_2: self.USER_1_REPLY_TO_ID_2
        }

        expected_subscriptions_data = {
            'creator_ids':
            self.CREATOR_IDS,
            'collection_ids':
            self.COLLECTION_IDS,
            'activity_ids':
            self.ACTIVITY_IDS + self.EXPLORATION_IDS,
            'general_feedback_thread_ids':
            self.GENERAL_FEEDBACK_THREAD_IDS + [thread_id],
            'last_checked':
            None
        }

        expected_topic_data = {
            'managed_topic_ids': [self.TOPIC_ID_1, self.TOPIC_ID_2]
        }

        expected_export = {
            'user_stats_data': expected_stats_data,
            'user_settings_data': expected_settings_data,
            'user_subscriptions_data': expected_subscriptions_data,
            'user_skill_mastery_data': expected_skill_data,
            'user_contributions_data': expected_contribution_data,
            'exploration_user_data_data': expected_exploration_data,
            'completed_activities_data': expected_completed_activities_data,
            'incomplete_activities_data': expected_incomplete_activities_data,
            'exp_user_last_playthrough_data': expected_last_playthrough_data,
            'learner_playlist_data': expected_learner_playlist_data,
            'topic_rights_data': expected_topic_data,
            'collection_progress_data': expected_collection_progress_data,
            'story_progress_data': expected_story_progress_data,
            'general_feedback_thread_data':
            expected_general_feedback_thread_data,
            'general_feedback_thread_user_data':
            expected_general_feedback_thread_user_data,
            'general_feedback_message_data':
            expected_general_feedback_message_data,
            'collection_rights_data': expected_collection_rights_data,
            'general_suggestion_data': expected_general_suggestion_data,
            'exploration_rights_data': expected_exploration_rights_data,
            'general_feedback_email_reply_to_id_data': expected_reply_to_data
        }

        exported_data = takeout_service.export_data_for_user(self.USER_ID_1)
        self.assertEqual(exported_data, expected_export)
Exemplo n.º 6
0
    def test_export_data_trivial(self):
        """Trivial test of export_data functionality."""
        self.set_up_trivial()

        # Generate expected output.
        collection_progress_data = {}
        collection_rights_data = {
            'editable_collection_ids': [],
            'owned_collection_ids': [],
            'viewable_collection_ids': [],
            'voiced_collection_ids': []
        }
        completed_activities_data = {}
        contribution_data = {}
        exploration_rights_data = {
            'editable_exploration_ids': [],
            'owned_exploration_ids': [],
            'viewable_exploration_ids': [],
            'voiced_exploration_ids': []
        }
        exploration_data = {}
        reply_to_data = {}
        general_feedback_message_data = {}
        general_feedback_thread_data = {}
        general_feedback_thread_user_data = {}
        general_suggestion_data = {}
        last_playthrough_data = {}
        learner_playlist_data = {}
        incomplete_activities_data = {}
        settings_data = {
            'email': '*****@*****.**',
            'role': feconf.ROLE_ID_ADMIN,
            'username': None,
            'normalized_username': None,
            'last_agreed_to_terms': None,
            'last_started_state_editor_tutorial': None,
            'last_started_state_translation_tutorial': None,
            'last_logged_in': None,
            'last_edited_an_exploration': None,
            'profile_picture_data_url': None,
            'default_dashboard': 'learner',
            'creator_dashboard_display_pref': 'card',
            'user_bio': None,
            'subject_interests': [],
            'first_contribution_msec': None,
            'preferred_language_codes': [],
            'preferred_site_language_code': None,
            'preferred_audio_language_code': None
        }
        skill_data = {}
        stats_data = {}
        story_progress_data = {}
        subscriptions_data = {
            'activity_ids': [],
            'collection_ids': [],
            'creator_ids': [],
            'general_feedback_thread_ids': [],
            'last_checked': None
        }
        topic_rights_data = {'managed_topic_ids': []}
        expected_export = {
            'user_stats_data': stats_data,
            'user_settings_data': settings_data,
            'user_subscriptions_data': subscriptions_data,
            'user_skill_mastery_data': skill_data,
            'user_contributions_data': contribution_data,
            'exploration_user_data_data': exploration_data,
            'completed_activities_data': completed_activities_data,
            'incomplete_activities_data': incomplete_activities_data,
            'exp_user_last_playthrough_data': last_playthrough_data,
            'learner_playlist_data': learner_playlist_data,
            'topic_rights_data': topic_rights_data,
            'collection_progress_data': collection_progress_data,
            'story_progress_data': story_progress_data,
            'general_feedback_thread_data': general_feedback_thread_data,
            'general_feedback_thread_user_data':
            general_feedback_thread_user_data,
            'general_feedback_message_data': general_feedback_message_data,
            'collection_rights_data': collection_rights_data,
            'general_suggestion_data': general_suggestion_data,
            'exploration_rights_data': exploration_rights_data,
            'general_feedback_email_reply_to_id_data': reply_to_data
        }

        # Perform export and compare.
        exported_data = takeout_service.export_data_for_user(self.USER_ID_1)
        self.assertEqual(expected_export, exported_data)
Exemplo n.º 7
0
    def test_export_data_nontrivial(self):
        """Nontrivial test of export_data functionality."""
        self.set_up_non_trivial()
        # We set up the feedback_thread_model here so that we can easily
        # access it when computing the expected data later.
        feedback_thread_model = feedback_models.GeneralFeedbackThreadModel(
            entity_type=self.THREAD_ENTITY_TYPE,
            entity_id=self.THREAD_ENTITY_ID,
            original_author_id=self.USER_ID_1,
            status=self.THREAD_STATUS,
            subject=self.THREAD_SUBJECT,
            has_suggestion=self.THREAD_HAS_SUGGESTION,
            summary=self.THREAD_SUMMARY,
            message_count=self.THREAD_MESSAGE_COUNT)
        feedback_thread_model.put()

        expected_stats_data = {
            'impact_score': self.USER_1_IMPACT_SCORE,
            'total_plays': self.USER_1_TOTAL_PLAYS,
            'average_ratings': self.USER_1_AVERAGE_RATINGS,
            'num_ratings': self.USER_1_NUM_RATINGS,
            'weekly_creator_stats_list': self.USER_1_WEEKLY_CREATOR_STATS_LIST
        }
        expected_skill_data = {
            self.SKILL_ID_1: self.DEGREE_OF_MASTERY,
            self.SKILL_ID_2: self.DEGREE_OF_MASTERY
        }
        expected_contribution_data = {
            'created_exploration_ids': [self.EXPLORATION_IDS[0]],
            'edited_exploration_ids': [self.EXPLORATION_IDS[0]]
        }
        expected_exploration_data = {
            self.EXPLORATION_IDS[0]: {
                'rating':
                2,
                'rated_on':
                self.GENERIC_EPOCH,
                'draft_change_list': {
                    'new_content': {}
                },
                'draft_change_list_last_updated':
                self.GENERIC_EPOCH,
                'draft_change_list_exp_version':
                3,
                'draft_change_list_id':
                1,
                'mute_suggestion_notifications':
                (feconf.DEFAULT_SUGGESTION_NOTIFICATIONS_MUTED_PREFERENCE),
                'mute_feedback_notifications':
                (feconf.DEFAULT_SUGGESTION_NOTIFICATIONS_MUTED_PREFERENCE)
            }
        }
        expected_completed_activities_data = {
            'completed_exploration_ids': self.EXPLORATION_IDS,
            'completed_collection_ids': self.COLLECTION_IDS
        }
        expected_incomplete_activities_data = {
            'incomplete_exploration_ids': self.EXPLORATION_IDS,
            'incomplete_collection_ids': self.COLLECTION_IDS
        }
        expected_last_playthrough_data = {
            self.EXPLORATION_IDS[0]: {
                'exp_version': self.EXP_VERSION,
                'state_name': self.STATE_NAME
            }
        }
        expected_learner_playlist_data = {
            'playlist_exploration_ids': self.EXPLORATION_IDS,
            'playlist_collection_ids': self.COLLECTION_IDS
        }
        expected_collection_progress_data = {
            self.COLLECTION_IDS[0]: self.EXPLORATION_IDS
        }
        expected_story_progress_data = {
            self.STORY_ID_1: self.COMPLETED_NODE_IDS_1
        }
        thread_id = feedback_services.create_thread(self.THREAD_ENTITY_TYPE,
                                                    self.THREAD_ENTITY_ID,
                                                    self.USER_ID_1,
                                                    self.THREAD_SUBJECT,
                                                    self.MESSAGE_TEXT)
        feedback_services.create_message(thread_id, self.USER_ID_1,
                                         self.THREAD_STATUS,
                                         self.THREAD_SUBJECT,
                                         self.MESSAGE_TEXT)
        expected_general_feedback_thread_data = {
            feedback_thread_model.id: {
                'entity_type':
                self.THREAD_ENTITY_TYPE,
                'entity_id':
                self.THREAD_ENTITY_ID,
                'status':
                self.THREAD_STATUS,
                'subject':
                self.THREAD_SUBJECT,
                'has_suggestion':
                self.THREAD_HAS_SUGGESTION,
                'summary':
                self.THREAD_SUMMARY,
                'message_count':
                self.THREAD_MESSAGE_COUNT,
                'last_updated_msec':
                utils.get_time_in_millisecs(feedback_thread_model.last_updated)
            },
            thread_id: {
                'entity_type':
                self.THREAD_ENTITY_TYPE,
                'entity_id':
                self.THREAD_ENTITY_ID,
                'status':
                self.THREAD_STATUS,
                'subject':
                self.THREAD_SUBJECT,
                'has_suggestion':
                False,
                'summary':
                None,
                'message_count':
                2,
                'last_updated_msec':
                utils.get_time_in_millisecs(
                    feedback_models.GeneralFeedbackThreadModel.get_by_id(
                        thread_id).last_updated)
            }
        }
        expected_general_feedback_thread_user_data = {
            thread_id: self.MESSAGE_IDS_READ_BY_USER
        }
        expected_general_feedback_message_data = {
            thread_id + '.0': {
                'thread_id': thread_id,
                'message_id': 0,
                'updated_status': self.THREAD_STATUS,
                'updated_subject': self.THREAD_SUBJECT,
                'text': self.MESSAGE_TEXT,
                'received_via_email': self.MESSAGE_RECEIEVED_VIA_EMAIL
            },
            thread_id + '.1': {
                'thread_id': thread_id,
                'message_id': 1,
                'updated_status': self.THREAD_STATUS,
                'updated_subject': self.THREAD_SUBJECT,
                'text': self.MESSAGE_TEXT,
                'received_via_email': self.MESSAGE_RECEIEVED_VIA_EMAIL
            }
        }
        expected_collection_rights_data = {
            'owned_collection_ids': ([self.COLLECTION_IDS[0]]),
            'editable_collection_ids': ([self.COLLECTION_IDS[0]]),
            'voiced_collection_ids': ([self.COLLECTION_IDS[0]]),
            'viewable_collection_ids': [self.COLLECTION_IDS[0]]
        }
        expected_general_suggestion_data = {
            'exploration.exp1.thread_1': {
                'suggestion_type':
                (suggestion_models.SUGGESTION_TYPE_EDIT_STATE_CONTENT),
                'target_type':
                suggestion_models.TARGET_TYPE_EXPLORATION,
                'target_id':
                self.EXPLORATION_IDS[0],
                'target_version_at_submission':
                1,
                'status':
                suggestion_models.STATUS_IN_REVIEW,
                'change_cmd':
                self.CHANGE_CMD
            }
        }
        expected_exploration_rights_data = {
            'owned_exploration_ids': ([self.EXPLORATION_IDS[0]]),
            'editable_exploration_ids': ([self.EXPLORATION_IDS[0]]),
            'voiced_exploration_ids': ([self.EXPLORATION_IDS[0]]),
            'viewable_exploration_ids': [self.EXPLORATION_IDS[0]]
        }
        expected_settings_data = {
            'email': self.USER_1_EMAIL,
            'role': feconf.ROLE_ID_ADMIN,
            'username': self.GENERIC_USERNAME,
            'normalized_username': self.GENERIC_USERNAME,
            'last_agreed_to_terms': self.GENERIC_EPOCH,
            'last_started_state_editor_tutorial': self.GENERIC_EPOCH,
            'last_started_state_translation_tutorial': self.GENERIC_EPOCH,
            'last_logged_in': self.GENERIC_EPOCH,
            'last_edited_an_exploration': self.GENERIC_EPOCH,
            'profile_picture_filename': 'user_settings_profile_picture.png',
            'default_dashboard': 'learner',
            'creator_dashboard_display_pref': 'card',
            'user_bio': self.GENERIC_USER_BIO,
            'subject_interests': self.GENERIC_SUBJECT_INTERESTS,
            'first_contribution_msec': 1,
            'preferred_language_codes': self.GENERIC_LANGUAGE_CODES,
            'preferred_site_language_code': self.GENERIC_LANGUAGE_CODES[0],
            'preferred_audio_language_code': self.GENERIC_LANGUAGE_CODES[0]
        }

        expected_reply_to_data = {
            self.THREAD_ID_1: self.USER_1_REPLY_TO_ID_1,
            self.THREAD_ID_2: self.USER_1_REPLY_TO_ID_2
        }

        expected_subscriptions_data = {
            'creator_usernames':
            self.CREATOR_USERNAMES,
            'collection_ids':
            self.COLLECTION_IDS,
            'activity_ids':
            self.ACTIVITY_IDS + self.EXPLORATION_IDS,
            'general_feedback_thread_ids':
            self.GENERAL_FEEDBACK_THREAD_IDS + [thread_id],
            'last_checked':
            self.GENERIC_EPOCH
        }

        expected_task_entry_data = {
            'task_ids_resolved_by_user': [self.GENERIC_MODEL_ID]
        }
        expected_topic_data = {
            'managed_topic_ids': [self.TOPIC_ID_1, self.TOPIC_ID_2]
        }

        expected_voiceover_application_data = {
            'application_1_id': {
                'target_type': 'exploration',
                'target_id': 'exp_id',
                'status': 'review',
                'language_code': 'en',
                'filename': 'application_audio.mp3',
                'content': '<p>Some content</p>',
                'rejection_message': None
            },
            'application_2_id': {
                'target_type': 'exploration',
                'target_id': 'exp_id',
                'status': 'review',
                'language_code': 'en',
                'filename': 'application_audio.mp3',
                'content': '<p>Some content</p>',
                'rejection_message': None
            }
        }

        expected_community_rights_data = {
            'can_review_translation_for_language_codes': ['hi', 'en'],
            'can_review_voiceover_for_language_codes': ['hi'],
            'can_review_questions': True
        }

        expected_contrib_score_data = {
            self.SCORE_CATEGORY_1: {
                'has_email_been_sent': False,
                'score': 1.5
            },
            self.SCORE_CATEGORY_2: {
                'has_email_been_sent': False,
                'score': 2
            }
        }
        expected_collection_rights_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }
        expected_collection_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }

        expected_skill_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }
        expected_subtopic_page_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }
        expected_topic_rights_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }
        expected_topic_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }

        expected_story_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }
        expected_question_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }
        expected_config_property_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }

        expected_exploration_rights_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }

        expected_exploration_sm = {
            'exp_1-1': {
                'commit_type':
                'create',
                'commit_cmds': [{
                    'category': 'A category',
                    'cmd': 'create_new',
                    'title': 'A title'
                }],
                'commit_message':
                'New exploration created with title \'A title\'.'
            },
            'exp_1-2': {
                'commit_type':
                'edit',
                'commit_cmds': [{
                    'new_value': 'the objective',
                    'cmd': 'edit_exploration_property',
                    'old_value': None,
                    'property_name': 'objective'
                }],
                'commit_message':
                'Test edit'
            }
        }

        expected_platform_parameter_sm = {
            self.GENERIC_MODEL_ID: {
                'commit_type': self.COMMIT_TYPE,
                'commit_message': self.COMMIT_MESSAGE,
                'commit_cmds': self.COMMIT_CMDS
            }
        }

        expected_data = {
            'user_stats': expected_stats_data,
            'user_settings': expected_settings_data,
            'user_subscriptions': expected_subscriptions_data,
            'user_skill_mastery': expected_skill_data,
            'user_contributions': expected_contribution_data,
            'exploration_user_data': expected_exploration_data,
            'completed_activities': expected_completed_activities_data,
            'incomplete_activities': expected_incomplete_activities_data,
            'exp_user_last_playthrough': expected_last_playthrough_data,
            'learner_playlist': expected_learner_playlist_data,
            'task_entry': expected_task_entry_data,
            'topic_rights': expected_topic_data,
            'collection_progress': expected_collection_progress_data,
            'story_progress': expected_story_progress_data,
            'general_feedback_thread': expected_general_feedback_thread_data,
            'general_feedback_thread_user':
            expected_general_feedback_thread_user_data,
            'general_feedback_message': expected_general_feedback_message_data,
            'collection_rights': expected_collection_rights_data,
            'general_suggestion': expected_general_suggestion_data,
            'exploration_rights': expected_exploration_rights_data,
            'general_feedback_email_reply_to_id': expected_reply_to_data,
            'general_voiceover_application':
            expected_voiceover_application_data,
            'user_contribution_scoring': expected_contrib_score_data,
            'user_community_rights': expected_community_rights_data,
            'collection_rights_snapshot_metadata':
            expected_collection_rights_sm,
            'collection_snapshot_metadata': expected_collection_sm,
            'skill_snapshot_metadata': expected_skill_sm,
            'subtopic_page_snapshot_metadata': expected_subtopic_page_sm,
            'topic_rights_snapshot_metadata': expected_topic_rights_sm,
            'topic_snapshot_metadata': expected_topic_sm,
            'story_snapshot_metadata': expected_story_sm,
            'question_snapshot_metadata': expected_question_sm,
            'config_property_snapshot_metadata': expected_config_property_sm,
            'exploration_rights_snapshot_metadata':
            expected_exploration_rights_sm,
            'exploration_snapshot_metadata': expected_exploration_sm,
            'platform_parameter_snapshot_metadata':
            expected_platform_parameter_sm,
        }
        user_takeout_object = takeout_service.export_data_for_user(
            self.USER_ID_1)
        observed_data = user_takeout_object.user_data
        observed_images = user_takeout_object.user_images
        self.assertEqual(observed_data, expected_data)
        observed_json = json.dumps(observed_data)
        expected_json = json.dumps(expected_data)
        self.assertEqual(json.loads(observed_json), json.loads(expected_json))
        expected_images = [
            takeout_domain.TakeoutImage(self.GENERIC_IMAGE_URL,
                                        'user_settings_profile_picture.png')
        ]
        self.assertEqual(len(expected_images), len(observed_images))
        for i, _ in enumerate(expected_images):
            self.assertEqual(expected_images[i].b64_image_data,
                             observed_images[i].b64_image_data)
            self.assertEqual(expected_images[i].image_export_path,
                             observed_images[i].image_export_path)
Exemplo n.º 8
0
    def test_export_data_trivial(self):
        """Trivial test of export_data functionality."""
        self.set_up_trivial()

        # Generate expected output.
        collection_progress_data = {}
        collection_rights_data = {
            'editable_collection_ids': [],
            'owned_collection_ids': [],
            'viewable_collection_ids': [],
            'voiced_collection_ids': []
        }
        completed_activities_data = {}
        contribution_data = {}
        exploration_rights_data = {
            'editable_exploration_ids': [],
            'owned_exploration_ids': [],
            'viewable_exploration_ids': [],
            'voiced_exploration_ids': []
        }
        exploration_data = {}
        reply_to_data = {}
        general_feedback_message_data = {}
        general_feedback_thread_data = {}
        general_feedback_thread_user_data = {}
        general_suggestion_data = {}
        last_playthrough_data = {}
        learner_playlist_data = {}
        incomplete_activities_data = {}
        settings_data = {
            'email': '*****@*****.**',
            'role': feconf.ROLE_ID_ADMIN,
            'username': None,
            'normalized_username': None,
            'last_agreed_to_terms': None,
            'last_started_state_editor_tutorial': None,
            'last_started_state_translation_tutorial': None,
            'last_logged_in': None,
            'last_edited_an_exploration': None,
            'profile_picture_filename': None,
            'default_dashboard': 'learner',
            'creator_dashboard_display_pref': 'card',
            'user_bio': None,
            'subject_interests': [],
            'first_contribution_msec': None,
            'preferred_language_codes': [],
            'preferred_site_language_code': None,
            'preferred_audio_language_code': None
        }
        skill_data = {}
        stats_data = {}
        story_progress_data = {}
        subscriptions_data = {
            'activity_ids': [],
            'collection_ids': [],
            'creator_usernames': [],
            'general_feedback_thread_ids': [],
            'last_checked': None
        }
        task_entry_data = {'task_ids_resolved_by_user': []}
        topic_rights_data = {'managed_topic_ids': []}

        expected_voiceover_application_data = {}
        expected_contrib_score_data = {}
        expected_community_rights_data = {}
        expected_collection_rights_sm = {}
        expected_collection_sm = {}
        expected_skill_sm = {}
        expected_subtopic_page_sm = {}
        expected_topic_rights_sm = {}
        expected_topic_sm = {}
        expected_story_sm = {}
        expected_question_sm = {}
        expected_config_property_sm = {}
        expected_exploration_rights_sm = {}
        expected_exploration_sm = {}
        expected_platform_parameter_sm = {}

        expected_data = {
            'user_stats': stats_data,
            'user_settings': settings_data,
            'user_subscriptions': subscriptions_data,
            'user_skill_mastery': skill_data,
            'user_contributions': contribution_data,
            'exploration_user_data': exploration_data,
            'completed_activities': completed_activities_data,
            'incomplete_activities': incomplete_activities_data,
            'exp_user_last_playthrough': last_playthrough_data,
            'learner_playlist': learner_playlist_data,
            'task_entry': task_entry_data,
            'topic_rights': topic_rights_data,
            'collection_progress': collection_progress_data,
            'story_progress': story_progress_data,
            'general_feedback_thread': general_feedback_thread_data,
            'general_feedback_thread_user': general_feedback_thread_user_data,
            'general_feedback_message': general_feedback_message_data,
            'collection_rights': collection_rights_data,
            'general_suggestion': general_suggestion_data,
            'exploration_rights': exploration_rights_data,
            'general_feedback_email_reply_to_id': reply_to_data,
            'general_voiceover_application':
            expected_voiceover_application_data,
            'user_contribution_scoring': expected_contrib_score_data,
            'user_community_rights': expected_community_rights_data,
            'collection_rights_snapshot_metadata':
            expected_collection_rights_sm,
            'collection_snapshot_metadata': expected_collection_sm,
            'skill_snapshot_metadata': expected_skill_sm,
            'subtopic_page_snapshot_metadata': expected_subtopic_page_sm,
            'topic_rights_snapshot_metadata': expected_topic_rights_sm,
            'topic_snapshot_metadata': expected_topic_sm,
            'story_snapshot_metadata': expected_story_sm,
            'question_snapshot_metadata': expected_question_sm,
            'config_property_snapshot_metadata': expected_config_property_sm,
            'exploration_rights_snapshot_metadata':
            expected_exploration_rights_sm,
            'exploration_snapshot_metadata': expected_exploration_sm,
            'platform_parameter_snapshot_metadata':
            expected_platform_parameter_sm,
        }

        # Perform export and compare.
        user_takeout_object = takeout_service.export_data_for_user(
            self.USER_ID_1)
        observed_data = user_takeout_object.user_data
        observed_images = user_takeout_object.user_images
        self.assertEqual(expected_data, observed_data)
        observed_json = json.dumps(observed_data)
        expected_json = json.dumps(expected_data)
        self.assertEqual(json.loads(expected_json), json.loads(observed_json))
        expected_images = []
        self.assertEqual(expected_images, observed_images)