Пример #1
0
    def test_demo_exploration(self):
        exp_services.load_demo('1')
        rights_manager.release_ownership_of_exploration(
            self.system_user, '1')
        exp_rights = rights_manager.get_exploration_rights('1')

        self.assertTrue(rights_manager.check_can_access_activity(
            self.user_a, exp_rights))
        self.assertTrue(rights_manager.check_can_edit_activity(
            self.user_a, exp_rights))
        self.assertTrue(rights_manager.check_can_translate_activity(
            self.user_a, exp_rights))
        self.assertFalse(rights_manager.check_can_delete_activity(
            self.user_a, exp_rights))

        self.assertTrue(rights_manager.check_can_access_activity(
            self.user_admin, exp_rights))
        self.assertTrue(rights_manager.check_can_edit_activity(
            self.user_admin, exp_rights))
        self.assertTrue(rights_manager.check_can_translate_activity(
            self.user_admin, exp_rights))
        self.assertTrue(rights_manager.check_can_delete_activity(
            self.user_admin, exp_rights))

        self.assertTrue(rights_manager.check_can_access_activity(
            self.user_moderator, exp_rights))
        self.assertTrue(rights_manager.check_can_edit_activity(
            self.user_moderator, exp_rights))
        self.assertTrue(rights_manager.check_can_translate_activity(
            self.user_moderator, exp_rights))
        self.assertTrue(rights_manager.check_can_delete_activity(
            self.user_moderator, exp_rights))
Пример #2
0
    def setUp(self):
        """Create exploration with two versions"""
        super(VersioningIntegrationTest, self).setUp()

        self.EXP_ID = '0'

        exp_services.load_demo(self.EXP_ID)
        rights_manager.release_ownership_of_exploration(
            feconf.SYSTEM_COMMITTER_ID, self.EXP_ID)

        self.login(self.EDITOR_EMAIL)
        self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL)

        # In version 2, change the objective and the initial state content.
        exploration = exp_services.get_exploration_by_id(self.EXP_ID)
        exp_services.update_exploration(
            self.editor_id, self.EXP_ID, [{
                'cmd': 'edit_exploration_property',
                'property_name': 'objective',
                'new_value': 'the objective',
            }, {
                'cmd': 'edit_state_property',
                'property_name': 'content',
                'state_name': exploration.init_state_name,
                'new_value': [{'type': 'text', 'value': 'ABC'}],
            }], 'Change objective and init state content')
Пример #3
0
    def test_community_owned_exploration(self):
        with self.swap(
                subscription_services, 'subscribe_to_thread', self._null_fn
            ), self.swap(
                subscription_services, 'subscribe_to_exploration',
                self._null_fn):
            # User A adds user B as an editor to the exploration.
            rights_manager.assign_role_for_exploration(
                self.user_a_id, self.EXP_ID_1, self.user_b_id,
                rights_manager.ROLE_EDITOR)
            # The exploration becomes community-owned.
            rights_manager.publish_exploration(self.user_a_id, self.EXP_ID_1)
            rights_manager.release_ownership_of_exploration(
                self.user_a_id, self.EXP_ID_1)
            # User C edits the exploration.
            exp_services.update_exploration(
                self.user_c_id, self.EXP_ID_1, [], 'Update exploration')

        self._run_one_off_job()

        # User A and user B are subscribed to the exploration; user C is not.
        user_a_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_a_id)
        user_b_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_b_id)
        user_c_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_c_id, strict=False)

        self.assertEqual(
            user_a_subscriptions_model.activity_ids, [self.EXP_ID_1])
        self.assertEqual(
            user_b_subscriptions_model.activity_ids, [self.EXP_ID_1])
        self.assertEqual(user_c_subscriptions_model, None)
