def test_can_only_delete_unpublished_collections(self): self.save_new_default_collection(self.COLLECTION_ID, self.user_id_a) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) self.assertTrue( rights_manager.check_can_delete_activity(self.user_a, collection_rights)) rights_manager.publish_collection(self.user_a, self.COLLECTION_ID) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) self.assertFalse( rights_manager.check_can_delete_activity(self.user_a, collection_rights)) rights_manager.unpublish_collection(self.user_admin, self.COLLECTION_ID) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) self.assertTrue( rights_manager.check_can_delete_activity(self.user_a, collection_rights))
def test_reload_collection(self): observed_log_messages = [] def _mock_logging_function(msg, *args): """Mocks logging.info().""" observed_log_messages.append(msg % args) self.login(self.ADMIN_EMAIL, is_super_admin=True) csrf_token = self.get_new_csrf_token() collection_services.load_demo('0') collection_rights = rights_manager.get_collection_rights('0') self.assertFalse(collection_rights.community_owned) with self.swap(logging, 'info', _mock_logging_function): self.post_json('/adminhandler', { 'action': 'reload_collection', 'collection_id': '0' }, csrf_token=csrf_token) collection_rights = rights_manager.get_collection_rights('0') self.assertTrue(collection_rights.community_owned) self.assertEqual(observed_log_messages, [ '[ADMIN] %s reloaded collection 0' % self.admin_id, 'Collection with id 0 was loaded.' ]) self.logout()
def test_collection_rights_handler(self): collection_id = 'collection_id' collection = collection_domain.Collection.create_default_collection( collection_id, 'A title', 'A Category', 'An Objective') collection_services.save_new_collection(self.owner_id, collection) # Check that collection is published correctly. rights_manager.assign_role_for_collection( self.owner_id, collection_id, self.editor_id, rights_manager.ROLE_EDITOR) rights_manager.publish_collection(self.owner_id, collection_id) # Check that collection cannot be unpublished by non admin. with self.assertRaisesRegexp( Exception, 'This collection cannot be unpublished.'): rights_manager.unpublish_collection(self.owner_id, collection_id) collection_rights = rights_manager.get_collection_rights(collection_id) self.assertEqual(collection_rights.status, rights_manager.ACTIVITY_STATUS_PUBLIC) # Check that collection can be unpublished by admin. rights_manager.unpublish_collection(self.admin_id, collection_id) collection_rights = rights_manager.get_collection_rights(collection_id) self.assertEqual(collection_rights.status, rights_manager.ACTIVITY_STATUS_PRIVATE)
def test_collection_rights_handler(self): collection_id = 'collection_id' collection = collection_domain.Collection.create_default_collection( collection_id, 'A title', 'A Category', 'An Objective') collection_services.save_new_collection(self.owner_id, collection) # Check that collection is published correctly. rights_manager.assign_role_for_collection(self.owner, collection_id, self.editor_id, rights_manager.ROLE_EDITOR) rights_manager.publish_collection(self.owner, collection_id) # Check that collection cannot be unpublished by non admin. with self.assertRaisesRegexp(Exception, 'This collection cannot be unpublished.'): rights_manager.unpublish_collection(self.owner, collection_id) collection_rights = rights_manager.get_collection_rights(collection_id) self.assertEqual(collection_rights.status, rights_manager.ACTIVITY_STATUS_PUBLIC) # Check that collection can be unpublished by admin. rights_manager.unpublish_collection(self.admin, collection_id) collection_rights = rights_manager.get_collection_rights(collection_id) self.assertEqual(collection_rights.status, rights_manager.ACTIVITY_STATUS_PRIVATE)
def test_publishing_and_unpublishing_collection(self): self.save_new_default_collection(self.COLLECTION_ID, self.user_id_a) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) self.assertFalse( rights_manager.check_can_access_activity(self.user_b, collection_rights)) rights_manager.publish_collection(self.user_a, self.COLLECTION_ID) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) self.assertTrue( rights_manager.check_can_access_activity(self.user_b, collection_rights)) self.assertFalse( rights_manager.check_can_unpublish_activity( self.user_a, collection_rights)) rights_manager.unpublish_collection(self.user_admin, self.COLLECTION_ID) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) self.assertTrue( rights_manager.check_can_access_activity(self.user_a, collection_rights)) self.assertFalse( rights_manager.check_can_access_activity(self.user_b, collection_rights))
def test_inviting_collaborator_to_collection(self): self.save_new_valid_collection( self.COLLECTION_ID, self.user_id_a, exploration_id=self.EXP_ID_FOR_COLLECTION) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) # Verify initial editor permissions for the collection. self.assertTrue( rights_manager.check_can_access_activity(self.user_a, collection_rights)) self.assertTrue( rights_manager.check_can_edit_activity(self.user_a, collection_rights)) # Verify initial editor permissions for the exploration within the # collection. self.assertFalse( rights_manager.check_can_access_activity(self.user_b, collection_rights)) self.assertFalse( rights_manager.check_can_edit_activity(self.user_b, collection_rights)) # User A adds user B to the collection as an editor. rights_manager.assign_role_for_collection(self.user_a, self.COLLECTION_ID, self.user_id_b, rights_manager.ROLE_EDITOR) # Ensure User A is the only user in the owner names list. self.assertListEqual(['A'], rights_manager.get_collection_owner_names( self.COLLECTION_ID)) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) # Ensure User B is now an editor of the collection. self.assertTrue( rights_manager.check_can_access_activity(self.user_b, collection_rights)) self.assertTrue( rights_manager.check_can_edit_activity(self.user_b, collection_rights)) self.assertFalse( rights_manager.check_can_delete_activity(self.user_b, collection_rights)) exp_for_collection_rights = rights_manager.get_exploration_rights( self.EXP_ID_FOR_COLLECTION) # Ensure User B is not an editor of the exploration within the # collection. self.assertFalse( rights_manager.check_can_access_activity( self.user_b, exp_for_collection_rights)) self.assertFalse( rights_manager.check_can_edit_activity(self.user_b, exp_for_collection_rights))
def test_get_collection_rights_for_nonexistent_collection(self): NON_COL_ID = "this_collection_does_not_exist_id" with self.assertRaisesRegexp( Exception, "Entity for class CollectionRightsModel with id " "this_collection_does_not_exist_id not found" ): rights_manager.get_collection_rights(NON_COL_ID) self.assertIsNone(rights_manager.get_collection_rights(NON_COL_ID, strict=False))
def test_get_collection_rights_for_nonexistent_collection(self): non_col_id = 'this_collection_does_not_exist_id' with self.assertRaisesRegexp( Exception, 'Entity for class CollectionRightsModel with id ' 'this_collection_does_not_exist_id not found'): rights_manager.get_collection_rights(non_col_id) self.assertIsNone( rights_manager.get_collection_rights(non_col_id, strict=False))
def test_inviting_playtester_to_collection(self): self.save_new_valid_collection( self.COLLECTION_ID, self.user_id_a, exploration_id=self.EXP_ID_FOR_COLLECTION) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) exp_for_collection_rights = rights_manager.get_exploration_rights( self.EXP_ID_FOR_COLLECTION) # Verify initial viewer permissions for the collection. self.assertFalse( rights_manager.check_can_access_activity(self.user_b, collection_rights)) self.assertFalse( rights_manager.check_can_edit_activity(self.user_b, collection_rights)) # Verify initial viewer permissions for the exploration within the # collection. self.assertFalse( rights_manager.check_can_access_activity( self.user_b, exp_for_collection_rights)) self.assertFalse( rights_manager.check_can_edit_activity(self.user_b, exp_for_collection_rights)) # User A adds user B to the collection as a viewer. rights_manager.assign_role_for_collection(self.user_a, self.COLLECTION_ID, self.user_id_b, rights_manager.ROLE_VIEWER) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) exp_for_collection_rights = rights_manager.get_exploration_rights( self.EXP_ID_FOR_COLLECTION) # Ensure User B is now a viewer of the collection. self.assertTrue( rights_manager.check_can_access_activity(self.user_b, collection_rights)) self.assertFalse( rights_manager.check_can_edit_activity(self.user_b, collection_rights)) # Ensure User B cannot view the exploration just because he/she has # access to the collection containing it. self.assertFalse( rights_manager.check_can_access_activity( self.user_b, exp_for_collection_rights)) self.assertFalse( rights_manager.check_can_edit_activity(self.user_b, exp_for_collection_rights))
def test_get_collection_rights_for_nonexistent_collection(self): non_col_id = 'this_collection_does_not_exist_id' with self.assertRaisesRegexp( Exception, 'Entity for class CollectionRightsModel with id ' 'this_collection_does_not_exist_id not found' ): rights_manager.get_collection_rights(non_col_id) self.assertIsNone( rights_manager.get_collection_rights(non_col_id, strict=False))
def _get_search_rank(collection_id): """Returns an integer determining the document's rank in search. Featured collections get a ranking bump, and so do collections that have been more recently updated. """ rights = rights_manager.get_collection_rights(collection_id) rank = _DEFAULT_RANK + ( _STATUS_PUBLICIZED_BONUS if rights.status == rights_manager.ACTIVITY_STATUS_PUBLICIZED else 0) # Iterate backwards through the collection history metadata until we find # the most recent snapshot that was committed by a human. last_human_update_ms = 0 snapshots_metadata = get_collection_snapshots_metadata(collection_id) for snapshot_metadata in reversed(snapshots_metadata): if snapshot_metadata['committer_id'] != feconf.MIGRATION_BOT_USER_ID: last_human_update_ms = snapshot_metadata['created_on_ms'] break _time_now_ms = utils.get_current_time_in_millisecs() time_delta_days = int( (_time_now_ms - last_human_update_ms) / _MS_IN_ONE_DAY) if time_delta_days == 0: rank += 80 elif time_delta_days == 1: rank += 50 elif 2 <= time_delta_days <= 7: rank += 35 # Ranks must be non-negative. return max(rank, 0)
def _get_search_rank(collection_id): """Returns an integer determining the document's rank in search. Featured collections get a ranking bump, and so do collections that have been more recently updated. """ rights = rights_manager.get_collection_rights(collection_id) rank = _DEFAULT_RANK + (_STATUS_PUBLICIZED_BONUS if rights.status == rights_manager.ACTIVITY_STATUS_PUBLICIZED else 0) # Iterate backwards through the collection history metadata until we find # the most recent snapshot that was committed by a human. last_human_update_ms = 0 snapshots_metadata = get_collection_snapshots_metadata(collection_id) for snapshot_metadata in reversed(snapshots_metadata): if snapshot_metadata['committer_id'] != feconf.MIGRATION_BOT_USER_ID: last_human_update_ms = snapshot_metadata['created_on_ms'] break _time_now_ms = utils.get_current_time_in_millisecs() time_delta_days = int( (_time_now_ms - last_human_update_ms) / _MS_IN_ONE_DAY) if time_delta_days == 0: rank += 80 elif time_delta_days == 1: rank += 50 elif 2 <= time_delta_days <= 7: rank += 35 # Ranks must be non-negative. return max(rank, 0)
def put(self, collection_id): """Unpublishes the given collection.""" collection = collection_services.get_collection_by_id(collection_id) version = self.payload.get('version') _require_valid_version(version, collection.version) rights_manager.unpublish_collection(self.user, collection_id) search_services.delete_collections_from_search_index([collection_id]) collection_rights = rights_manager.get_collection_rights(collection_id, strict=False) self.values.update({ 'can_edit': True, 'can_unpublish': rights_manager.check_can_unpublish_activity( self.user, collection_rights), 'collection_id': collection.id, 'is_private': rights_manager.is_collection_private(collection_id), 'owner_names': rights_manager.get_collection_owner_names(collection_id) }) self.render_json(self.values)
def get(self, collection_id): """Handles GET requests.""" try: collection = collection_services.get_collection_by_id( collection_id) except Exception as e: raise self.PageNotFoundException(e) collection_rights = rights_manager.get_collection_rights(collection_id, strict=False) self.values.update({ 'nav_mode': feconf.NAV_MODE_COLLECTION, 'can_edit': rights_manager.check_can_edit_activity(self.user, collection_rights), 'is_logged_in': bool(self.user_id), 'collection_id': collection_id, 'collection_title': collection.title, 'is_private': rights_manager.is_collection_private(collection_id), 'meta_name': collection.title, 'meta_description': utils.capitalize_string(collection.objective) }) self.render_template('pages/collection_player/collection_player.html')
def test_demo_collection(self): collection_services.load_demo('0') rights_manager.release_ownership_of_collection( self.system_user, '0') collection_rights = rights_manager.get_collection_rights('0') self.assertTrue(rights_manager.check_can_access_activity( self.user_a, collection_rights)) self.assertTrue(rights_manager.check_can_edit_activity( self.user_a, collection_rights)) self.assertFalse(rights_manager.check_can_delete_activity( self.user_a, collection_rights)) self.assertTrue(rights_manager.check_can_access_activity( self.user_admin, collection_rights)) self.assertTrue(rights_manager.check_can_edit_activity( self.user_admin, collection_rights)) self.assertTrue(rights_manager.check_can_delete_activity( self.user_admin, collection_rights)) self.assertTrue(rights_manager.check_can_access_activity( self.user_moderator, collection_rights)) self.assertTrue(rights_manager.check_can_edit_activity( self.user_moderator, collection_rights)) self.assertTrue(rights_manager.check_can_delete_activity( self.user_moderator, collection_rights))
def put(self, collection_id): """Updates the editing rights for the given collection.""" collection = collection_services.get_collection_by_id(collection_id) version = self.payload.get('version') _require_valid_version(version, collection.version) # TODO(bhenning): Implement other rights changes here. is_public = self.payload.get('is_public') if is_public is not None: if is_public: try: collection.validate(strict=True) collection_services.validate_exps_in_collection_are_public( collection) except utils.ValidationError as e: raise self.InvalidInputException(e) collection_services.publish_collection_and_update_user_profiles( self.user_id, collection_id) collection_services.index_collections_given_ids([ collection_id]) elif not self.is_admin: raise self.InvalidInputException( 'Cannot unpublish a collection.') self.render_json({ 'rights': rights_manager.get_collection_rights( collection_id).to_dict() })
def update_collection_status_in_search(collection_id): rights = rights_manager.get_collection_rights(collection_id) if rights.status == rights_manager.ACTIVITY_STATUS_PRIVATE: delete_documents_from_search_index([collection_id]) else: patch_collection_search_document( rights.id, _collection_rights_to_search_dict(rights))
def put(self, collection_id): """Publishes the given collection.""" collection = collection_services.get_collection_by_id(collection_id) version = self.payload.get('version') _require_valid_version(version, collection.version) collection.validate(strict=True) collection_services.validate_exps_in_collection_are_public(collection) collection_services.publish_collection_and_update_user_profiles( self.user, collection_id) collection_services.index_collections_given_ids([collection_id]) collection_rights = rights_manager.get_collection_rights(collection_id, strict=False) self.values.update({ 'can_edit': True, 'can_unpublish': rights_manager.check_can_unpublish_activity( self.user, collection_rights), 'collection_id': collection.id, 'is_private': rights_manager.is_collection_private(collection_id), 'owner_names': rights_manager.get_collection_owner_names(collection_id) }) self.render_json(self.values)
def put(self, collection_id): """Updates the editing rights for the given collection.""" collection = collection_services.get_collection_by_id(collection_id) version = self.payload.get('version') _require_valid_version(version, collection.version) # TODO(bhenning): Implement other rights changes here. is_public = self.payload.get('is_public') if is_public is not None: if is_public: try: collection.validate(strict=True) collection_services.validate_exps_in_collection_are_public( collection) except utils.ValidationError as e: raise self.InvalidInputException(e) collection_services.publish_collection_and_update_user_profiles( self.user_id, collection_id) collection_services.index_collections_given_ids( [collection_id]) elif not self.is_admin: raise self.InvalidInputException( 'Cannot unpublish a collection.') self.render_json({ 'rights': rights_manager.get_collection_rights(collection_id).to_dict() })
def _should_index_collection(collection): """Checks if a particular collection should be indexed. Args: collection: CollectionSummaryModel. """ rights = rights_manager.get_collection_rights(collection.id) return rights.status != rights_manager.ACTIVITY_STATUS_PRIVATE
def test_can_play(self, collection_id, **kwargs): collection_rights = rights_manager.get_collection_rights(collection_id, strict=False) if rights_manager.check_can_access_activity(self.user, collection_rights): return handler(self, collection_id, **kwargs) else: raise self.PageNotFoundException
def _get_domain_object_validation_type(cls, item): collection_rights = rights_manager.get_collection_rights(item.id, strict=False) if collection_rights is None: return base_model_validators.VALIDATION_MODE_NEUTRAL if rights_manager.is_collection_private(item.id): return base_model_validators.VALIDATION_MODE_NON_STRICT return base_model_validators.VALIDATION_MODE_STRICT
def _should_index_collection(collection): """Checks if a particular collection should be indexed. Args: collection: CollectionSummaryModel. The collection summary model object. Returns: bool. Whether a particular collection should be indexed. """ rights = rights_manager.get_collection_rights(collection.id) return rights.status != rights_domain.ACTIVITY_STATUS_PRIVATE
def update_collection_status_in_search(collection_id): """Updates the status field of a collection in the search index. Args: collection_id: str. ID of the collection. """ rights = rights_manager.get_collection_rights(collection_id) if rights.status == rights_manager.ACTIVITY_STATUS_PRIVATE: delete_collections_from_search_index([collection_id]) else: patch_collection_search_document(rights.id, {})
def _collection_to_search_dict(collection): rights = rights_manager.get_collection_rights(collection.id) doc = { 'id': collection.id, 'title': collection.title, 'category': collection.category, 'objective': collection.objective, 'rank': _get_search_rank(collection.id), } doc.update(_collection_rights_to_search_dict(rights)) return doc
def test_can_unpublish_collection(self, collection_id, **kwargs): collection_rights = rights_manager.get_collection_rights(collection_id) if collection_rights is None: raise base.UserFacingExceptions.PageNotFoundException if rights_manager.check_can_unpublish_activity(self.user, collection_rights): return handler(self, collection_id, **kwargs) raise self.UnauthorizedUserException( 'You do not have credentials to unpublish this collection.')
def _get_search_rank(collection_id): """Returns an integer determining the document's rank in search. Featured collections get a ranking bump, and so do collections that have been more recently updated. """ rights = rights_manager.get_collection_rights(collection_id) rank = _DEFAULT_RANK + (_STATUS_PUBLICIZED_BONUS if rights.status == rights_manager.ACTIVITY_STATUS_PUBLICIZED else 0) # Ranks must be non-negative. return max(rank, 0)
def test_can_play(self, collection_id, **kwargs): """Checks if the user can play the collection. Args: collection_id: str. The collection id. """ collection_rights = rights_manager.get_collection_rights(collection_id, strict=False) if rights_manager.check_can_access_activity(self.user, collection_rights): return handler(self, collection_id, **kwargs) else: raise self.PageNotFoundException
def _get_search_rank(collection_id): """Returns an integer determining the document's rank in search. Featured collections get a ranking bump, and so do collections that have been more recently updated. """ rights = rights_manager.get_collection_rights(collection_id) rank = _DEFAULT_RANK + ( _STATUS_PUBLICIZED_BONUS if rights.status == rights_manager.ACTIVITY_STATUS_PUBLICIZED else 0) # Ranks must be non-negative. return max(rank, 0)
def test_can_edit(self, collection_id, **kwargs): if not self.user_id: raise base.UserFacingExceptions.NotLoggedInException collection_rights = rights_manager.get_collection_rights(collection_id) if collection_rights is None: raise base.UserFacingExceptions.PageNotFoundException if rights_manager.check_can_edit_activity(self.user, collection_rights): return handler(self, collection_id, **kwargs) else: raise base.UserFacingExceptions.UnauthorizedUserException( 'You do not have credentials to edit this collection.')
def test_newly_created_collection(self): self.save_new_default_collection(self.COLLECTION_ID, self.user_id_a) self.assertListEqual(['A'], rights_manager.get_collection_owner_names( self.COLLECTION_ID)) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) self.assertTrue( rights_manager.check_can_access_activity(self.user_a, collection_rights)) self.assertTrue( rights_manager.check_can_edit_activity(self.user_a, collection_rights)) self.assertTrue( rights_manager.check_can_delete_activity(self.user_a, collection_rights)) self.assertTrue( rights_manager.check_can_access_activity(self.user_admin, collection_rights)) self.assertTrue( rights_manager.check_can_edit_activity(self.user_admin, collection_rights)) self.assertTrue( rights_manager.check_can_delete_activity(self.user_admin, collection_rights)) self.assertTrue( rights_manager.check_can_access_activity(self.user_moderator, collection_rights)) self.assertFalse( rights_manager.check_can_edit_activity(self.user_moderator, collection_rights)) self.assertFalse( rights_manager.check_can_delete_activity(self.user_moderator, collection_rights)) self.assertFalse( rights_manager.check_can_access_activity(self.user_b, collection_rights)) self.assertFalse( rights_manager.check_can_edit_activity(self.user_b, collection_rights)) self.assertFalse( rights_manager.check_can_delete_activity(self.user_b, collection_rights))
def _save_collection(committer_id, collection, commit_message, change_list): """Validates an collection and commits it to persistent storage. If successful, increments the version number of the incoming collection domain object by 1. """ if not change_list: raise Exception( 'Unexpected error: received an invalid change list when trying to ' 'save collection %s: %s' % (collection.id, change_list)) collection_rights = rights_manager.get_collection_rights(collection.id) if collection_rights.status != rights_manager.ACTIVITY_STATUS_PRIVATE: collection.validate(strict=True) else: collection.validate(strict=False) collection_model = collection_models.CollectionModel.get( collection.id, strict=False) if collection_model is None: collection_model = collection_models.CollectionModel(id=collection.id) else: if collection.version > collection_model.version: raise Exception( 'Unexpected error: trying to update version %s of collection ' 'from version %s. Please reload the page and try again.' % (collection_model.version, collection.version)) elif collection.version < collection_model.version: raise Exception( 'Trying to update version %s of collection from version %s, ' 'which is too old. Please reload the page and try again.' % (collection_model.version, collection.version)) collection_model.category = collection.category collection_model.title = collection.title collection_model.objective = collection.objective collection_model.schema_version = collection.schema_version collection_model.nodes = [ collection_node.to_dict() for collection_node in collection.nodes ] collection_model.commit(committer_id, commit_message, change_list) memcache_services.delete(_get_collection_memcache_key(collection.id)) event_services.CollectionContentChangeEventHandler.record(collection.id) index_collections_given_ids([collection.id]) collection.version += 1
def _save_collection(committer_id, collection, commit_message, change_list): """Validates an collection and commits it to persistent storage. If successful, increments the version number of the incoming collection domain object by 1. """ if not change_list: raise Exception( 'Unexpected error: received an invalid change list when trying to ' 'save collection %s: %s' % (collection.id, change_list)) collection_rights = rights_manager.get_collection_rights(collection.id) if collection_rights.status != rights_manager.ACTIVITY_STATUS_PRIVATE: collection.validate(strict=True) else: collection.validate(strict=False) collection_model = collection_models.CollectionModel.get(collection.id, strict=False) if collection_model is None: collection_model = collection_models.CollectionModel(id=collection.id) else: if collection.version > collection_model.version: raise Exception( 'Unexpected error: trying to update version %s of collection ' 'from version %s. Please reload the page and try again.' % (collection_model.version, collection.version)) elif collection.version < collection_model.version: raise Exception( 'Trying to update version %s of collection from version %s, ' 'which is too old. Please reload the page and try again.' % (collection_model.version, collection.version)) collection_model.category = collection.category collection_model.title = collection.title collection_model.objective = collection.objective collection_model.schema_version = collection.schema_version collection_model.nodes = [ collection_node.to_dict() for collection_node in collection.nodes ] collection_model.commit(committer_id, commit_message, change_list) memcache_services.delete(_get_collection_memcache_key(collection.id)) event_services.CollectionContentChangeEventHandler.record(collection.id) index_collections_given_ids([collection.id]) collection.version += 1
def test_ownership_of_collection(self): self.save_new_default_collection(self.COLLECTION_ID, self.user_id_a) rights_manager.assign_role_for_collection( self.user_a, self.COLLECTION_ID, self.user_id_b, rights_manager.ROLE_EDITOR) self.assertListEqual(['A'], rights_manager.get_collection_owner_names( self.COLLECTION_ID)) collection_rights = rights_manager.get_collection_rights( self.COLLECTION_ID) self.assertTrue(collection_rights.is_owner(self.user_id_a)) self.assertFalse(collection_rights.is_owner(self.user_id_b)) self.assertFalse(collection_rights.is_owner(self.user_id_admin))
def _get_search_rank(collection_id): """Returns an integer determining the document's rank in search. Featured collections get a ranking bump, and so do collections that have been more recently updated. """ # TODO(bhenning): Improve this calculation. Some possible suggestions for # a better ranking include using an average of the search ranks of each # exploration referenced in the collection and/or demoting collections # for any validation errors from explorations referenced in the collection. _STATUS_PUBLICIZED_BONUS = 30 # This is done to prevent the rank hitting 0 too easily. Note that # negative ranks are disallowed in the Search API. _DEFAULT_RANK = 20 collection = get_collection_by_id(collection_id) rights = rights_manager.get_collection_rights(collection_id) summary = get_collection_summary_by_id(collection_id) rank = _DEFAULT_RANK + ( _STATUS_PUBLICIZED_BONUS if rights.status == rights_manager.ACTIVITY_STATUS_PUBLICIZED else 0) # Iterate backwards through the collection history metadata until we find # the most recent snapshot that was committed by a human. last_human_update_ms = 0 snapshots_metadata = get_collection_snapshots_metadata(collection_id) for snapshot_metadata in reversed(snapshots_metadata): if snapshot_metadata['committer_id'] != feconf.MIGRATION_BOT_USER_ID: last_human_update_ms = snapshot_metadata['created_on_ms'] break _TIME_NOW_MS = utils.get_current_time_in_millisecs() _MS_IN_ONE_DAY = 24 * 60 * 60 * 1000 time_delta_days = int( (_TIME_NOW_MS - last_human_update_ms) / _MS_IN_ONE_DAY) if time_delta_days == 0: rank += 80 elif time_delta_days == 1: rank += 50 elif 2 <= time_delta_days <= 7: rank += 35 # Ranks must be non-negative. return max(rank, 0)
def _get_search_rank(collection_id): """Returns an integer determining the document's rank in search. Featured collections get a ranking bump, and so do collections that have been more recently updated. """ # TODO(bhenning): Improve this calculation. Some possible suggestions for # a better ranking include using an average of the search ranks of each # exploration referenced in the collection and/or demoting collections # for any validation errors from explorations referenced in the collection. _STATUS_PUBLICIZED_BONUS = 30 # This is done to prevent the rank hitting 0 too easily. Note that # negative ranks are disallowed in the Search API. _DEFAULT_RANK = 20 collection = get_collection_by_id(collection_id) rights = rights_manager.get_collection_rights(collection_id) summary = get_collection_summary_by_id(collection_id) rank = _DEFAULT_RANK + (_STATUS_PUBLICIZED_BONUS if rights.status == rights_manager.ACTIVITY_STATUS_PUBLICIZED else 0) # Iterate backwards through the collection history metadata until we find # the most recent snapshot that was committed by a human. last_human_update_ms = 0 snapshots_metadata = get_collection_snapshots_metadata(collection_id) for snapshot_metadata in reversed(snapshots_metadata): if snapshot_metadata['committer_id'] != feconf.MIGRATION_BOT_USER_ID: last_human_update_ms = snapshot_metadata['created_on_ms'] break _TIME_NOW_MS = utils.get_current_time_in_millisecs() _MS_IN_ONE_DAY = 24 * 60 * 60 * 1000 time_delta_days = int( (_TIME_NOW_MS - last_human_update_ms) / _MS_IN_ONE_DAY) if time_delta_days == 0: rank += 80 elif time_delta_days == 1: rank += 50 elif 2 <= time_delta_days <= 7: rank += 35 # Ranks must be non-negative. return max(rank, 0)
def get(self, collection_id): """Populates the data on the individual collection page.""" try: collection_dict = ( summary_services.get_learner_collection_dict_by_id( collection_id, self.user, allow_invalid_explorations=False)) except Exception as e: raise self.PageNotFoundException(e) collection_rights = rights_manager.get_collection_rights( collection_id, strict=False) self.values.update({ 'can_edit': rights_manager.check_can_edit_activity( self.user, collection_rights), 'collection': collection_dict, 'is_logged_in': bool(self.user_id), 'session_id': utils.generate_new_session_id(), }) self.render_json(self.values)
def test_can_unpublish_collection(self, collection_id, **kwargs): """Checks if the user can unpublish the collection. Args: collection_id: str. The collection id. **kwargs: *. Keyword arguments. Returns: bool. Whether the user can unpublish the collection. """ collection_rights = rights_manager.get_collection_rights(collection_id) if collection_rights is None: raise base.UserFacingExceptions.PageNotFoundException if rights_manager.check_can_unpublish_activity(self.user, collection_rights): return handler(self, collection_id, **kwargs) raise self.UnauthorizedUserException( 'You do not have credentials to unpublish this collection.')
def _save_collection(committer_id, collection, commit_message, change_list): """Validates an collection and commits it to persistent storage. If successful, increments the version number of the incoming collection domain object by 1. """ if not change_list: raise Exception( 'Unexpected error: received an invalid change list when trying to ' 'save collection %s: %s' % (collection.id, change_list)) collection_rights = rights_manager.get_collection_rights(collection.id) if collection_rights.status != rights_manager.ACTIVITY_STATUS_PRIVATE: collection.validate(strict=True) else: collection.validate(strict=False) # Validate that all explorations referenced by the collection exist. exp_ids = collection.exploration_ids exp_summaries = ( exp_services.get_exploration_summaries_matching_ids(exp_ids)) exp_summaries_dict = { exp_id: exp_summaries[ind] for (ind, exp_id) in enumerate(exp_ids) } for collection_node in collection.nodes: if not exp_summaries_dict[collection_node.exploration_id]: raise utils.ValidationError( 'Expected collection to only reference valid explorations, ' 'but found an exploration with ID: %s (was it deleted?)' % collection_node.exploration_id) # Ensure no explorations are being added that are 'below' the public status # of this collection. If the collection is private, it can have both # private and public explorations. If it's public, it can only have public # explorations. # TODO(bhenning): Ensure the latter is enforced above when trying to # publish a collection. if rights_manager.is_collection_public(collection.id): validate_exps_in_collection_are_public(collection) collection_model = collection_models.CollectionModel.get( collection.id, strict=False) if collection_model is None: collection_model = collection_models.CollectionModel(id=collection.id) else: if collection.version > collection_model.version: raise Exception( 'Unexpected error: trying to update version %s of collection ' 'from version %s. Please reload the page and try again.' % (collection_model.version, collection.version)) elif collection.version < collection_model.version: raise Exception( 'Trying to update version %s of collection from version %s, ' 'which is too old. Please reload the page and try again.' % (collection_model.version, collection.version)) collection_model.category = collection.category collection_model.title = collection.title collection_model.objective = collection.objective collection_model.language_code = collection.language_code collection_model.tags = collection.tags collection_model.schema_version = collection.schema_version collection_model.nodes = [ collection_node.to_dict() for collection_node in collection.nodes ] collection_model.node_count = len(collection_model.nodes) collection_model.commit(committer_id, commit_message, change_list) memcache_services.delete(_get_collection_memcache_key(collection.id)) index_collections_given_ids([collection.id]) collection.version += 1
def _should_index(collection): rights = rights_manager.get_collection_rights(collection.id) return rights.status != rights_manager.ACTIVITY_STATUS_PRIVATE