예제 #1
0
    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))
예제 #2
0
    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()
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
    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))
예제 #6
0
    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))
예제 #7
0
    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))
예제 #8
0
    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))
예제 #9
0
    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))
예제 #10
0
    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))
예제 #11
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)
예제 #12
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)
예제 #13
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)
예제 #14
0
    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')
예제 #15
0
    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))
예제 #16
0
    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()
        })
예제 #17
0
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))
예제 #18
0
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))
예제 #19
0
    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)
예제 #20
0
    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()
        })
예제 #21
0
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
예제 #22
0
    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
예제 #23
0
    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
예제 #24
0
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
예제 #25
0
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, {})
예제 #26
0
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
예제 #27
0
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
예제 #28
0
    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.')
예제 #29
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)

    # Ranks must be non-negative.
    return max(rank, 0)
예제 #30
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
예제 #31
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)

    # Ranks must be non-negative.
    return max(rank, 0)
예제 #32
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.')
예제 #33
0
    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))
예제 #34
0
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
예제 #35
0
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
예제 #36
0
    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))
예제 #37
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)
예제 #38
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)
예제 #39
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)
예제 #40
0
    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.')
예제 #41
0
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
예제 #42
0
def _should_index(collection):
    rights = rights_manager.get_collection_rights(collection.id)
    return rights.status != rights_manager.ACTIVITY_STATUS_PRIVATE