Пример #4
0
    def test_demo_exploration(self):
        exp_services.load_demo('1')
        rights_manager.release_ownership_of_exploration(
            feconf.SYSTEM_COMMITTER_ID, '1')

        self.assertTrue(
            rights_manager.Actor(self.user_id_a).can_play(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_a).can_view(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_a).can_edit(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertFalse(
            rights_manager.Actor(self.user_id_a).can_delete(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))

        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_play(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_view(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_edit(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_delete(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
Пример #5
0
    def test_contribution_msec_updates_on_published_explorations(self):
        exploration = self.save_new_valid_exploration(
            self.EXP_ID, self.admin_id, end_state_name='End')
        init_state_name = exploration.init_state_name
        exp_services.publish_exploration_and_update_user_profiles(
            self.admin_id, self.EXP_ID)

        # Test all owners and editors of exploration after publication have
        # updated first contribution times in msecs.
        self.assertIsNotNone(user_services.get_user_settings(
            self.admin_id).first_contribution_msec)

        # Test editor of published exploration has updated contribution time.
        rights_manager.release_ownership_of_exploration(
            self.admin_id, self.EXP_ID)

        exp_services.update_exploration(
            self.editor_id, self.EXP_ID, [{
                'cmd': 'edit_state_property',
                'state_name': init_state_name,
                'property_name': 'widget_id',
                'new_value': 'MultipleChoiceInput'
            }], 'commit')

        self.assertIsNotNone(user_services.get_user_settings(
            self.editor_id).first_contribution_msec)
Пример #6
0
    def test_community_owned_exploration(self):
        with self.swap(
            subscription_services, 'subscribe_to_thread', self._null_fn
            ), self.swap(
                subscription_services, 'subscribe_to_exploration', self._null_fn
            ):
            # User A adds user B as an editor to the exploration.
            rights_manager.assign_role_for_exploration(
                self.user_a, self.EXP_ID_1, self.user_b_id,
                rights_manager.ROLE_EDITOR)
            # The exploration becomes community-owned.
            rights_manager.publish_exploration(self.user_a, self.EXP_ID_1)
            rights_manager.release_ownership_of_exploration(
                self.user_a, self.EXP_ID_1)
            # User C edits the exploration.
            exp_services.update_exploration(
                self.user_c_id, self.EXP_ID_1, [], 'Update exploration')

        self._run_one_off_job()

        # User A and user B are subscribed to the exploration; user C is not.
        user_a_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_a_id)
        user_b_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_b_id)
        user_c_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_c_id, strict=False)

        self.assertEqual(
            user_a_subscriptions_model.activity_ids, [self.EXP_ID_1])
        self.assertEqual(
            user_b_subscriptions_model.activity_ids, [self.EXP_ID_1])
        self.assertEqual(user_c_subscriptions_model, None)
Пример #7
0
    def test_contribution_msec_updates_on_published_explorations(self):
        exploration = self.save_new_valid_exploration(self.EXP_ID,
                                                      self.admin_id,
                                                      end_state_name='End')
        init_state_name = exploration.init_state_name
        exp_services.publish_exploration_and_update_user_profiles(
            self.admin_id, self.EXP_ID)

        # Test all owners and editors of exploration after publication have
        # updated first contribution times in msecs.
        self.assertIsNotNone(
            user_services.get_user_settings(
                self.admin_id).first_contribution_msec)

        # Test editor of published exploration has updated contribution time.
        rights_manager.release_ownership_of_exploration(
            self.admin_id, self.EXP_ID)

        exp_services.update_exploration(self.editor_id, self.EXP_ID,
                                        [{
                                            'cmd': 'edit_state_property',
                                            'state_name': init_state_name,
                                            'property_name': 'widget_id',
                                            'new_value': 'MultipleChoiceInput'
                                        }], 'commit')

        self.assertIsNotNone(
            user_services.get_user_settings(
                self.editor_id).first_contribution_msec)
Пример #8
0
    def test_demo_exploration(self):
        exp_services.load_demo('1')
        rights_manager.release_ownership_of_exploration(
            feconf.SYSTEM_COMMITTER_ID, '1')

        self.assertTrue(
            rights_manager.Actor(self.user_id_a).can_play(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_a).can_view(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_a).can_edit(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertFalse(
            rights_manager.Actor(self.user_id_a).can_delete(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))

        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_play(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_view(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_edit(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_delete(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '1'))
Пример #9
0
    def test_contribution_msec_updates_on_published_explorations(self):
        exploration = self.save_new_valid_exploration(
            self.EXP_ID, self.admin_id, end_state_name='End')
        init_state_name = exploration.init_state_name

        # Test that no contribution time is set.
        job_id = (
            user_jobs_one_off.UserFirstContributionMsecOneOffJob.create_new())
        user_jobs_one_off.UserFirstContributionMsecOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()
        self.assertIsNone(
            user_services.get_user_settings(
                self.admin_id).first_contribution_msec)

        # Test all owners and editors of exploration after publication have
        # updated times.
        exp_services.publish_exploration_and_update_user_profiles(
            self.admin, self.EXP_ID)
        rights_manager.release_ownership_of_exploration(
            self.admin, self.EXP_ID)
        exp_services.update_exploration(
            self.editor_id, self.EXP_ID, [{
                'cmd': 'edit_state_property',
                'state_name': init_state_name,
                'property_name': 'widget_id',
                'new_value': 'MultipleChoiceInput'
            }], 'commit')
        job_id = (
            user_jobs_one_off.UserFirstContributionMsecOneOffJob.create_new())
        user_jobs_one_off.UserFirstContributionMsecOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()
        self.assertIsNotNone(user_services.get_user_settings(
            self.admin_id).first_contribution_msec)
        self.assertIsNotNone(user_services.get_user_settings(
            self.editor_id).first_contribution_msec)
Пример #10
0
    def setUp(self):
        """Create exploration with two versions"""
        super(VersioningIntegrationTest, self).setUp()

        self.EXP_ID = "0"

        exp_services.load_demo(self.EXP_ID)
        rights_manager.release_ownership_of_exploration(feconf.SYSTEM_COMMITTER_ID, self.EXP_ID)

        self.login(self.EDITOR_EMAIL)
        self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL)

        # In version 2, change the objective and the initial state content.
        exploration = exp_services.get_exploration_by_id(self.EXP_ID)
        exp_services.update_exploration(
            self.editor_id,
            self.EXP_ID,
            [
                {"cmd": "edit_exploration_property", "property_name": "objective", "new_value": "the objective"},
                {
                    "cmd": "edit_state_property",
                    "property_name": "content",
                    "state_name": exploration.init_state_name,
                    "new_value": [{"type": "text", "value": "ABC"}],
                },
            ],
            "Change objective and init state content",
        )
Пример #11
0
    def test_non_splash_page_demo_exploration(self):
        # Note: there is no difference between permissions for demo
        # explorations, whether or not they are on the splash page.
        exp_services.load_demo('3')
        rights_manager.release_ownership_of_exploration(
            feconf.SYSTEM_COMMITTER_ID, '3')

        self.assertTrue(
            rights_manager.Actor(self.user_id_a).can_play(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_a).can_view(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertTrue(rights_manager.Actor(
            self.user_id_a).can_edit(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertFalse(rights_manager.Actor(
            self.user_id_a).can_delete(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))

        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_play(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_view(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertTrue(rights_manager.Actor(
            self.user_id_admin).can_edit(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_delete(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
Пример #12
0
    def setUp(self):
        """Create exploration with two versions"""
        super(VersioningIntegrationTest, self).setUp()

        self.EXP_ID = '0'

        exp_services.load_demo(self.EXP_ID)
        rights_manager.release_ownership_of_exploration(
            feconf.SYSTEM_COMMITTER_ID, self.EXP_ID)

        self.login(self.EDITOR_EMAIL)

        # In version 2, change the objective and the initial state content.
        exploration = exp_services.get_exploration_by_id(self.EXP_ID)
        exp_services.update_exploration(
            self.EDITOR_EMAIL, self.EXP_ID,
            [{
                'cmd': 'edit_exploration_property',
                'property_name': 'objective',
                'new_value': 'the objective',
            }, {
                'cmd': 'edit_state_property',
                'property_name': 'content',
                'state_name': exploration.init_state_name,
                'new_value': [{
                    'type': 'text',
                    'value': 'ABC'
                }],
            }], 'Change objective and init state content')
Пример #13
0
    def test_non_splash_page_demo_exploration(self):
        # Note: there is no difference between permissions for demo
        # explorations, whether or not they are on the splash page.
        exp_services.load_demo('3')
        rights_manager.release_ownership_of_exploration(
            feconf.SYSTEM_COMMITTER_ID, '3')

        self.assertTrue(
            rights_manager.Actor(self.user_id_a).can_play(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_a).can_view(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertTrue(rights_manager.Actor(
            self.user_id_a).can_edit(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertFalse(rights_manager.Actor(
            self.user_id_a).can_delete(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))

        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_play(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_view(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertTrue(rights_manager.Actor(
            self.user_id_admin).can_edit(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
        self.assertTrue(
            rights_manager.Actor(self.user_id_admin).can_delete(
                rights_manager.ACTIVITY_TYPE_EXPLORATION, '3'))
Пример #14
0
    def test_non_splash_page_demo_exploration(self):
        # Note: there is no difference between permissions for demo
        # explorations, whether or not they are on the splash page.
        exp_services.load_demo('3')
        rights_manager.release_ownership_of_exploration(
            self.system_user, '3')
        exp_rights = rights_manager.get_exploration_rights('3')

        self.assertTrue(rights_manager.check_can_access_activity(
            self.user_a, exp_rights))
        self.assertTrue(rights_manager.check_can_edit_activity(
            self.user_a, exp_rights))
        self.assertTrue(rights_manager.check_can_translate_activity(
            self.user_a, exp_rights))
        self.assertFalse(rights_manager.check_can_delete_activity(
            self.user_a, exp_rights))

        self.assertTrue(rights_manager.check_can_access_activity(
            self.user_admin, exp_rights))
        self.assertTrue(rights_manager.check_can_edit_activity(
            self.user_admin, exp_rights))
        self.assertTrue(rights_manager.check_can_translate_activity(
            self.user_admin, exp_rights))
        self.assertTrue(rights_manager.check_can_delete_activity(
            self.user_admin, exp_rights))

        self.assertTrue(rights_manager.check_can_access_activity(
            self.user_moderator, exp_rights))
        self.assertTrue(rights_manager.check_can_edit_activity(
            self.user_moderator, exp_rights))
        self.assertTrue(rights_manager.check_can_translate_activity(
            self.user_moderator, exp_rights))
        self.assertTrue(rights_manager.check_can_delete_activity(
            self.user_moderator, exp_rights))
Пример #15
0
    def test_contribution_msec_updates_on_published_explorations(self):
        exploration = self.save_new_valid_exploration(
            self.EXP_ID, self.admin_id, end_state_name='End')
        init_state_name = exploration.init_state_name

        # Test that no contribution time is set.
        job_id = (
            user_jobs_one_off.UserFirstContributionMsecOneOffJob.create_new())
        user_jobs_one_off.UserFirstContributionMsecOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()
        self.assertIsNone(
            user_services.get_user_settings(
                self.admin_id).first_contribution_msec)

        # Test all owners and editors of exploration after publication have
        # updated times.
        exp_services.publish_exploration_and_update_user_profiles(
            self.admin_id, self.EXP_ID)
        rights_manager.release_ownership_of_exploration(
            self.admin_id, self.EXP_ID)
        exp_services.update_exploration(
            self.editor_id, self.EXP_ID, [{
                'cmd': 'edit_state_property',
                'state_name': init_state_name,
                'property_name': 'widget_id',
                'new_value': 'MultipleChoiceInput'
            }], 'commit')
        job_id = (
            user_jobs_one_off.UserFirstContributionMsecOneOffJob.create_new())
        user_jobs_one_off.UserFirstContributionMsecOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()
        self.assertIsNotNone(user_services.get_user_settings(
            self.admin_id).first_contribution_msec)
        self.assertIsNotNone(user_services.get_user_settings(
            self.editor_id).first_contribution_msec)
Пример #16
0
    def setUp(self):
        super(AudioDevHandlerTest, self).setUp()
        exp_services.delete_demo('0')
        self.system_user = user_services.get_system_user()
        exp_services.load_demo('0')

        rights_manager.release_ownership_of_exploration(self.system_user, '0')
        self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
Пример #17
0
    def setUp(self):
        """Load a demo exploration and register self.EDITOR_EMAIL."""
        super(ImageHandlerTest, self).setUp()

        exp_services.delete_demo('0')
        exp_services.load_demo('0')
        rights_manager.release_ownership_of_exploration(
            feconf.SYSTEM_COMMITTER_ID, '0')
        self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
Пример #18
0
 def _reload_exploration(self, exploration_id):
     if feconf.DEV_MODE:
         logging.info('[ADMIN] %s reloaded exploration %s' %
                      (self.user_id, exploration_id))
         exp_services.load_demo(unicode(exploration_id))
         rights_manager.release_ownership_of_exploration(
             feconf.SYSTEM_COMMITTER_ID, unicode(exploration_id))
     else:
         raise Exception('Cannot reload an exploration in production.')
Пример #19
0
 def _reload_exploration(self, exploration_id):
     if constants.DEV_MODE:
         logging.info('[ADMIN] %s reloaded exploration %s' %
                      (self.user_id, exploration_id))
         exp_services.load_demo(unicode(exploration_id))
         rights_manager.release_ownership_of_exploration(
             user_services.get_system_user(), unicode(exploration_id))
     else:
         raise Exception('Cannot reload an exploration in production.')
Пример #20
0
    def put(self, exploration_id):
        """Updates the editing rights for the given exploration."""
        exploration = exp_fetchers.get_exploration_by_id(exploration_id)
        version = self.normalized_payload.get('version')
        _require_valid_version(version, exploration.version)

        make_community_owned = (
            self.normalized_payload.get('make_community_owned'))
        new_member_username = self.normalized_payload.get(
            'new_member_username')
        new_member_role = self.normalized_payload.get('new_member_role')
        viewable_if_private = self.normalized_payload.get(
            'viewable_if_private')

        if new_member_username:
            new_member_id = user_services.get_user_id_from_username(
                new_member_username)
            if new_member_id is None:
                raise self.InvalidInputException(
                    'Sorry, we could not find the specified user.')
            if new_member_id == self.user_id:
                raise self.InvalidInputException(
                    'Users are not allowed to assign other roles to themselves'
                )
            rights_manager.assign_role_for_exploration(self.user,
                                                       exploration_id,
                                                       new_member_id,
                                                       new_member_role)
            email_manager.send_role_notification_email(self.user_id,
                                                       new_member_id,
                                                       new_member_role,
                                                       exploration_id,
                                                       exploration.title)

        elif make_community_owned:
            exploration = exp_fetchers.get_exploration_by_id(exploration_id)
            try:
                exploration.validate(strict=True)
            except utils.ValidationError as e:
                raise self.InvalidInputException(e)

            rights_manager.release_ownership_of_exploration(
                self.user, exploration_id)

        elif viewable_if_private is not None:
            rights_manager.set_private_viewability_of_exploration(
                self.user, exploration_id, viewable_if_private)

        else:
            raise self.InvalidInputException(
                'No change was made to this exploration.')

        self.render_json({
            'rights':
            rights_manager.get_exploration_rights(exploration_id).to_dict()
        })
Пример #21
0
    def setUp(self):
        """Load a demo exploration and register self.EDITOR_EMAIL."""
        super(AssetDevHandlerImageTests, self).setUp()

        exp_services.delete_demo('0')
        self.system_user = user_services.get_system_user()
        exp_services.load_demo('0')

        rights_manager.release_ownership_of_exploration(self.system_user, '0')
        self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
Пример #22
0
 def _reload_exploration(self, exploration_id):
     if feconf.DEV_MODE:
         logging.info(
             '[ADMIN] %s reloaded exploration %s' %
             (self.user_id, exploration_id))
         exp_services.load_demo(unicode(exploration_id))
         rights_manager.release_ownership_of_exploration(
             feconf.SYSTEM_COMMITTER_ID, unicode(exploration_id))
     else:
         raise Exception('Cannot reload an exploration in production.')
Пример #23
0
    def setUp(self):
        super(AssetDevHandlerAudioTest, self).setUp()
        exp_services.delete_demo('0')
        self.system_user = user_services.get_system_user()
        exp_services.load_demo('0')

        rights_manager.release_ownership_of_exploration(self.system_user, '0')
        self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)

        mock_accepted_audio_extensions = {
            'mp3': ['audio/mp3'],
            'flac': ['audio/flac']
        }

        self.accepted_audio_extensions_swap = self.swap(
            feconf, 'ACCEPTED_AUDIO_EXTENSIONS',
            mock_accepted_audio_extensions)
Пример #24
0
    def _reload_exploration(self, exploration_id):
        """Reloads the exploration in dev_mode corresponding to the given
        exploration id.

        Args:
            exploration_id: str. The exploration id.

        Raises:
            Exception: Cannot reload an exploration in production.
        """
        if constants.DEV_MODE:
            logging.info('[ADMIN] %s reloaded exploration %s' %
                         (self.user_id, exploration_id))
            exp_services.load_demo(unicode(exploration_id))
            rights_manager.release_ownership_of_exploration(
                user_services.get_system_user(), unicode(exploration_id))
        else:
            raise Exception('Cannot reload an exploration in production.')
Пример #25
0
    def test_user_banning(self):
        """Test that banned users are banned."""

        exp_id = '0'
        exp_services.load_demo(exp_id)
        rights_manager.release_ownership_of_exploration(
            feconf.SYSTEM_COMMITTER_ID, exp_id)

        # Sign-up new editors Joe and Sandra.
        self.signup('*****@*****.**', 'joe')
        self.signup('*****@*****.**', 'sandra')

        # Joe logs in.
        self.login('*****@*****.**')

        response = self.testapp.get(feconf.LIBRARY_INDEX_URL)
        self.assertEqual(response.status_int, 200)
        response = self.testapp.get('/create/%s' % exp_id)
        self.assertEqual(response.status_int, 200)
        self.assert_can_edit(response.body)

        # Ban joe.
        config_services.set_property(
            feconf.SYSTEM_COMMITTER_ID, 'banned_usernames', ['joe'])

        # Test that Joe is banned. (He can still access the library page.)
        response = self.testapp.get(
            feconf.LIBRARY_INDEX_URL, expect_errors=True)
        self.assertEqual(response.status_int, 200)
        response = self.testapp.get('/create/%s' % exp_id, expect_errors=True)
        self.assertEqual(response.status_int, 200)
        self.assert_cannot_edit(response.body)

        # Joe logs out.
        self.logout()

        # Sandra logs in and is unaffected.
        self.login('*****@*****.**')
        response = self.testapp.get('/create/%s' % exp_id)
        self.assertEqual(response.status_int, 200)
        self.assert_can_edit(response.body)
        self.logout()
Пример #26
0
    def test_user_banning(self):
        """Test that banned users are banned."""

        exp_id = '0'
        exp_services.load_demo(exp_id)
        rights_manager.release_ownership_of_exploration(
            feconf.SYSTEM_COMMITTER_ID, exp_id)

        # Sign-up new editors Joe and Sandra.
        self.signup('*****@*****.**', 'joe')
        self.signup('*****@*****.**', 'sandra')

        # Joe logs in.
        self.login('*****@*****.**')

        response = self.testapp.get(feconf.GALLERY_URL)
        self.assertEqual(response.status_int, 200)
        response = self.testapp.get('/create/%s' % exp_id)
        self.assertEqual(response.status_int, 200)
        self.assert_can_edit(response.body)

        # Ban joe.
        config_services.set_property(
            feconf.SYSTEM_COMMITTER_ID, 'banned_usernames', ['joe'])

        # Test that Joe is banned. (He can still access the gallery.)
        response = self.testapp.get(feconf.GALLERY_URL, expect_errors=True)
        self.assertEqual(response.status_int, 200)
        response = self.testapp.get('/create/%s' % exp_id, expect_errors=True)
        self.assertEqual(response.status_int, 200)
        self.assert_cannot_edit(response.body)

        # Joe logs out.
        self.logout()

        # Sandra logs in and is unaffected.
        self.login('*****@*****.**')
        response = self.testapp.get('/create/%s' % exp_id)
        self.assertEqual(response.status_int, 200)
        self.assert_can_edit(response.body)
        self.logout()
Пример #27
0
    def test_user_banning(self):
        """Test that banned users are banned."""

        EXP_ID = "0"
        exp_services.load_demo(EXP_ID)
        rights_manager.release_ownership_of_exploration(feconf.SYSTEM_COMMITTER_ID, EXP_ID)

        # Sign-up new editors Joe and Sandra.
        self.signup("*****@*****.**", "joe")
        self.signup("*****@*****.**", "sandra")

        # Joe logs in.
        self.login("*****@*****.**")

        response = self.testapp.get(feconf.GALLERY_URL)
        self.assertEqual(response.status_int, 200)
        response = self.testapp.get("/create/%s" % EXP_ID)
        self.assertEqual(response.status_int, 200)
        self.assert_can_edit(response.body)

        # Ban joe.
        config_services.set_property(feconf.SYSTEM_COMMITTER_ID, "banned_usernames", ["joe"])

        # Test that Joe is banned. (He can still access the gallery.)
        response = self.testapp.get(feconf.GALLERY_URL, expect_errors=True)
        self.assertEqual(response.status_int, 200)
        response = self.testapp.get("/create/%s" % EXP_ID, expect_errors=True)
        self.assertEqual(response.status_int, 200)
        self.assert_cannot_edit(response.body)

        # Joe logs out.
        self.logout()

        # Sandra logs in and is unaffected.
        self.login("*****@*****.**")
        response = self.testapp.get("/create/%s" % EXP_ID)
        self.assertEqual(response.status_int, 200)
        self.assert_can_edit(response.body)
        self.logout()
Пример #28
0
    def test_cannot_release_ownership_of_exploration_with_insufficient_rights(
            self):
        observed_log_messages = []

        def _mock_logging_function(msg, *args):
            """Mocks logging.error()."""
            observed_log_messages.append(msg % args)

        logging_swap = self.swap(logging, 'error', _mock_logging_function)

        assert_raises_regexp_context_manager = self.assertRaisesRegexp(
            Exception, 'The ownership of this exploration cannot be released.')

        with logging_swap, assert_raises_regexp_context_manager:
            rights_manager.release_ownership_of_exploration(
                self.viewer, self.exp_id)

        self.assertEqual(len(observed_log_messages), 1)
        self.assertEqual(
            observed_log_messages[0],
            'User %s tried to release ownership of exploration %s but was '
            'refused permission.' % (self.viewer_id, self.exp_id))
Пример #29
0
    def test_untrained_answers_handler(self):
        with self.swap(feconf, "SHOW_TRAINABLE_UNRESOLVED_ANSWERS", True):

            def _create_answer(value, count=1):
                return {"value": value, "count": count}

            def _create_training_data(*arg):
                return [_create_answer(value) for value in arg]

            # Load the fuzzy rules demo exploration.
            exp_services.load_demo("15")
            rights_manager.release_ownership_of_exploration(feconf.SYSTEM_COMMITTER_ID, "15")

            exploration_dict = self.get_json("%s/15" % feconf.EXPLORATION_INIT_URL_PREFIX)
            self.assertEqual(exploration_dict["exploration"]["title"], "Demonstrating fuzzy rules")

            # This test uses the interaction which supports numeric input.
            state_name = "text"

            self.assertIn(state_name, exploration_dict["exploration"]["states"])
            self.assertEqual(exploration_dict["exploration"]["states"][state_name]["interaction"]["id"], "TextInput")

            # Input happy since there is an explicit rule checking for that.
            result_dict = self.submit_answer("15", state_name, "happy")

            # Input text not at all similar to happy (default outcome).
            self.submit_answer("15", state_name, "sad")

            # Input cheerful: this is current training data and falls under the
            # fuzzy rule.
            self.submit_answer("15", state_name, "cheerful")

            # Input joyful: this is not training data but will be classified
            # under the fuzzy rule.
            self.submit_answer("15", state_name, "joyful")

            # Log in as an editor.
            self.login(self.EDITOR_EMAIL)
            response = self.testapp.get("/create/15")
            csrf_token = self.get_csrf_token_from_response(response)
            url = str("/createhandler/training_data/15/%s" % state_name)

            exploration_dict = self.get_json("%s/15" % feconf.EXPLORATION_INIT_URL_PREFIX)

            # Only two of the four submitted answers should be unhandled.
            response_dict = self.get_json(url)
            self.assertEqual(response_dict["unhandled_answers"], _create_training_data("joyful", "sad"))

            # If the confirmed unclassified answers is trained for one of the
            # values, it should no longer show up in unhandled answers.
            self.put_json(
                "/createhandler/data/15",
                {
                    "change_list": [
                        {
                            "cmd": exp_domain.CMD_EDIT_STATE_PROPERTY,
                            "state_name": state_name,
                            "property_name": (exp_domain.STATE_PROPERTY_INTERACTION_UNCLASSIFIED_ANSWERS),
                            "new_value": ["sad"],
                        }
                    ],
                    "commit_message": "Update confirmed unclassified answers",
                    "version": exploration_dict["version"],
                },
                csrf_token,
            )
            response_dict = self.get_json(url)
            self.assertEqual(response_dict["unhandled_answers"], _create_training_data("joyful"))

            exploration_dict = self.get_json("%s/15" % feconf.EXPLORATION_INIT_URL_PREFIX)

            # If one of the values is added to the training data of a fuzzy
            # rule, then it should not be returned as an unhandled answer.
            state = exploration_dict["exploration"]["states"][state_name]
            answer_group = state["interaction"]["answer_groups"][1]
            rule_spec = answer_group["rule_specs"][0]
            self.assertEqual(rule_spec["rule_type"], rule_domain.FUZZY_RULE_TYPE)
            rule_spec["inputs"]["training_data"].append("joyful")

            self.put_json(
                "/createhandler/data/15",
                {
                    "change_list": [
                        {
                            "cmd": exp_domain.CMD_EDIT_STATE_PROPERTY,
                            "state_name": state_name,
                            "property_name": (exp_domain.STATE_PROPERTY_INTERACTION_UNCLASSIFIED_ANSWERS),
                            "new_value": [],
                        },
                        {
                            "cmd": exp_domain.CMD_EDIT_STATE_PROPERTY,
                            "state_name": state_name,
                            "property_name": (exp_domain.STATE_PROPERTY_INTERACTION_ANSWER_GROUPS),
                            "new_value": state["interaction"]["answer_groups"],
                        },
                    ],
                    "commit_message": "Update confirmed unclassified answers",
                    "version": exploration_dict["version"],
                },
                csrf_token,
            )
            response_dict = self.get_json(url)
            self.assertEqual(response_dict["unhandled_answers"], _create_training_data("sad"))

            exploration_dict = self.get_json("%s/15" % feconf.EXPLORATION_INIT_URL_PREFIX)

            # If both are classified, then nothing should be returned
            # unhandled.
            self.put_json(
                "/createhandler/data/15",
                {
                    "change_list": [
                        {
                            "cmd": exp_domain.CMD_EDIT_STATE_PROPERTY,
                            "state_name": state_name,
                            "property_name": (exp_domain.STATE_PROPERTY_INTERACTION_UNCLASSIFIED_ANSWERS),
                            "new_value": ["sad"],
                        }
                    ],
                    "commit_message": "Update confirmed unclassified answers",
                    "version": exploration_dict["version"],
                },
                csrf_token,
            )
            response_dict = self.get_json(url)
            self.assertEqual(response_dict["unhandled_answers"], [])

            exploration_dict = self.get_json("%s/15" % feconf.EXPLORATION_INIT_URL_PREFIX)

            # If one of the existing training data elements in the fuzzy rule
            # is removed (5 in this case), but it is not backed up by an
            # answer, it will not be returned as potential training data.
            state = exploration_dict["exploration"]["states"][state_name]
            answer_group = state["interaction"]["answer_groups"][1]
            rule_spec = answer_group["rule_specs"][0]
            del rule_spec["inputs"]["training_data"][1]
            self.put_json(
                "/createhandler/data/15",
                {
                    "change_list": [
                        {
                            "cmd": exp_domain.CMD_EDIT_STATE_PROPERTY,
                            "state_name": state_name,
                            "property_name": (exp_domain.STATE_PROPERTY_INTERACTION_ANSWER_GROUPS),
                            "new_value": state["interaction"]["answer_groups"],
                        }
                    ],
                    "commit_message": "Update confirmed unclassified answers",
                    "version": exploration_dict["version"],
                },
                csrf_token,
            )
            response_dict = self.get_json(url)
            self.assertEqual(response_dict["unhandled_answers"], [])

            self.logout()
Пример #30
0
    def put(self, exploration_id):
        """Updates the editing rights for the given exploration."""
        exploration = exp_services.get_exploration_by_id(exploration_id)
        version = self.payload.get('version')
        _require_valid_version(version, exploration.version)

        is_public = self.payload.get('is_public')
        is_publicized = self.payload.get('is_publicized')
        is_community_owned = self.payload.get('is_community_owned')
        new_member_username = self.payload.get('new_member_username')
        new_member_role = self.payload.get('new_member_role')
        viewable_if_private = self.payload.get('viewable_if_private')

        if new_member_username:
            if not rights_manager.Actor(self.user_id).can_modify_roles(
                    rights_manager.ACTIVITY_TYPE_EXPLORATION, exploration_id):
                raise self.UnauthorizedUserException(
                    'Only an owner of this exploration can add or change '
                    'roles.')

            new_member_id = user_services.get_user_id_from_username(
                new_member_username)
            if new_member_id is None:
                raise Exception('Sorry, we could not find the specified user.')

            rights_manager.assign_role_for_exploration(self.user_id,
                                                       exploration_id,
                                                       new_member_id,
                                                       new_member_role)

        elif is_public is not None:
            exploration = exp_services.get_exploration_by_id(exploration_id)
            if is_public:
                try:
                    exploration.validate(strict=True)
                except utils.ValidationError as e:
                    raise self.InvalidInputException(e)

                exp_services.publish_exploration_and_update_user_profiles(
                    self.user_id, exploration_id)
                exp_services.index_explorations_given_ids([exploration_id])
            else:
                rights_manager.unpublish_exploration(self.user_id,
                                                     exploration_id)
                exp_services.delete_documents_from_search_index(
                    [exploration_id])

        elif is_publicized is not None:
            exploration = exp_services.get_exploration_by_id(exploration_id)
            if is_publicized:
                try:
                    exploration.validate(strict=True)
                except utils.ValidationError as e:
                    raise self.InvalidInputException(e)

                rights_manager.publicize_exploration(self.user_id,
                                                     exploration_id)
            else:
                rights_manager.unpublicize_exploration(self.user_id,
                                                       exploration_id)

        elif is_community_owned:
            exploration = exp_services.get_exploration_by_id(exploration_id)
            try:
                exploration.validate(strict=True)
            except utils.ValidationError as e:
                raise self.InvalidInputException(e)

            rights_manager.release_ownership_of_exploration(
                self.user_id, exploration_id)

        elif viewable_if_private is not None:
            rights_manager.set_private_viewability_of_exploration(
                self.user_id, exploration_id, viewable_if_private)

        else:
            raise self.InvalidInputException(
                'No change was made to this exploration.')

        self.render_json({
            'rights':
            rights_manager.get_exploration_rights(exploration_id).to_dict()
        })
Пример #31
0
def pre_delete_user(user_id):
    """Prepare user for the full deletion.
        1. Mark all the activities that are private and solely owned by the user
           being deleted as deleted.
        2. Disable all the email preferences.
        3. Mark the user as to be deleted.
        4. Create PendingDeletionRequestModel for the user.

    Args:
        user_id: str. The id of the user to be deleted. If the user_id
            corresponds to a profile user then only that profile is deleted.
            For a full user, all of its associated profile users are deleted
            too.
    """
    pending_deletion_requests = []
    user_settings = user_services.get_user_settings(user_id, strict=True)

    linked_profile_user_ids = [
        user.user_id for user in
        user_services.get_all_profiles_auth_details_by_parent_user_id(user_id)
    ]
    profile_users_settings_list = user_services.get_users_settings(
        linked_profile_user_ids)
    for profile_user_settings in profile_users_settings_list:
        profile_id = profile_user_settings.user_id
        user_services.mark_user_for_deletion(profile_id)
        pending_deletion_requests.append(
            wipeout_domain.PendingDeletionRequest.create_default(
                profile_id, profile_user_settings.email,
                profile_user_settings.role, [], []))
    explorations_to_be_deleted_ids = []
    collections_to_be_deleted_ids = []
    if user_settings.role != feconf.ROLE_ID_LEARNER:
        subscribed_exploration_summaries = (
            exp_fetchers.get_exploration_summaries_subscribed_to(user_id))

        explorations_to_be_deleted_ids = [
            exp_summary.id for exp_summary in subscribed_exploration_summaries
            if exp_summary.is_private()
            and exp_summary.is_solely_owned_by_user(user_id)
        ]
        exp_services.delete_explorations(user_id,
                                         explorations_to_be_deleted_ids)

        # Release ownership of explorations that are public and are solely owned
        # by the to-be-deleted user.
        explorations_to_release_ownership_ids = [
            exp_summary.id for exp_summary in subscribed_exploration_summaries
            if not exp_summary.is_private()
            and exp_summary.is_solely_owned_by_user(user_id)
        ]
        for exp_id in explorations_to_release_ownership_ids:
            rights_manager.release_ownership_of_exploration(
                user_services.get_system_user(), exp_id)

        explorations_to_remove_user_from_ids = [
            exp_summary.id for exp_summary in subscribed_exploration_summaries
            if not exp_summary.is_solely_owned_by_user(user_id)
        ]
        for exp_id in explorations_to_remove_user_from_ids:
            rights_manager.deassign_role_for_exploration(
                user_services.get_system_user(), exp_id, user_id)

        subscribed_collection_summaries = (
            collection_services.get_collection_summaries_subscribed_to(user_id)
        )
        collections_to_be_deleted_ids = [
            col_summary.id for col_summary in subscribed_collection_summaries
            if col_summary.is_private()
            and col_summary.is_solely_owned_by_user(user_id)
        ]
        collection_services.delete_collections(user_id,
                                               collections_to_be_deleted_ids)

        # Release ownership of collections that are public and are solely owned
        # by the to-be-deleted user.
        collections_to_release_ownership_ids = [
            col_summary.id for col_summary in subscribed_collection_summaries
            if not col_summary.is_private()
            and col_summary.is_solely_owned_by_user(user_id)
        ]
        for col_id in collections_to_release_ownership_ids:
            rights_manager.release_ownership_of_collection(
                user_services.get_system_user(), col_id)

        collections_to_remove_user_from_ids = [
            col_summary.id for col_summary in subscribed_collection_summaries
            if not col_summary.is_solely_owned_by_user(user_id)
        ]
        for col_id in collections_to_remove_user_from_ids:
            rights_manager.deassign_role_for_collection(
                user_services.get_system_user(), col_id, user_id)

        topic_services.deassign_user_from_all_topics(
            user_services.get_system_user(), user_id)

        # Set all the user's email preferences to False in order to disable all
        # ordinary emails that could be sent to the users.
        user_services.update_email_preferences(user_id, False, False, False,
                                               False)

    user_services.mark_user_for_deletion(user_id)
    pending_deletion_requests.append(
        wipeout_domain.PendingDeletionRequest.create_default(
            user_id, user_settings.email, user_settings.role,
            explorations_to_be_deleted_ids, collections_to_be_deleted_ids))

    save_pending_deletion_requests(pending_deletion_requests)
Пример #32
0
    def post(self):
        """Handles POST requests."""
        try:
            if self.payload.get('action') == 'reload_exploration':
                exploration_id = self.payload.get('exploration_id')
                logging.info(
                    '[ADMIN] %s reloaded exploration %s' %
                    (self.user_id, exploration_id))
                exp_services.load_demo(unicode(exploration_id))
                rights_manager.release_ownership_of_exploration(
                    feconf.SYSTEM_COMMITTER_ID, unicode(exploration_id))
            elif self.payload.get('action') == 'reload_collection':
                collection_id = self.payload.get('collection_id')
                logging.info(
                    '[ADMIN] %s reloaded collection %s' %
                    (self.user_id, collection_id))
                collection_services.load_demo(unicode(collection_id))
                rights_manager.release_ownership_of_collection(
                    feconf.SYSTEM_COMMITTER_ID, unicode(collection_id))
            elif self.payload.get('action') == 'clear_search_index':
                exp_services.clear_search_index()
            elif self.payload.get('action') == 'save_config_properties':
                new_config_property_values = self.payload.get(
                    'new_config_property_values')
                logging.info('[ADMIN] %s saved config property values: %s' %
                             (self.user_id, new_config_property_values))
                for (name, value) in new_config_property_values.iteritems():
                    config_services.set_property(self.user_id, name, value)
            elif self.payload.get('action') == 'revert_config_property':
                config_property_id = self.payload.get('config_property_id')
                logging.info('[ADMIN] %s reverted config property: %s' %
                             (self.user_id, config_property_id))
                config_services.revert_property(
                    self.user_id, config_property_id)
            elif self.payload.get('action') == 'start_new_job':
                for klass in jobs_registry.ONE_OFF_JOB_MANAGERS:
                    if klass.__name__ == self.payload.get('job_type'):
                        klass.enqueue(klass.create_new())
                        break
            elif self.payload.get('action') == 'cancel_job':
                job_id = self.payload.get('job_id')
                job_type = self.payload.get('job_type')
                for klass in jobs_registry.ONE_OFF_JOB_MANAGERS:
                    if klass.__name__ == job_type:
                        klass.cancel(job_id, self.user_id)
                        break
            elif self.payload.get('action') == 'start_computation':
                computation_type = self.payload.get('computation_type')
                for klass in jobs_registry.ALL_CONTINUOUS_COMPUTATION_MANAGERS:
                    if klass.__name__ == computation_type:
                        klass.start_computation()
                        break
            elif self.payload.get('action') == 'stop_computation':
                computation_type = self.payload.get('computation_type')
                for klass in jobs_registry.ALL_CONTINUOUS_COMPUTATION_MANAGERS:
                    if klass.__name__ == computation_type:
                        klass.stop_computation(self.user_id)
                        break
            elif self.payload.get('action') == 'upload_topic_similarities':
                data = self.payload.get('data')
                recommendations_services.update_topic_similarities(data)

            self.render_json({})
        except Exception as e:
            self.render_json({'error': unicode(e)})
            raise
Пример #33
0
    def post(self):
        """Handles POST requests."""
        try:
            if self.payload.get('action') == 'reload_exploration':
                exploration_id = self.payload.get('exploration_id')
                logging.info(
                    '[ADMIN] %s reloaded exploration %s' %
                    (self.user_id, exploration_id))
                exp_services.load_demo(unicode(exploration_id))
                rights_manager.release_ownership_of_exploration(
                    feconf.SYSTEM_COMMITTER_ID, unicode(exploration_id))
            elif self.payload.get('action') == 'reload_collection':
                collection_id = self.payload.get('collection_id')
                logging.info(
                    '[ADMIN] %s reloaded collection %s' %
                    (self.user_id, collection_id))
                collection_services.load_demo(unicode(collection_id))
                rights_manager.release_ownership_of_collection(
                    feconf.SYSTEM_COMMITTER_ID, unicode(collection_id))
            elif self.payload.get('action') == 'clear_search_index':
                exp_services.clear_search_index()
            elif self.payload.get('action') == 'save_config_properties':
                new_config_property_values = self.payload.get(
                    'new_config_property_values')
                logging.info('[ADMIN] %s saved config property values: %s' %
                             (self.user_id, new_config_property_values))
                for (name, value) in new_config_property_values.iteritems():
                    config_services.set_property(self.user_id, name, value)
            elif self.payload.get('action') == 'revert_config_property':
                config_property_id = self.payload.get('config_property_id')
                logging.info('[ADMIN] %s reverted config property: %s' %
                             (self.user_id, config_property_id))
                config_services.revert_property(
                    self.user_id, config_property_id)
            elif self.payload.get('action') == 'refresh_computed_property':
                computed_property_name = self.payload.get(
                    'computed_property_name')
                config_domain.Registry.get_config_property(
                    computed_property_name).refresh_default_value()
            elif self.payload.get('action') == 'start_new_job':
                for klass in jobs_registry.ONE_OFF_JOB_MANAGERS:
                    if klass.__name__ == self.payload.get('job_type'):
                        klass.enqueue(klass.create_new())
                        break
            elif self.payload.get('action') == 'cancel_job':
                job_id = self.payload.get('job_id')
                job_type = self.payload.get('job_type')
                for klass in jobs_registry.ONE_OFF_JOB_MANAGERS:
                    if klass.__name__ == job_type:
                        klass.cancel(job_id, self.user_id)
                        break
            elif self.payload.get('action') == 'start_computation':
                computation_type = self.payload.get('computation_type')
                for klass in jobs_registry.ALL_CONTINUOUS_COMPUTATION_MANAGERS:
                    if klass.__name__ == computation_type:
                        klass.start_computation()
                        break
            elif self.payload.get('action') == 'stop_computation':
                computation_type = self.payload.get('computation_type')
                for klass in jobs_registry.ALL_CONTINUOUS_COMPUTATION_MANAGERS:
                    if klass.__name__ == computation_type:
                        klass.stop_computation(self.user_id)
                        break
            elif self.payload.get('action') == 'upload_topic_similarities':
                data = self.payload.get('data')
                recommendations_services.update_topic_similarities(data)

            self.render_json({})
        except Exception as e:
            self.render_json({'error': unicode(e)})
            raise
Пример #34
0
    def post(self):
        """Generates structures for Android end-to-end tests.

        This handler generates structures for Android end-to-end tests in
        order to evaluate the integration of network requests from the
        Android client to the backend. This handler should only be called
        once (or otherwise raises an exception), and can only be used in
        development mode (this handler is unavailable in production).

        Note that the handler outputs an empty JSON dict when the request is
        successful.

        The specific structures that are generated:
            Topic: A topic with both a test story and a subtopic.
            Story: A story with 'android_interactions' as a exploration
                node.
            Exploration: 'android_interactions' from the local assets.
            Subtopic: A dummy subtopic to validate the topic.
            Skill: A dummy skill to validate the subtopic.

        Raises:
            Exception. When used in production mode.
            InvalidInputException. The topic is already
                created but not published.
            InvalidInputException. The topic is already published.
        """

        if not constants.DEV_MODE:
            raise Exception('Cannot load new structures data in production.')
        if topic_services.does_topic_with_name_exist('Android test'):
            topic = topic_fetchers.get_topic_by_name('Android test')
            topic_rights = topic_fetchers.get_topic_rights(topic.id,
                                                           strict=False)
            if topic_rights.topic_is_published:
                raise self.InvalidInputException(
                    'The topic is already published.')

            raise self.InvalidInputException(
                'The topic exists but is not published.')
        exp_id = '26'
        user_id = feconf.SYSTEM_COMMITTER_ID
        # Generate new Structure id for topic, story, skill and question.
        topic_id = topic_fetchers.get_new_topic_id()
        story_id = story_services.get_new_story_id()
        skill_id = skill_services.get_new_skill_id()
        question_id = question_services.get_new_question_id()

        # Create dummy skill and question.
        skill = self._create_dummy_skill(skill_id, 'Dummy Skill for Android',
                                         '<p>Dummy Explanation 1</p>')
        question = self._create_dummy_question(question_id, 'Question 1',
                                               [skill_id])
        question_services.add_question(user_id, question)
        question_services.create_new_question_skill_link(
            user_id, question_id, skill_id, 0.3)

        # Create and update topic to validate before publishing.
        topic = topic_domain.Topic.create_default_topic(
            topic_id, 'Android test', 'test-topic-one', 'description', 'fragm')
        topic.update_url_fragment('test-topic')
        topic.update_meta_tag_content('tag')
        topic.update_page_title_fragment_for_web('page title for topic')
        # Save the dummy image to the filesystem to be used as thumbnail.
        with utils.open_file(os.path.join(feconf.TESTS_DATA_DIR,
                                          'test_svg.svg'),
                             'rb',
                             encoding=None) as f:
            raw_image = f.read()
        fs = fs_services.GcsFileSystem(feconf.ENTITY_TYPE_TOPIC, topic_id)
        fs.commit('%s/test_svg.svg' % (constants.ASSET_TYPE_THUMBNAIL),
                  raw_image,
                  mimetype='image/svg+xml')
        # Update thumbnail properties.
        topic_services.update_thumbnail_filename(topic, 'test_svg.svg')
        topic.update_thumbnail_bg_color('#C6DCDA')

        # Add other structures to the topic.
        topic.add_canonical_story(story_id)
        topic.add_uncategorized_skill_id(skill_id)
        topic.add_subtopic(1, 'Test Subtopic Title', 'testsubtop')

        # Update and validate subtopic.
        topic_services.update_subtopic_thumbnail_filename(
            topic, 1, 'test_svg.svg')
        topic.update_subtopic_thumbnail_bg_color(1, '#FFFFFF')
        topic.update_subtopic_url_fragment(1, 'suburl')
        topic.move_skill_id_to_subtopic(None, 1, skill_id)
        subtopic_page = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                1, topic_id))

        # Upload local exploration to the datastore and enable feedback.
        exp_services.load_demo(exp_id)
        rights_manager.release_ownership_of_exploration(
            user_services.get_system_user(), exp_id)
        exp_services.update_exploration(
            user_id, exp_id, [
                exp_domain.ExplorationChange({
                    'cmd': exp_domain.CMD_EDIT_EXPLORATION_PROPERTY,
                    'property_name': 'correctness_feedback_enabled',
                    'new_value': True
                })
            ], 'Changed correctness_feedback_enabled.')

        # Add and update the exploration/node to the story.
        story = story_domain.Story.create_default_story(
            story_id, 'Android End to End testing', 'Description', topic_id,
            'android-end-to-end-testing')

        story.add_node('%s%d' % (story_domain.NODE_ID_PREFIX, 1),
                       'Testing with UI Automator')

        story.update_node_description(
            '%s%d' % (story_domain.NODE_ID_PREFIX, 1),
            'To test all Android interactions')
        story.update_node_exploration_id(
            '%s%d' % (story_domain.NODE_ID_PREFIX, 1), exp_id)

        # Save the dummy image to the filesystem to be used as thumbnail.
        with utils.open_file(os.path.join(feconf.TESTS_DATA_DIR,
                                          'test_svg.svg'),
                             'rb',
                             encoding=None) as f:
            raw_image = f.read()
        fs = fs_services.GcsFileSystem(feconf.ENTITY_TYPE_STORY, story_id)
        fs.commit('%s/test_svg.svg' % (constants.ASSET_TYPE_THUMBNAIL),
                  raw_image,
                  mimetype='image/svg+xml')

        story.update_node_thumbnail_filename(
            '%s%d' % (story_domain.NODE_ID_PREFIX, 1), 'test_svg.svg')
        story.update_node_thumbnail_bg_color(
            '%s%d' % (story_domain.NODE_ID_PREFIX, 1), '#F8BF74')

        # Update and validate the story.
        story.update_meta_tag_content('tag')
        story.update_thumbnail_filename('test_svg.svg')
        story.update_thumbnail_bg_color(
            constants.ALLOWED_THUMBNAIL_BG_COLORS['story'][0])

        # Save the previously created structures
        # (skill, story, topic, subtopic).
        skill_services.save_new_skill(user_id, skill)
        story_services.save_new_story(user_id, story)
        topic_services.save_new_topic(user_id, topic)
        subtopic_page_services.save_subtopic_page(
            user_id, subtopic_page, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Dummy Subtopic Title',
                    'url_fragment': 'dummy-fragment'
                })
            ])

        # Generates translation opportunities for the Contributor Dashboard.
        exp_ids_in_story = story.story_contents.get_all_linked_exp_ids()
        opportunity_services.add_new_exploration_opportunities(
            story_id, exp_ids_in_story)

        # Publish the story and topic.
        topic_services.publish_story(topic_id, story_id, user_id)
        topic_services.publish_topic(topic_id, user_id)

        # Upload thumbnails to be accessible through AssetsDevHandler.
        self._upload_thumbnail(topic_id, feconf.ENTITY_TYPE_TOPIC)
        self._upload_thumbnail(story_id, feconf.ENTITY_TYPE_STORY)
        self.render_json({})
Пример #35
0
    def test_untrained_answers_handler(self):
        with self.swap(feconf, 'SHOW_TRAINABLE_UNRESOLVED_ANSWERS', True):
            def _create_answer(value, count=1):
                return {'value': value, 'count': count}
            def _create_training_data(*arg):
                return [_create_answer(value) for value in arg]

            # Load the fuzzy rules demo exploration.
            exp_services.load_demo('15')
            rights_manager.release_ownership_of_exploration(
                feconf.SYSTEM_COMMITTER_ID, '15')

            exploration_dict = self.get_json(
                '%s/15' % feconf.EXPLORATION_INIT_URL_PREFIX)
            self.assertEqual(
                exploration_dict['exploration']['title'],
                'Demonstrating fuzzy rules')

            # This test uses the interaction which supports numeric input.
            state_name = 'text'

            self.assertIn(
                state_name, exploration_dict['exploration']['states'])
            self.assertEqual(
                exploration_dict['exploration']['states'][state_name][
                    'interaction']['id'], 'TextInput')

            # Input happy since there is an explicit rule checking for that.
            self.submit_answer('15', state_name, 'happy')

            # Input text not at all similar to happy (default outcome).
            self.submit_answer('15', state_name, 'sad')

            # Input cheerful: this is current training data and falls under the
            # fuzzy rule.
            self.submit_answer('15', state_name, 'cheerful')

            # Input joyful: this is not training data but will be classified
            # under the fuzzy rule.
            self.submit_answer('15', state_name, 'joyful')

            # Log in as an editor.
            self.login(self.EDITOR_EMAIL)
            response = self.testapp.get('/create/15')
            csrf_token = self.get_csrf_token_from_response(response)
            url = str('/createhandler/training_data/15/%s' % state_name)

            exploration_dict = self.get_json(
                '%s/15' % feconf.EXPLORATION_INIT_URL_PREFIX)

            # Only two of the four submitted answers should be unhandled.
            response_dict = self.get_json(url)
            self.assertEqual(
                response_dict['unhandled_answers'],
                _create_training_data('joyful', 'sad'))

            # If the confirmed unclassified answers is trained for one of the
            # values, it should no longer show up in unhandled answers.
            self.put_json('/createhandler/data/15', {
                'change_list': [{
                    'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY,
                    'state_name': state_name,
                    'property_name': (
                        exp_domain.STATE_PROPERTY_INTERACTION_UNCLASSIFIED_ANSWERS),
                    'new_value': ['sad']
                }],
                'commit_message': 'Update confirmed unclassified answers',
                'version': exploration_dict['version'],
            }, csrf_token)
            response_dict = self.get_json(url)
            self.assertEqual(
                response_dict['unhandled_answers'],
                _create_training_data('joyful'))

            exploration_dict = self.get_json(
                '%s/15' % feconf.EXPLORATION_INIT_URL_PREFIX)

            # If one of the values is added to the training data of a fuzzy
            # rule, then it should not be returned as an unhandled answer.
            state = exploration_dict['exploration']['states'][state_name]
            answer_group = state['interaction']['answer_groups'][1]
            rule_spec = answer_group['rule_specs'][0]
            self.assertEqual(
                rule_spec['rule_type'], rule_domain.FUZZY_RULE_TYPE)
            rule_spec['inputs']['training_data'].append('joyful')

            self.put_json('/createhandler/data/15', {
                'change_list': [{
                    'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY,
                    'state_name': state_name,
                    'property_name': (
                        exp_domain.STATE_PROPERTY_INTERACTION_UNCLASSIFIED_ANSWERS),
                    'new_value': []
                }, {
                    'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY,
                    'state_name': state_name,
                    'property_name': (
                        exp_domain.STATE_PROPERTY_INTERACTION_ANSWER_GROUPS),
                    'new_value': state['interaction']['answer_groups']
                }],
                'commit_message': 'Update confirmed unclassified answers',
                'version': exploration_dict['version'],
            }, csrf_token)
            response_dict = self.get_json(url)
            self.assertEqual(
                response_dict['unhandled_answers'],
                _create_training_data('sad'))

            exploration_dict = self.get_json(
                '%s/15' % feconf.EXPLORATION_INIT_URL_PREFIX)

            # If both are classified, then nothing should be returned
            # unhandled.
            self.put_json('/createhandler/data/15', {
                'change_list': [{
                    'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY,
                    'state_name': state_name,
                    'property_name': (
                        exp_domain.STATE_PROPERTY_INTERACTION_UNCLASSIFIED_ANSWERS),
                    'new_value': ['sad']
                }],
                'commit_message': 'Update confirmed unclassified answers',
                'version': exploration_dict['version'],
            }, csrf_token)
            response_dict = self.get_json(url)
            self.assertEqual(response_dict['unhandled_answers'], [])

            exploration_dict = self.get_json(
                '%s/15' % feconf.EXPLORATION_INIT_URL_PREFIX)

            # If one of the existing training data elements in the fuzzy rule
            # is removed (5 in this case), but it is not backed up by an
            # answer, it will not be returned as potential training data.
            state = exploration_dict['exploration']['states'][state_name]
            answer_group = state['interaction']['answer_groups'][1]
            rule_spec = answer_group['rule_specs'][0]
            del rule_spec['inputs']['training_data'][1]
            self.put_json('/createhandler/data/15', {
                'change_list': [{
                    'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY,
                    'state_name': state_name,
                    'property_name': (
                        exp_domain.STATE_PROPERTY_INTERACTION_ANSWER_GROUPS),
                    'new_value': state['interaction']['answer_groups']
                }],
                'commit_message': 'Update confirmed unclassified answers',
                'version': exploration_dict['version'],
            }, csrf_token)
            response_dict = self.get_json(url)
            self.assertEqual(response_dict['unhandled_answers'], [])

            self.logout()
Пример #36
0
def _remove_user_from_activities_with_associated_rights_models(
        user_id, use_user_subscriptions_ids):
    """Remove the user from exploration, collection, and topic models.

    Args:
        user_id: str. The ID of the user for which to remove the user from
            explorations, collections, and topics.
        use_user_subscriptions_ids: bool. Whether to use the IDs from user's
            UserSubscriptionsModel. When False the IDs are gathered via
            datastore queries.
    """
    if use_user_subscriptions_ids:
        subscribed_exploration_summaries = (
            exp_fetchers.get_exploration_summaries_subscribed_to(user_id))
    else:
        subscribed_exploration_summaries = (
            exp_fetchers.get_exploration_summaries_where_user_has_role(user_id)
        )

    explorations_to_be_deleted_ids = [
        exp_summary.id for exp_summary in subscribed_exploration_summaries
        if exp_summary.is_private()
        and exp_summary.is_solely_owned_by_user(user_id)
    ]
    exp_services.delete_explorations(user_id,
                                     explorations_to_be_deleted_ids,
                                     force_deletion=True)

    # Release ownership of explorations that are public and are solely owned
    # by the to-be-deleted user.
    explorations_to_release_ownership_ids = [
        exp_summary.id for exp_summary in subscribed_exploration_summaries
        if not exp_summary.is_private() and exp_summary.
        is_solely_owned_by_user(user_id) and not exp_summary.community_owned
    ]
    for exp_id in explorations_to_release_ownership_ids:
        rights_manager.release_ownership_of_exploration(
            user_services.get_system_user(), exp_id)

    explorations_to_remove_user_from_ids = [
        exp_summary.id for exp_summary in subscribed_exploration_summaries
        if not exp_summary.is_solely_owned_by_user(user_id)
        and exp_summary.does_user_have_any_role(user_id)
    ]
    for exp_id in explorations_to_remove_user_from_ids:
        rights_manager.deassign_role_for_exploration(
            user_services.get_system_user(), exp_id, user_id)

    if use_user_subscriptions_ids:
        subscribed_collection_summaries = (
            collection_services.get_collection_summaries_subscribed_to(user_id)
        )
    else:
        subscribed_collection_summaries = (
            collection_services.get_collection_summaries_where_user_has_role(
                user_id))

    collections_to_be_deleted_ids = [
        col_summary.id for col_summary in subscribed_collection_summaries
        if col_summary.is_private()
        and col_summary.is_solely_owned_by_user(user_id)
    ]
    collection_services.delete_collections(user_id,
                                           collections_to_be_deleted_ids,
                                           force_deletion=True)

    # Release ownership of collections that are public and are solely owned
    # by the to-be-deleted user.
    collections_to_release_ownership_ids = [
        col_summary.id for col_summary in subscribed_collection_summaries
        if not col_summary.is_private() and col_summary.
        is_solely_owned_by_user(user_id) and not col_summary.community_owned
    ]
    for col_id in collections_to_release_ownership_ids:
        rights_manager.release_ownership_of_collection(
            user_services.get_system_user(), col_id)

    collections_to_remove_user_from_ids = [
        col_summary.id for col_summary in subscribed_collection_summaries
        if not col_summary.is_solely_owned_by_user(user_id)
        and col_summary.does_user_have_any_role(user_id)
    ]
    for col_id in collections_to_remove_user_from_ids:
        rights_manager.deassign_role_for_collection(
            user_services.get_system_user(), col_id, user_id)

    topic_services.deassign_user_from_all_topics(
        user_services.get_system_user(), user_id)
Пример #37
0
    def put(self, exploration_id):
        """Updates the editing rights for the given exploration."""
        exploration = exp_services.get_exploration_by_id(exploration_id)
        version = self.payload.get('version')
        _require_valid_version(version, exploration.version)

        is_public = self.payload.get('is_public')
        is_publicized = self.payload.get('is_publicized')
        is_community_owned = self.payload.get('is_community_owned')
        new_member_username = self.payload.get('new_member_username')
        new_member_role = self.payload.get('new_member_role')
        viewable_if_private = self.payload.get('viewable_if_private')

        if new_member_username:
            if not rights_manager.Actor(
                    self.user_id).can_modify_roles(
                        rights_manager.ACTIVITY_TYPE_EXPLORATION,
                        exploration_id):
                raise self.UnauthorizedUserException(
                    'Only an owner of this exploration can add or change '
                    'roles.')

            new_member_id = user_services.get_user_id_from_username(
                new_member_username)
            if new_member_id is None:
                raise Exception(
                    'Sorry, we could not find the specified user.')

            rights_manager.assign_role_for_exploration(
                self.user_id, exploration_id, new_member_id, new_member_role)

        elif is_public is not None:
            exploration = exp_services.get_exploration_by_id(exploration_id)
            if is_public:
                try:
                    exploration.validate(strict=True)
                except utils.ValidationError as e:
                    raise self.InvalidInputException(e)

                exp_services.publish_exploration_and_update_user_profiles(
                    self.user_id, exploration_id)
                exp_services.index_explorations_given_ids([exploration_id])
            else:
                rights_manager.unpublish_exploration(
                    self.user_id, exploration_id)
                exp_services.delete_documents_from_search_index([
                    exploration_id])

        elif is_publicized is not None:
            exploration = exp_services.get_exploration_by_id(exploration_id)
            if is_publicized:
                try:
                    exploration.validate(strict=True)
                except utils.ValidationError as e:
                    raise self.InvalidInputException(e)

                rights_manager.publicize_exploration(
                    self.user_id, exploration_id)
            else:
                rights_manager.unpublicize_exploration(
                    self.user_id, exploration_id)

        elif is_community_owned:
            exploration = exp_services.get_exploration_by_id(exploration_id)
            try:
                exploration.validate(strict=True)
            except utils.ValidationError as e:
                raise self.InvalidInputException(e)

            rights_manager.release_ownership_of_exploration(
                self.user_id, exploration_id)

        elif viewable_if_private is not None:
            rights_manager.set_private_viewability_of_exploration(
                self.user_id, exploration_id, viewable_if_private)

        else:
            raise self.InvalidInputException(
                'No change was made to this exploration.')

        self.render_json({
            'rights': rights_manager.get_exploration_rights(
                exploration_id).to_dict()
        })
Пример #38
0
 def setUp(self):
     super(EditorTest, self).setUp()
     exp_services.load_demo('0')
     rights_manager.release_ownership_of_exploration(
         feconf.SYSTEM_COMMITTER_ID, '0')
Пример #39
0
def remove_user_from_activities_with_associated_rights_models(user_id):
    """Remove the user from exploration, collection, and topic models.

    Args:
        user_id: str. The ID of the user for which to remove the user from
            explorations, collections, and topics.
    """
    subscribed_exploration_summaries = (
        exp_fetchers.get_exploration_summaries_where_user_has_role(user_id))

    explorations_to_be_deleted_ids = [
        exp_summary.id for exp_summary in subscribed_exploration_summaries if
        exp_summary.is_private() and
        exp_summary.is_solely_owned_by_user(user_id)
    ]
    exp_services.delete_explorations(
        user_id, explorations_to_be_deleted_ids, force_deletion=True)

    # Release ownership of explorations that are public and are solely owned
    # by the to-be-deleted user.
    explorations_to_release_ownership_ids = [
        exp_summary.id for exp_summary in subscribed_exploration_summaries if
        not exp_summary.is_private() and
        exp_summary.is_solely_owned_by_user(user_id) and
        not exp_summary.community_owned
    ]
    for exp_id in explorations_to_release_ownership_ids:
        rights_manager.release_ownership_of_exploration(
            user_services.get_system_user(), exp_id)

    explorations_to_remove_user_from_ids = [
        exp_summary.id for exp_summary in subscribed_exploration_summaries if
        not exp_summary.is_solely_owned_by_user(user_id) and
        exp_summary.does_user_have_any_role(user_id)
    ]
    for exp_id in explorations_to_remove_user_from_ids:
        rights_manager.deassign_role_for_exploration(
            user_services.get_system_user(), exp_id, user_id)

    # To hard-delete explorations marked as deleted we are using the rights
    # model to retrieve the exploration as the summary model gets hard-deleted
    # while marking the exploration as deleted.
    explorations_rights = (
        rights_manager.get_exploration_rights_where_user_is_owner(user_id))
    explorations_to_be_deleted_ids = [
        exploration_rights.id for exploration_rights
        in explorations_rights if
        exploration_rights.is_private() and
        exploration_rights.is_solely_owned_by_user(user_id)
    ]
    exp_services.delete_explorations(
        user_id, explorations_to_be_deleted_ids, force_deletion=True)

    subscribed_collection_summaries = (
        collection_services.get_collection_summaries_where_user_has_role(
            user_id))

    collections_to_be_deleted_ids = [
        col_summary.id for col_summary in subscribed_collection_summaries if
        col_summary.is_private() and
        col_summary.is_solely_owned_by_user(user_id)
    ]
    collection_services.delete_collections(
        user_id, collections_to_be_deleted_ids, force_deletion=True)

    # Release ownership of collections that are public and are solely owned
    # by the to-be-deleted user.
    collections_to_release_ownership_ids = [
        col_summary.id for col_summary in subscribed_collection_summaries if
        not col_summary.is_private() and
        col_summary.is_solely_owned_by_user(user_id) and
        not col_summary.community_owned
    ]
    for col_id in collections_to_release_ownership_ids:
        rights_manager.release_ownership_of_collection(
            user_services.get_system_user(), col_id)

    collections_to_remove_user_from_ids = [
        col_summary.id for col_summary in subscribed_collection_summaries if
        not col_summary.is_solely_owned_by_user(user_id) and
        col_summary.does_user_have_any_role(user_id)
    ]
    for col_id in collections_to_remove_user_from_ids:
        rights_manager.deassign_role_for_collection(
            user_services.get_system_user(), col_id, user_id)

    # To hard-delete collections marked as deleted we are using the rights
    # model to retrieve the collection as the summary model gets hard-deleted
    # while marking the collection as deleted.
    collection_rights = (
        rights_manager.get_collection_rights_where_user_is_owner(user_id))
    collections_to_be_deleted_ids = [
        collection_rights.id for collection_rights in collection_rights if
        collection_rights.is_private() and
        collection_rights.is_solely_owned_by_user(user_id)
    ]
    collection_services.delete_collections(
        user_id, collections_to_be_deleted_ids, force_deletion=True)

    topic_services.deassign_user_from_all_topics(
        user_services.get_system_user(), user_id)