def test_exploration_subscription(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) # User A adds user C as a viewer of the exploration. rights_manager.assign_role_for_exploration( self.user_a_id, self.EXP_ID_1, self.user_c_id, rights_manager.ROLE_VIEWER) self._run_one_off_job() # Users A and 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_a_subscriptions_model.feedback_thread_ids, []) self.assertEqual(user_b_subscriptions_model.feedback_thread_ids, []) self.assertEqual(user_c_subscriptions_model, None)
def test_root_redirect_rules_for_logged_in_editors(self): self.login(self.TEST_CREATOR_EMAIL) creator_user_id = self.get_user_id_from_email(self.TEST_CREATOR_EMAIL) editor_user_id = self.get_user_id_from_email(self.TEST_EDITOR_EMAIL) exploration_id = '1_en_test_exploration' self.save_new_valid_exploration( exploration_id, creator_user_id, title='Test', category='Test', language_code='en') rights_manager.assign_role_for_exploration( creator_user_id, exploration_id, editor_user_id, rights_manager.ROLE_EDITOR) self.logout() self.login(self.TEST_EDITOR_EMAIL) exp_services.update_exploration( editor_user_id, exploration_id, [{ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'edited title' }, { 'cmd': 'edit_exploration_property', 'property_name': 'category', 'new_value': 'edited category' }], 'Change title and category') # Since user has edited one exploration created by another user, # going to '/' should redirect to the dashboard page. response = self.testapp.get('/') self.assertEqual(response.status_int, 302) self.assertIn('dashboard', response.headers['location']) self.logout()
def test_deletion_rights_for_published_exploration(self): """Test rights management for deletion of published explorations.""" published_exp_id = 'published_eid' exploration = exp_domain.Exploration.create_default_exploration( published_exp_id, 'A title', 'A category') exp_services.save_new_exploration(self.owner_id, exploration) rights_manager.assign_role_for_exploration( self.owner_id, published_exp_id, self.editor_id, rights_manager.ROLE_EDITOR) rights_manager.publish_exploration(self.owner_id, published_exp_id) self.login(self.EDITOR_EMAIL) response = self.testapp.delete( '/createhandler/data/%s' % published_exp_id, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.VIEWER_EMAIL) response = self.testapp.delete( '/createhandler/data/%s' % published_exp_id, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.OWNER_EMAIL) response = self.testapp.delete( '/createhandler/data/%s' % published_exp_id, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.ADMIN_EMAIL) response = self.testapp.delete( '/createhandler/data/%s' % published_exp_id) self.assertEqual(response.status_int, 200) self.logout()
def test_adding_new_exploration_viewer_role_does_not_result_in_subscription(self): exploration = exp_domain.Exploration.create_default_exploration(EXP_ID, "Title", "Category") exp_services.save_new_exploration(self.owner_id, exploration) self.assertEqual(self._get_exploration_ids_subscribed_to(self.viewer_id), []) rights_manager.assign_role_for_exploration(self.owner_id, EXP_ID, self.viewer_id, rights_manager.ROLE_VIEWER) self.assertEqual(self._get_exploration_ids_subscribed_to(self.viewer_id), [])
def test_get_public_and_filtered_private_summary_dicts_for_creator(self): # If a new exploration is created by another user (Bob) and not public, # then Albert cannot see it when querying for explorations. displayable_summaries = ( summary_services.get_displayable_exp_summary_dicts_matching_ids( [self.EXP_ID_1, self.EXP_ID_2, self.EXP_ID_3, self.EXP_ID_5], editor_user_id=self.albert_id)) self.assertEqual(len(displayable_summaries), 2) self.assertEqual(displayable_summaries[0]['id'], self.EXP_ID_1) self.assertEqual(displayable_summaries[1]['id'], self.EXP_ID_2) # However, if Albert is granted editor access to Bob's exploration, # then Albert has access to the corresponding summary. rights_manager.assign_role_for_exploration( self.bob_id, self.EXP_ID_5, self.albert_id, rights_manager.ROLE_EDITOR) displayable_summaries = ( summary_services.get_displayable_exp_summary_dicts_matching_ids( [self.EXP_ID_1, self.EXP_ID_2, self.EXP_ID_3, self.EXP_ID_5], editor_user_id=self.albert_id)) self.assertEqual(len(displayable_summaries), 3) self.assertEqual(displayable_summaries[0]['status'], 'private') self.assertEqual(displayable_summaries[0]['id'], self.EXP_ID_1) self.assertEqual(displayable_summaries[1]['status'], 'public') self.assertEqual(displayable_summaries[1]['id'], self.EXP_ID_2) self.assertEqual(displayable_summaries[2]['status'], 'private') self.assertEqual(displayable_summaries[2]['id'], self.EXP_ID_5)
def test_collaborators_can_see_explorations(self): self.save_new_default_exploration( self.EXP_ID, self.owner_id, title=self.EXP_TITLE) rights_manager.assign_role_for_exploration( self.owner_id, self.EXP_ID, self.collaborator_id, rights_manager.ROLE_EDITOR) self.set_admins([self.OWNER_USERNAME]) self.login(self.COLLABORATOR_EMAIL) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PRIVATE) rights_manager.publish_exploration(self.owner_id, self.EXP_ID) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PUBLIC) rights_manager.publicize_exploration(self.owner_id, self.EXP_ID) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PUBLICIZED) self.logout()
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)
def test_inviting_playtester_to_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_VIEWER) self.assertTrue( rights_manager.Actor(self.user_id_b).can_play( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID))
def test_adding_new_exploration_owner_or_editor_role_results_in_subscription(self): exploration = exp_domain.Exploration.create_default_exploration(EXP_ID, "Title", "Category") exp_services.save_new_exploration(self.owner_id, exploration) self.assertEqual(self._get_exploration_ids_subscribed_to(self.owner_2_id), []) rights_manager.assign_role_for_exploration(self.owner_id, EXP_ID, self.owner_2_id, rights_manager.ROLE_OWNER) self.assertEqual(self._get_exploration_ids_subscribed_to(self.owner_2_id), [EXP_ID]) self.assertEqual(self._get_exploration_ids_subscribed_to(self.editor_id), []) rights_manager.assign_role_for_exploration(self.owner_id, EXP_ID, self.editor_id, rights_manager.ROLE_EDITOR) self.assertEqual(self._get_exploration_ids_subscribed_to(self.editor_id), [EXP_ID])
def test_ownership_of_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) rights_manager.assign_role_for_exploration(self.user_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_EDITOR) exp_rights = rights_manager.get_exploration_rights(self.EXP_ID) self.assertTrue(exp_rights.is_owner(self.user_id_a)) self.assertFalse(exp_rights.is_owner(self.user_id_b)) self.assertFalse(exp_rights.is_owner(self.user_id_admin))
def post(self, unused_entity_type, entity_id): """Handles Post requests.""" voice_artist = self.payload.get('username') voice_artist_id = user_services.get_user_id_from_username(voice_artist) if voice_artist_id is None: raise self.InvalidInputException( 'Sorry, we could not find the specified user.') rights_manager.assign_role_for_exploration( self.user, entity_id, voice_artist_id, rights_domain.ROLE_VOICE_ARTIST) self.render_json({})
def test_can_get_editable_private_exploration_summaries(self): self.login(self.VIEWER_EMAIL) response_dict = self.get_json( feconf.EXPLORATION_SUMMARIES_DATA_URL, { 'stringified_exp_ids': json.dumps([ self.PRIVATE_EXP_ID_EDITOR, self.PUBLIC_EXP_ID_EDITOR, self.PRIVATE_EXP_ID_VIEWER ]), 'include_private_explorations': True }) self.assertIn('summaries', response_dict) summaries = response_dict['summaries'] self.assertEqual(len(summaries), 2) self.assertEqual(summaries[0]['id'], self.PUBLIC_EXP_ID_EDITOR) self.assertEqual(summaries[0]['status'], 'public') self.assertEqual(summaries[1]['id'], self.PRIVATE_EXP_ID_VIEWER) self.assertEqual(summaries[1]['status'], 'private') # If the viewer user is granted edit access to the editor user's # private exploration, then it will show up for the next request. rights_manager.assign_role_for_exploration(self.editor, self.PRIVATE_EXP_ID_EDITOR, self.viewer_id, rights_manager.ROLE_EDITOR) response_dict = self.get_json( feconf.EXPLORATION_SUMMARIES_DATA_URL, { 'stringified_exp_ids': json.dumps([ self.PRIVATE_EXP_ID_EDITOR, self.PUBLIC_EXP_ID_EDITOR, self.PRIVATE_EXP_ID_VIEWER ]), 'include_private_explorations': True }) self.assertIn('summaries', response_dict) summaries = response_dict['summaries'] self.assertEqual(len(summaries), 3) self.assertEqual(summaries[0]['id'], self.PRIVATE_EXP_ID_EDITOR) self.assertEqual(summaries[0]['status'], 'private') self.assertEqual(summaries[1]['id'], self.PUBLIC_EXP_ID_EDITOR) self.assertEqual(summaries[1]['status'], 'public') self.assertEqual(summaries[2]['id'], self.PRIVATE_EXP_ID_VIEWER) self.assertEqual(summaries[2]['status'], 'private') self.logout()
def put(self, exploration_id): """Updates the editing rights for the given exploration.""" exploration = exp_fetchers.get_exploration_by_id(exploration_id) version = self.payload.get('version') _require_valid_version(version, exploration.version) make_community_owned = self.payload.get('make_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: 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() })
def accept_voiceover_application(voiceover_application_id, reviewer_id): """Accept the voiceover application of given voiceover application id. Args: voiceover_application_id: str. The id of the voiceover application which need to be accepted. reviewer_id: str. The user ID of the reviewer. """ voiceover_application = get_voiceover_application_by_id( voiceover_application_id) if reviewer_id == voiceover_application.author_id: raise Exception('Applicants are not allowed to review their own ' 'voiceover application.') reviewer = user_services.get_user_actions_info(reviewer_id) voiceover_application.accept(reviewer_id) _save_voiceover_applications([voiceover_application]) if voiceover_application.target_type == feconf.ENTITY_TYPE_EXPLORATION: rights_manager.assign_role_for_exploration( reviewer, voiceover_application.target_id, voiceover_application.author_id, rights_domain.ROLE_VOICE_ARTIST) opportunity_services.update_exploration_voiceover_opportunities( voiceover_application.target_id, voiceover_application.language_code) opportunities = ( opportunity_services.get_exploration_opportunity_summaries_by_ids( [voiceover_application.target_id])) email_manager.send_accepted_voiceover_application_email( voiceover_application.author_id, opportunities[voiceover_application.target_id].chapter_title, voiceover_application.language_code) # TODO(#7969): Add notification to the user's dashboard for the accepted # voiceover application. voiceover_application_models = ( suggestion_models.GeneralVoiceoverApplicationModel. get_voiceover_applications(voiceover_application.target_type, voiceover_application.target_id, voiceover_application.language_code)) rejected_voiceover_applications = [] for model in voiceover_application_models: voiceover_application = _get_voiceover_application_from_model(model) if not voiceover_application.is_handled: voiceover_application.reject( reviewer_id, 'We have to reject your application as another ' 'application for the same opportunity got accepted.') rejected_voiceover_applications.append(voiceover_application) _save_voiceover_applications(rejected_voiceover_applications)
def test_adding_new_exploration_viewer_role_does_not_result_in_subscription( self) -> None: exploration = exp_domain.Exploration.create_default_exploration( EXP_ID) # type: ignore[no-untyped-call] exp_services.save_new_exploration( self.owner_id, exploration) # type: ignore[no-untyped-call] self.assertEqual( self._get_exploration_ids_subscribed_to(self.viewer_id), []) rights_manager.assign_role_for_exploration( # type: ignore[no-untyped-call] self.owner, EXP_ID, self.viewer_id, rights_domain.ROLE_VIEWER) self.assertEqual( self._get_exploration_ids_subscribed_to(self.viewer_id), [])
def test_adding_new_exploration_viewer_role_does_not_result_in_subscription( self): exploration = exp_domain.Exploration.create_default_exploration( EXP_ID, 'Title', 'Category') exp_services.save_new_exploration(self.owner_id, exploration) self.assertEqual( self._get_exploration_ids_subscribed_to(self.viewer_id), []) rights_manager.assign_role_for_exploration(self.owner_id, EXP_ID, self.viewer_id, rights_manager.ROLE_VIEWER) self.assertEqual( self._get_exploration_ids_subscribed_to(self.viewer_id), [])
def setUp(self): super(VoiceArtistTest, self).setUp() self.login(self.OWNER_EMAIL) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.save_new_valid_exploration(self.EXP_ID, self.owner_id) rights_manager.assign_role_for_exploration( self.owner, self.EXP_ID, self.voice_artist_id, rights_manager.ROLE_VOICE_ARTIST) self.logout() self.login(self.VOICE_ARTIST_EMAIL) # Generate CSRF token. self.csrf_token = self.get_new_csrf_token()
def test_viewer_cannot_be_reassigned_as_viewer(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) rights_manager.assign_role_for_exploration( self.user_a, self.EXP_ID, self.user_id_b, rights_domain.ROLE_VIEWER) with self.assertRaisesRegexp( Exception, 'This user already can view this'): rights_manager.assign_role_for_exploration( self.user_a, self.EXP_ID, self.user_id_b, rights_domain.ROLE_VIEWER)
def test_stats_for_multiple_explorations_with_multiple_owners(self): exploration_1 = self.save_new_default_exploration( self.EXP_ID_1, self.owner_id_1, title=self.EXP_TITLE_1) exploration_2 = self.save_new_default_exploration( self.EXP_ID_2, self.owner_id_1, title=self.EXP_TITLE_2) rights_manager.assign_role_for_exploration( self.owner_id_1, self.EXP_ID_1, self.owner_id_2, rights_manager.ROLE_OWNER) rights_manager.assign_role_for_exploration( self.owner_id_1, self.EXP_ID_2, self.owner_id_2, rights_manager.ROLE_OWNER) self.login(self.OWNER_EMAIL_2) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 2) exp_version = self.EXP_DEFAULT_VERSION exp_id_1 = self.EXP_ID_1 state_1 = exploration_1.init_state_name exp_id_2 = self.EXP_ID_2 state_2 = exploration_2.init_state_name self._record_start(exp_id_1, exp_version, state_1) self._record_start(exp_id_1, exp_version, state_1) self._record_start(exp_id_2, exp_version, state_2) self._record_start(exp_id_2, exp_version, state_2) self._run_stats_aggregator_jobs() self._rate_exploration(exp_id_1, [3]) self._rate_exploration(exp_id_2, [2]) self._run_user_stats_aggregator_job() user_model_2 = user_models.UserStatsModel.get(self.owner_id_2) self.assertEquals(user_model_2.total_plays, 4) self.assertEquals( user_model_2.impact_score, self.USER_IMPACT_SCORE_DEFAULT) self.assertEquals(user_model_2.average_ratings, 2.5) self.logout() self.login(self.OWNER_EMAIL_1) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 2) user_model_1 = user_models.UserStatsModel.get(self.owner_id_1) self.assertEquals(user_model_1.total_plays, 4) self.assertEquals( user_model_1.impact_score, self.USER_IMPACT_SCORE_DEFAULT) self.assertEquals(user_model_1.average_ratings, 2.5) self.logout()
def test_contribution_msec_does_not_update_until_exp_is_published(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 saving an exploration does not update first contribution # time. self.assertIsNone( user_services.get_user_settings( self.admin_id).first_contribution_msec) # Test that commit to unpublished exploration does not update # contribution time. exp_services.update_exploration(self.admin_id, self.EXP_ID, [ exp_domain.ExplorationChange({ 'cmd': 'edit_state_property', 'state_name': init_state_name, 'property_name': 'widget_id', 'new_value': 'MultipleChoiceInput' }) ], '') self.assertIsNone( user_services.get_user_settings( self.admin_id).first_contribution_msec) # Test that another user who commits to unpublished exploration does not # have updated first contribution time. rights_manager.assign_role_for_exploration(self.admin, self.EXP_ID, self.editor_id, 'editor') exp_services.update_exploration(self.editor_id, self.EXP_ID, [ exp_domain.ExplorationChange({ 'cmd': 'rename_state', 'old_state_name': feconf.DEFAULT_INIT_STATE_NAME, 'new_state_name': u'¡Hola! αβγ', }) ], '') self.assertIsNone( user_services.get_user_settings( self.editor_id).first_contribution_msec) # Test that after an exploration is published, all contributors have # updated first contribution time. exp_services.publish_exploration_and_update_user_profiles( self.admin, self.EXP_ID) 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)
def test_contribution_msec_does_not_change_if_no_contribution_to_exp(self): self.save_new_valid_exploration( self.EXP_ID, self.admin_id, end_state_name='End') rights_manager.assign_role_for_exploration( self.admin_id, self.EXP_ID, self.editor_id, 'editor') exp_services.publish_exploration_and_update_user_profiles( self.admin_id, self.EXP_ID) # Test that contribution time is not given to an editor that has not # contributed. self.assertIsNotNone(user_services.get_user_settings( self.admin_id).first_contribution_msec) self.assertIsNone(user_services.get_user_settings( self.editor_id).first_contribution_msec)
def setUp(self): super(TranslationFirstTimeTutorialTest, self).setUp() self.login(self.OWNER_EMAIL) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.save_new_valid_exploration(self.EXP_ID, self.owner_id) self.publish_exploration(self.owner_id, self.EXP_ID) rights_manager.assign_role_for_exploration( self.voiceover_admin, self.EXP_ID, self.voice_artist_id, rights_domain.ROLE_VOICE_ARTIST) self.logout() self.login(self.VOICE_ARTIST_EMAIL) # Generate CSRF token. self.csrf_token = self.get_new_csrf_token()
def setUp(self): super(TranslatorTest, self).setUp() self.login(self.OWNER_EMAIL) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.save_new_valid_exploration(self.EXP_ID, self.owner_id) rights_manager.assign_role_for_exploration( self.owner, self.EXP_ID, self.translator_id, rights_manager.ROLE_TRANSLATOR) self.logout() self.login(self.TRANSLATOR_EMAIL) # Generate CSRF token. response = self.testapp.get('/create/%s' % self.EXP_ID) self.csrf_token = self.get_csrf_token_from_response(response)
def setUp(self): super(TranslationFirstTimeTutorialTest, self).setUp() self.login(self.OWNER_EMAIL) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.save_new_valid_exploration(self.EXP_ID, self.owner_id) rights_manager.assign_role_for_exploration( self.owner, self.EXP_ID, self.voice_artist_id, rights_manager.ROLE_VOICE_ARTIST) self.logout() self.login(self.VOICE_ARTIST_EMAIL) # Generate CSRF token. response = self.get_html_response('/create/%s' % self.EXP_ID) self.csrf_token = self.get_csrf_token_from_response(response)
def test_contribution_msec_does_not_update_until_exploration_is_published(self): self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME) self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL) self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL) exploration = self.save_new_valid_exploration( self.EXP_ID, self.admin_id, end_state_name='End') self.init_state_name = exploration.init_state_name # Test that saving an exploration does not update first contribution # time. self.assertIsNone(user_services.get_user_settings( self.admin_id).first_contribution_msec) # Test that commit to unpublished exploration does not update # contribution time. exp_services.update_exploration( self.admin_id, self.EXP_ID, [{ 'cmd': 'edit_state_property', 'state_name': self.init_state_name, 'property_name': 'widget_id', 'new_value': 'MultipleChoiceInput' }], '') self.assertIsNone(user_services.get_user_settings( self.admin_id).first_contribution_msec) # Test that another user who commits to unpublished exploration does not # have updated first contribution time. rights_manager.assign_role_for_exploration( self.admin_id, self.EXP_ID, self.editor_id, 'editor') exp_services.update_exploration( self.editor_id, self.EXP_ID, [{ 'cmd': 'rename_state', 'old_state_name': feconf.DEFAULT_INIT_STATE_NAME, 'new_state_name': u'¡Hola! αβγ', }], '') self.assertIsNone(user_services.get_user_settings( self.editor_id).first_contribution_msec) # Test that after an exploration is published, all contributors have # updated first contribution time. exp_services.publish_exploration_and_update_user_profiles( self.admin_id, self.EXP_ID) 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)
def test_assign_voice_artist_to_role_owner(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) rights_manager.assign_role_for_exploration( self.user_a, self.EXP_ID, self.user_id_b, rights_domain.ROLE_VOICE_ARTIST) exp_rights = rights_manager.get_exploration_rights(self.EXP_ID) self.assertFalse(exp_rights.is_owner(self.user_id_b)) rights_manager.assign_role_for_exploration( self.user_a, self.EXP_ID, self.user_id_b, rights_domain.ROLE_OWNER) exp_rights = rights_manager.get_exploration_rights(self.EXP_ID) self.assertTrue(exp_rights.is_owner(self.user_id_b))
def test_stats_for_single_exploration_with_multiple_owners(self): exploration = self.save_new_default_exploration(self.EXP_ID_1, self.owner_id_1, title=self.EXP_TITLE_1) rights_manager.assign_role_for_exploration(self.owner_id_1, self.EXP_ID_1, self.owner_id_2, rights_manager.ROLE_OWNER) self.login(self.OWNER_EMAIL_1) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) exp_version = self.EXP_DEFAULT_VERSION exp_id = self.EXP_ID_1 state = exploration.init_state_name self._record_start(exp_id, exp_version, state) self._record_start(exp_id, exp_version, state) self._run_stats_aggregator_jobs() self._rate_exploration(exp_id, [3, 4, 5]) self.logout() self.login(self.OWNER_EMAIL_2) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self._rate_exploration(exp_id, [3, 4, 5]) self._run_user_stats_aggregator_job() user_model_1 = user_models.UserStatsModel.get(self.owner_id_1) self.assertEquals(user_model_1.total_plays, 2) self.assertEquals(user_model_1.impact_score, self.USER_IMPACT_SCORE_DEFAULT) self.assertEquals(user_model_1.num_ratings, 3) self.assertEquals(user_model_1.average_ratings, 4) user_model_2 = user_models.UserStatsModel.get(self.owner_id_2) self.assertEquals(user_model_2.total_plays, 2) self.assertEquals(user_model_2.impact_score, self.USER_IMPACT_SCORE_DEFAULT) self.assertEquals(user_model_2.num_ratings, 3) self.assertEquals(user_model_2.average_ratings, 4) self.logout()
def test_adding_new_exploration_owner_or_editor_role_results_in_subscription(self): # pylint: disable=line-too-long exploration = exp_domain.Exploration.create_default_exploration(EXP_ID) exp_services.save_new_exploration(self.owner_id, exploration) self.assertEqual( self._get_exploration_ids_subscribed_to(self.owner_2_id), []) rights_manager.assign_role_for_exploration( self.owner_id, EXP_ID, self.owner_2_id, rights_manager.ROLE_OWNER) self.assertEqual( self._get_exploration_ids_subscribed_to(self.owner_2_id), [EXP_ID]) self.assertEqual( self._get_exploration_ids_subscribed_to(self.editor_id), []) rights_manager.assign_role_for_exploration( self.owner_id, EXP_ID, self.editor_id, rights_manager.ROLE_EDITOR) self.assertEqual( self._get_exploration_ids_subscribed_to(self.editor_id), [EXP_ID])
def test_viewer_cannot_see_explorations(self): self.save_new_default_exploration( self.EXP_ID, self.owner_id, title=self.EXP_TITLE) rights_manager.assign_role_for_exploration( self.owner, self.EXP_ID, self.viewer_id, rights_domain.ROLE_VIEWER) self.set_admins([self.OWNER_USERNAME]) self.login(self.VIEWER_EMAIL) response = self.get_json(feconf.CREATOR_DASHBOARD_DATA_URL) self.assertEqual(response['explorations_list'], []) rights_manager.publish_exploration(self.owner, self.EXP_ID) response = self.get_json(feconf.CREATOR_DASHBOARD_DATA_URL) self.assertEqual(response['explorations_list'], []) self.logout()
def setUp(self): super(SuggestionMigrationOneOffJobTest, self).setUp() self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.signup(self.AUTHOR_EMAIL, 'author') self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL) self.author_id = self.get_user_id_from_email(self.AUTHOR_EMAIL) self.editor = user_services.UserActionsInfo(self.editor_id) # Login and create exploration and suggestions. self.login(self.EDITOR_EMAIL) # Create exploration. self.save_new_valid_exploration(self.EXP_ID, self.editor_id, title='Exploration for suggestions', category='Algebra', objective='Test a suggestion.') exploration = exp_services.get_exploration_by_id(self.EXP_ID) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = exploration.init_state_name self.old_content = state_domain.SubtitledHtml('content', 'old content').to_dict() exp_services.update_exploration(self.editor_id, self.EXP_ID, [ exp_domain.ExplorationChange({ 'cmd': exp_domain.CMD_ADD_STATE, 'state_name': 'State 1', }), exp_domain.ExplorationChange({ 'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY, 'state_name': 'State 1', 'property_name': exp_domain.STATE_PROPERTY_CONTENT, 'new_value': self.old_content }) ], 'Add state name') rights_manager.publish_exploration(self.editor, self.EXP_ID) rights_manager.assign_role_for_exploration(self.editor, self.EXP_ID, self.owner_id, rights_manager.ROLE_EDITOR)
def test_ownership_of_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_EDITOR) self.assertTrue( rights_manager.Actor(self.user_id_a).is_owner( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).is_owner( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_admin).is_owner( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID))
def test_ownership_of_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) rights_manager.assign_role_for_exploration(self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_EDITOR) self.assertTrue( rights_manager.Actor(self.user_id_a).is_owner( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).is_owner( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_admin).is_owner( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID))
def test_can_get_editable_private_exploration_summaries(self): self.login(self.VIEWER_EMAIL) response_dict = self.get_json(feconf.EXPLORATION_SUMMARIES_DATA_URL, { 'stringified_exp_ids': json.dumps([ self.PRIVATE_EXP_ID_EDITOR, self.PUBLIC_EXP_ID_EDITOR, self.PRIVATE_EXP_ID_VIEWER]), 'include_private_explorations': True }) self.assertIn('summaries', response_dict) summaries = response_dict['summaries'] self.assertEqual(len(summaries), 2) self.assertEqual(summaries[0]['id'], self.PUBLIC_EXP_ID_EDITOR) self.assertEqual(summaries[0]['status'], 'public') self.assertEqual(summaries[1]['id'], self.PRIVATE_EXP_ID_VIEWER) self.assertEqual(summaries[1]['status'], 'private') # If the viewer user is granted edit access to the editor user's # private exploration, then it will show up for the next request. rights_manager.assign_role_for_exploration( self.editor_id, self.PRIVATE_EXP_ID_EDITOR, self.viewer_id, rights_manager.ROLE_EDITOR) response_dict = self.get_json(feconf.EXPLORATION_SUMMARIES_DATA_URL, { 'stringified_exp_ids': json.dumps([ self.PRIVATE_EXP_ID_EDITOR, self.PUBLIC_EXP_ID_EDITOR, self.PRIVATE_EXP_ID_VIEWER]), 'include_private_explorations': True }) self.assertIn('summaries', response_dict) summaries = response_dict['summaries'] self.assertEqual(len(summaries), 3) self.assertEqual(summaries[0]['id'], self.PRIVATE_EXP_ID_EDITOR) self.assertEqual(summaries[0]['status'], 'private') self.assertEqual(summaries[1]['id'], self.PUBLIC_EXP_ID_EDITOR) self.assertEqual(summaries[1]['status'], 'public') self.assertEqual(summaries[2]['id'], self.PRIVATE_EXP_ID_VIEWER) self.assertEqual(summaries[2]['status'], 'private') self.logout()
def test_stats_for_single_exploration_with_multiple_owners(self): exploration = self.save_new_default_exploration( self.EXP_ID_1, self.owner_id_1, title=self.EXP_TITLE_1) rights_manager.assign_role_for_exploration( self.owner_1, self.EXP_ID_1, self.owner_id_2, rights_domain.ROLE_OWNER) self.login(self.OWNER_EMAIL_1) response = self.get_json(feconf.CREATOR_DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) exp_version = self.EXP_DEFAULT_VERSION exp_id = self.EXP_ID_1 state = exploration.init_state_name self._record_start(exp_id, exp_version, state) self._record_start(exp_id, exp_version, state) self._rate_exploration(exp_id, [3, 4, 5]) self.logout() self.login(self.OWNER_EMAIL_2) response = self.get_json(feconf.CREATOR_DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self._rate_exploration(exp_id, [3, 4, 5]) user_model_1 = user_models.UserStatsModel.get( self.owner_id_1) self.assertEqual(user_model_1.total_plays, 2) # TODO(#11475): Calculate impact_score with an Apache Beam job. self.assertIsNone(user_model_1.impact_score) self.assertEqual(user_model_1.num_ratings, 3) self.assertEqual(user_model_1.average_ratings, 4) user_model_2 = user_models.UserStatsModel.get( self.owner_id_2) self.assertEqual(user_model_2.total_plays, 2) # TODO(#11475): Calculate impact_score with an Apache Beam job. self.assertIsNone(user_model_2.impact_score) self.assertEqual(user_model_2.num_ratings, 3) self.assertEqual(user_model_2.average_ratings, 4) self.logout()
def test_realtime_layer_batch_job_single_exploration_multiple_owners(self): exploration = self._create_exploration( self.EXP_ID_1, self.user_a_id) rights_manager.assign_role_for_exploration( self.user_a_id, self.EXP_ID_1, self.user_b_id, rights_manager.ROLE_OWNER) exp_version = self.EXP_DEFAULT_VERSION exp_id = self.EXP_ID_1 state = exploration.init_state_name self._record_start(exp_id, exp_version, state) self._record_start(exp_id, exp_version, state) self._record_exploration_rating(exp_id, [3, 4, 5]) self._record_exploration_rating(exp_id, [1, 5, 4]) expected_results = { 'total_plays': 2, 'num_ratings': 6, 'average_ratings': 22/6.0 } user_stats_1 = ( user_jobs_continuous.UserStatsAggregator.get_dashboard_stats( self.user_a_id)) self.assertEquals( user_stats_1['total_plays'], expected_results['total_plays']) self.assertEquals( user_stats_1['num_ratings'], expected_results['num_ratings']) self.assertEquals( user_stats_1['average_ratings'], expected_results['average_ratings']) user_stats_2 = ( user_jobs_continuous.UserStatsAggregator.get_dashboard_stats( self.user_b_id)) self.assertEquals( user_stats_2['total_plays'], expected_results['total_plays']) self.assertEquals( user_stats_2['num_ratings'], expected_results['num_ratings']) self.assertEquals( user_stats_2['average_ratings'], expected_results['average_ratings'])
def test_realtime_layer_batch_job_single_exploration_multiple_owners(self): exploration = self._create_exploration( self.EXP_ID_1, self.user_a_id) rights_manager.assign_role_for_exploration( self.user_a, self.EXP_ID_1, self.user_b_id, rights_manager.ROLE_OWNER) exp_version = self.EXP_DEFAULT_VERSION exp_id = self.EXP_ID_1 state = exploration.init_state_name self._record_start(exp_id, exp_version, state) self._record_start(exp_id, exp_version, state) self._record_exploration_rating(exp_id, [3, 4, 5]) self._record_exploration_rating(exp_id, [1, 5, 4]) expected_results = { 'total_plays': 2, 'num_ratings': 6, 'average_ratings': 22 / 6.0 } user_stats_1 = ( user_jobs_continuous.UserStatsAggregator.get_dashboard_stats( self.user_a_id)) self.assertEqual( user_stats_1['total_plays'], expected_results['total_plays']) self.assertEqual( user_stats_1['num_ratings'], expected_results['num_ratings']) self.assertEqual( user_stats_1['average_ratings'], expected_results['average_ratings']) user_stats_2 = ( user_jobs_continuous.UserStatsAggregator.get_dashboard_stats( self.user_b_id)) self.assertEqual( user_stats_2['total_plays'], expected_results['total_plays']) self.assertEqual( user_stats_2['num_ratings'], expected_results['num_ratings']) self.assertEqual( user_stats_2['average_ratings'], expected_results['average_ratings'])
def test_pre_delete_user_with_activities_multiple_owners(self): user_services.update_user_role( self.user_1_id, feconf.ROLE_ID_COLLECTION_EDITOR) user_1_actions = user_services.UserActionsInfo(self.user_1_id) self.save_new_valid_exploration('exp_id', self.user_1_id) rights_manager.assign_role_for_exploration( user_1_actions, 'exp_id', self.user_2_id, rights_manager.ROLE_OWNER) self.save_new_valid_collection( 'col_id', self.user_1_id, exploration_id='exp_id') rights_manager.assign_role_for_collection( user_1_actions, 'col_id', self.user_2_id, rights_manager.ROLE_OWNER) wipeout_service.pre_delete_user(self.user_1_id) pending_deletion_model = ( user_models.PendingDeletionRequestModel.get_by_id(self.user_1_id)) self.assertEqual( pending_deletion_model.exploration_ids, []) self.assertEqual(pending_deletion_model.collection_ids, [])
def test_viewer_cannot_see_explorations(self): self.save_new_default_exploration( self.EXP_ID, self.owner_id, title=self.EXP_TITLE) rights_manager.assign_role_for_exploration( self.owner_id, self.EXP_ID, self.viewer_id, rights_manager.ROLE_VIEWER) self.set_admins([self.OWNER_USERNAME]) self.login(self.VIEWER_EMAIL) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(response['explorations_list'], []) rights_manager.publish_exploration(self.owner_id, self.EXP_ID) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(response['explorations_list'], []) rights_manager.publicize_exploration(self.owner_id, self.EXP_ID) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(response['explorations_list'], []) self.logout()
def test_viewer_cannot_see_explorations(self): self.save_new_default_exploration(self.EXP_ID, self.owner_id, title=self.EXP_TITLE) rights_manager.assign_role_for_exploration(self.owner_id, self.EXP_ID, self.viewer_id, rights_manager.ROLE_VIEWER) self.set_admins([self.OWNER_EMAIL]) self.login(self.VIEWER_EMAIL) response = self.get_json(self.MY_EXPLORATIONS_DATA_URL) self.assertEqual(response['explorations_list'], []) rights_manager.publish_exploration(self.owner_id, self.EXP_ID) response = self.get_json(self.MY_EXPLORATIONS_DATA_URL) self.assertEqual(response['explorations_list'], []) rights_manager.publicize_exploration(self.owner_id, self.EXP_ID) response = self.get_json(self.MY_EXPLORATIONS_DATA_URL) self.assertEqual(response['explorations_list'], []) self.logout()
def setUp(self): super(VoiceArtistAutosaveTest, self).setUp() self.login(self.OWNER_EMAIL) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.save_new_valid_exploration(self.EXP_ID, self.owner_id) rights_manager.assign_role_for_exploration( self.owner, self.EXP_ID, self.voice_artist_id, rights_manager.ROLE_VOICE_ARTIST) self.logout() self.login(self.VOICE_ARTIST_EMAIL) user_models.ExplorationUserDataModel( id='%s.%s' % (self.voice_artist_id, self.EXP_ID), user_id=self.voice_artist_id, exploration_id=self.EXP_ID, draft_change_list=self.VALID_DRAFT_CHANGELIST, draft_change_list_last_updated=self.OLDER_DATETIME, draft_change_list_exp_version=1, draft_change_list_id=1).put() # Generate CSRF token. self.csrf_token = self.get_new_csrf_token()
def test_check_exploration_rights(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) rights_manager.assign_role_for_exploration( self.user_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_VIEWER) rights_manager.assign_role_for_exploration( self.user_a, self.EXP_ID, self.user_id_c, rights_manager.ROLE_EDITOR) rights_manager.assign_role_for_exploration( self.user_a, self.EXP_ID, self.user_id_d, rights_manager.ROLE_TRANSLATOR) exp_rights = rights_manager.get_exploration_rights(self.EXP_ID) self.assertTrue(exp_rights.is_owner(self.user_id_a)) self.assertTrue(exp_rights.is_editor(self.user_id_c)) self.assertTrue(exp_rights.is_viewer(self.user_id_b)) self.assertFalse(exp_rights.is_viewer(self.user_id_a)) self.assertFalse(exp_rights.is_owner(self.user_id_b)) self.assertFalse(exp_rights.is_editor(self.user_id_b)) self.assertTrue(exp_rights.is_translator(self.user_id_d)) self.assertFalse(exp_rights.is_translator(self.user_id_b))
def test_deletion_rights_for_published_exploration(self): """Test rights management for deletion of published explorations.""" PUBLISHED_EXP_ID = 'published_eid' exploration = exp_domain.Exploration.create_default_exploration( PUBLISHED_EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.owner_id, exploration) rights_manager.assign_role_for_exploration(self.owner_id, PUBLISHED_EXP_ID, self.editor_id, rights_manager.ROLE_EDITOR) rights_manager.publish_exploration(self.owner_id, PUBLISHED_EXP_ID) self.login(self.EDITOR_EMAIL) response = self.testapp.delete('/createhandler/data/%s' % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.VIEWER_EMAIL) response = self.testapp.delete('/createhandler/data/%s' % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.OWNER_EMAIL) response = self.testapp.delete('/createhandler/data/%s' % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.ADMIN_EMAIL) response = self.testapp.delete('/createhandler/data/%s' % PUBLISHED_EXP_ID) self.assertEqual(response.status_int, 200) self.logout()
def setUp(self): super(TranslatorAutosaveTest, self).setUp() self.login(self.OWNER_EMAIL) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.save_new_valid_exploration(self.EXP_ID, self.owner_id) rights_manager.assign_role_for_exploration( self.owner, self.EXP_ID, self.translator_id, rights_manager.ROLE_TRANSLATOR) self.logout() self.login(self.TRANSLATOR_EMAIL) user_models.ExplorationUserDataModel( id='%s.%s' % (self.translator_id, self.EXP_ID), user_id=self.translator_id, exploration_id=self.EXP_ID, draft_change_list=self.VALID_DRAFT_CHANGELIST, draft_change_list_last_updated=self.OLDER_DATETIME, draft_change_list_exp_version=1, draft_change_list_id=1).put() # Generate CSRF token. response = self.testapp.get('/create/%s' % self.EXP_ID) self.csrf_token = self.get_csrf_token_from_response(response)
def test_collaborators_can_see_explorations(self): self.save_new_default_exploration(self.EXP_ID, self.owner_id, title=self.EXP_TITLE) rights_manager.assign_role_for_exploration(self.owner, self.EXP_ID, self.collaborator_id, rights_domain.ROLE_EDITOR) self.set_curriculum_admins([self.OWNER_USERNAME]) self.login(self.COLLABORATOR_EMAIL) response = self.get_json(feconf.CREATOR_DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual(response['explorations_list'][0]['status'], rights_domain.ACTIVITY_STATUS_PRIVATE) rights_manager.publish_exploration(self.owner, self.EXP_ID) response = self.get_json(feconf.CREATOR_DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual(response['explorations_list'][0]['status'], rights_domain.ACTIVITY_STATUS_PUBLIC) self.logout()
def test_adding_new_exploration_owner_or_editor_role_results_in_subscription( self): EXP_ID = 'exp_id' exploration = exp_domain.Exploration.create_default_exploration( EXP_ID, 'Title', 'Category') exp_services.save_new_exploration(self.owner_id, exploration) self.assertEqual( self._get_exploration_ids_subscribed_to(self.owner_2_id), []) rights_manager.assign_role_for_exploration(self.owner_id, EXP_ID, self.owner_2_id, rights_manager.ROLE_OWNER) self.assertEqual( self._get_exploration_ids_subscribed_to(self.owner_2_id), [EXP_ID]) self.assertEqual( self._get_exploration_ids_subscribed_to(self.editor_id), []) rights_manager.assign_role_for_exploration(self.owner_id, EXP_ID, self.editor_id, rights_manager.ROLE_EDITOR) self.assertEqual( self._get_exploration_ids_subscribed_to(self.editor_id), [EXP_ID])
def test_deletion_rights_for_unpublished_exploration(self): """Test rights management for deletion of unpublished explorations.""" UNPUBLISHED_EXP_ID = "unpublished_eid" exploration = exp_domain.Exploration.create_default_exploration(UNPUBLISHED_EXP_ID, "A title", "A category") exp_services.save_new_exploration(self.owner_id, exploration) rights_manager.assign_role_for_exploration( self.owner_id, UNPUBLISHED_EXP_ID, self.editor_id, rights_manager.ROLE_EDITOR ) self.login(self.EDITOR_EMAIL) response = self.testapp.delete("/createhandler/data/%s" % UNPUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.VIEWER_EMAIL) response = self.testapp.delete("/createhandler/data/%s" % UNPUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.OWNER_EMAIL) response = self.testapp.delete("/createhandler/data/%s" % UNPUBLISHED_EXP_ID) self.assertEqual(response.status_int, 200) self.logout()
def setUp(self): super(SuggestionsIntegrationTests, self).setUp() # Register users. self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL) self.viewer_id = self.get_user_id_from_email(self.VIEWER_EMAIL) # Load exploration 0. exp_services.delete_demo(self.EXP_ID) exp_services.load_demo(self.EXP_ID) # Login and create exploration and suggestions. self.login(self.EDITOR_EMAIL) # Create exploration. self.save_new_valid_exploration( self.EXP_ID, self.editor_id, title='Exploration for suggestions', category='This is just a test category', objective='Test a suggestion.') exploration = exp_services.get_exploration_by_id(self.EXP_ID) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = exploration.init_state_name exploration.add_states(['State A', 'State 2', 'State 3']) exploration.states['State A'].update_interaction_id('TextInput') exploration.states['State 2'].update_interaction_id('TextInput') exploration.states['State 3'].update_interaction_id('TextInput') exp_services._save_exploration(self.editor_id, exploration, '', []) # pylint: disable=protected-access rights_manager.publish_exploration(self.editor_id, self.EXP_ID) rights_manager.assign_role_for_exploration( self.editor_id, self.EXP_ID, self.owner_id, rights_manager.ROLE_EDITOR) response = self.testapp.get('/explore/%s' % self.EXP_ID) csrf_token = self.get_csrf_token_from_response(response) # Create suggestions. self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 3, 'state_name': u'State A', 'description': u'Suggestion for state A.', 'suggestion_content': { 'type': 'text', 'value': u'new accepted suggestion for state A'}, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 1, 'state_name': u'State 2', 'description': u'A new value.', 'suggestion_content': { 'type': 'text', 'value': 'some new value'}, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State 3', 'description': u'Empty suggestion', 'suggestion_content': {'type': 'text', 'value': ''}, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State A', 'description': u'Just a space.', 'suggestion_content': {'type': 'text', 'value': ' '}, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 1, 'state_name': u'State 2', 'description': u'Random characters.', 'suggestion_content': {'type': 'text', 'value': '#!$%'}, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State 3', 'description': u'Very bizarre characters.', 'suggestion_content': {'type': 'text', 'value': u'Ֆݓॵক'}, }, csrf_token) self.logout()
def test_correct_email_is_sent_for_multiple_recipients(self): rights_manager.assign_role_for_exploration( self.editor_id, self.exploration.id, self.owner_id, rights_manager.ROLE_OWNER) expected_editor_email_html_body = ( 'Hi editor,<br>' 'newuser has submitted a new suggestion for your Oppia ' 'exploration, ' '<a href="https://www.oppia.org/create/A">"Title"</a>.<br>' 'You can accept or reject this suggestion by visiting the ' '<a href="https://www.oppia.org/create/A#/feedback">' 'feedback page</a> ' 'for your exploration.<br>' '<br>' 'Thanks!<br>' '- The Oppia Team<br>' '<br>' 'You can change your email preferences via the ' '<a href="https://www.example.com">Preferences</a> page.') expected_owner_email_html_body = ( 'Hi owner,<br>' 'newuser has submitted a new suggestion for your Oppia ' 'exploration, ' '<a href="https://www.oppia.org/create/A">"Title"</a>.<br>' 'You can accept or reject this suggestion by visiting the ' '<a href="https://www.oppia.org/create/A#/feedback">' 'feedback page</a> ' 'for your exploration.<br>' '<br>' 'Thanks!<br>' '- The Oppia Team<br>' '<br>' 'You can change your email preferences via the ' '<a href="https://www.example.com">Preferences</a> page.') expected_editor_email_text_body = ( 'Hi editor,\n' 'newuser has submitted a new suggestion for your Oppia ' 'exploration, "Title".\n' 'You can accept or reject this suggestion by visiting the ' 'feedback page for your exploration.\n' '\n' 'Thanks!\n' '- The Oppia Team\n' '\n' 'You can change your email preferences via the Preferences page.') expected_owner_email_text_body = ( 'Hi owner,\n' 'newuser has submitted a new suggestion for your Oppia ' 'exploration, "Title".\n' 'You can accept or reject this suggestion by visiting the ' 'feedback page for your exploration.\n' '\n' 'Thanks!\n' '- The Oppia Team\n' '\n' 'You can change your email preferences via the Preferences page.') with self.can_send_emails_ctx, self.can_send_feedback_email_ctx: feedback_services.create_suggestion( self.exploration.id, self.new_user_id, self.exploration.version, 'a state', 'simple description', {'content': {}}) self.process_and_flush_pending_tasks() editor_messages = ( self.mail_stub.get_sent_messages(to=self.EDITOR_EMAIL)) self.assertEqual(len(editor_messages), 1) self.assertEqual( editor_messages[0].html.decode(), expected_editor_email_html_body) self.assertEqual( editor_messages[0].body.decode(), expected_editor_email_text_body) owner_messages = ( self.mail_stub.get_sent_messages(to=self.OWNER_EMAIL)) self.assertEqual(len(owner_messages), 1) self.assertEqual( owner_messages[0].html.decode(), expected_owner_email_html_body) self.assertEqual( owner_messages[0].body.decode(), expected_owner_email_text_body)
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() })
def test_setting_rights_of_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_VIEWER) with self.assertRaisesRegexp(Exception, 'Could not assign new role.'): rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_c, rights_manager.ROLE_VIEWER) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_EDITOR) with self.assertRaisesRegexp(Exception, 'Could not assign new role.'): rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_c, rights_manager.ROLE_VIEWER) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_OWNER) rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_c, rights_manager.ROLE_OWNER) rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_d, rights_manager.ROLE_EDITOR) rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_e, rights_manager.ROLE_VIEWER)
def test_subscribing_to_exploration_subscribes_to_its_feedback_threads(self): with self.swap( jobs_registry, 'ALL_CONTINUOUS_COMPUTATION_MANAGERS', self.ALL_CONTINUOUS_COMPUTATION_MANAGERS_FOR_TESTS): EXP_ID = 'eid' EXP_TITLE = 'Title' FEEDBACK_THREAD_SUBJECT = 'feedback thread subject' USER_A_EMAIL = '*****@*****.**' USER_A_USERNAME = '******' self.signup(USER_A_EMAIL, USER_A_USERNAME) user_a_id = self.get_user_id_from_email(USER_A_EMAIL) USER_B_EMAIL = '*****@*****.**' USER_B_USERNAME = '******' self.signup(USER_B_EMAIL, USER_B_USERNAME) user_b_id = self.get_user_id_from_email(USER_B_EMAIL) # User A creates an exploration. self.save_new_valid_exploration( EXP_ID, user_a_id, title=EXP_TITLE, category='Category') exp_last_updated_ms = ( self._get_most_recent_exp_snapshot_created_on_ms(EXP_ID)) # User B starts a feedback thread. feedback_services.create_thread( EXP_ID, None, user_b_id, FEEDBACK_THREAD_SUBJECT, 'text') thread_id = ( feedback_services.get_threadlist(EXP_ID)[0]['thread_id']) message = feedback_services.get_messages(thread_id)[0] # User A adds user B as an editor of the exploration. rights_manager.assign_role_for_exploration( user_a_id, EXP_ID, user_b_id, rights_manager.ROLE_EDITOR) ModifiedRecentUpdatesAggregator.start_computation() self.assertEqual( self.count_jobs_in_taskqueue( queue_name=taskqueue_services.QUEUE_NAME_DEFAULT), 1) self.process_and_flush_pending_tasks() recent_notifications_for_user_a = ( ModifiedRecentUpdatesAggregator.get_recent_notifications( user_a_id)[1]) recent_notifications_for_user_b = ( ModifiedRecentUpdatesAggregator.get_recent_notifications( user_b_id)[1]) expected_feedback_thread_notification_dict = { 'activity_id': EXP_ID, 'activity_title': EXP_TITLE, 'author_id': user_b_id, 'last_updated_ms': message['created_on'], 'subject': FEEDBACK_THREAD_SUBJECT, 'type': feconf.UPDATE_TYPE_FEEDBACK_MESSAGE, } expected_exploration_created_notification_dict = ( self._get_expected_activity_created_dict( user_a_id, EXP_ID, EXP_TITLE, 'exploration', feconf.UPDATE_TYPE_EXPLORATION_COMMIT, exp_last_updated_ms)) # User A sees A's commit and B's feedback thread. self.assertEqual(recent_notifications_for_user_a, [ expected_feedback_thread_notification_dict, expected_exploration_created_notification_dict ]) # User B sees A's commit and B's feedback thread. self.assertEqual(recent_notifications_for_user_b, [ expected_feedback_thread_notification_dict, expected_exploration_created_notification_dict, ])
def test_subscribing_to_exploration_subscribes_to_its_feedback_threads( self): with self._get_test_context(): self.signup(USER_A_EMAIL, USER_A_USERNAME) user_a_id = self.get_user_id_from_email(USER_A_EMAIL) self.signup(USER_B_EMAIL, USER_B_USERNAME) user_b_id = self.get_user_id_from_email(USER_B_EMAIL) # User A creates an exploration. self.save_new_valid_exploration( EXP_ID, user_a_id, title=EXP_TITLE, category='Category') exp_last_updated_ms = ( self._get_most_recent_exp_snapshot_created_on_ms(EXP_ID)) # User B starts a feedback thread. feedback_services.create_thread( EXP_ID, None, user_b_id, FEEDBACK_THREAD_SUBJECT, 'text') thread_id = feedback_services.get_all_threads( EXP_ID, False)[0].get_thread_id() message = feedback_services.get_messages( EXP_ID, thread_id)[0] # User A adds user B as an editor of the exploration. rights_manager.assign_role_for_exploration( user_a_id, EXP_ID, user_b_id, rights_manager.ROLE_EDITOR) ModifiedRecentUpdatesAggregator.start_computation() self.assertEqual( self.count_jobs_in_taskqueue( queue_name=taskqueue_services.QUEUE_NAME_DEFAULT), 1) self.process_and_flush_pending_tasks() recent_notifications_for_user_a = ( ModifiedRecentUpdatesAggregator.get_recent_notifications( user_a_id)[1]) recent_notifications_for_user_b = ( ModifiedRecentUpdatesAggregator.get_recent_notifications( user_b_id)[1]) expected_thread_notification = { 'activity_id': EXP_ID, 'activity_title': EXP_TITLE, 'author_id': user_b_id, 'last_updated_ms': utils.get_time_in_millisecs( message.created_on), 'subject': FEEDBACK_THREAD_SUBJECT, 'type': feconf.UPDATE_TYPE_FEEDBACK_MESSAGE, } expected_creation_notification = ( self._get_expected_activity_created_dict( user_a_id, EXP_ID, EXP_TITLE, 'exploration', feconf.UPDATE_TYPE_EXPLORATION_COMMIT, exp_last_updated_ms)) # User A sees A's commit and B's feedback thread. self.assertEqual(recent_notifications_for_user_a, [ expected_thread_notification, expected_creation_notification ]) # User B sees A's commit and B's feedback thread. self.assertEqual(recent_notifications_for_user_b, [ expected_thread_notification, expected_creation_notification, ])