Commit 3ca5be00 authored by Mickaël Desfrênes's avatar Mickaël Desfrênes
Browse files

remove all owner references in rpc.methods

parent d4a5c49a
Loading
Loading
Loading
Loading
+143 −73
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ def _check_project_permission(
        - user has no access to given project/permission
        - project is int and no such pk exists
    """
    if project is None:
        raise ServiceException("project_id is not set")
    if isinstance(project, int):
        try:
            project = Project.objects.get(pk=project)
@@ -106,6 +108,9 @@ def has_permission(user: User, project_id: int, permission: str) -> bool:
    return False


has_permission.rpc_groups = ["Utilities"]


def metadatasets(user: User, project_id: int) -> List[Dict]:
    """
    Get the list of all the project's metadata sets.
@@ -582,21 +587,19 @@ def delete_collection(user: User, collection_id: int, recursive: bool = False) -
    unless the 'recursive'parameter is set to True.
    """
    query_set: Union[Iterator[Collection], QuerySet] = Collection.objects.filter(
        pk=collection_id, owner=user, deleted_at__isnull=True
        pk=collection_id, deleted_at__isnull=True
    )
    collection_instance = query_set.first()
    if not collection_instance:
        return {"success": True, "status": "does not exist"}
    _check_project_permission(user, collection_instance.project, "collection.delete")
    if recursive:
        if has_permission(user, collection_instance.project, "resource.delete"):
            for resource_instance in collection_instance.resources.all():
            if resource_instance.ptr_owner == user:
                resource_instance.soft_delete()
            for resource_instance in collection_instance.descendants_resources():
            if resource_instance.ptr_owner == user:
                resource_instance.soft_delete()
        for descendant_collection_instance in collection_instance.descendants():
            if descendant_collection_instance.owner == user:
            descendant_collection_instance.soft_delete()

    # do not allow to delete collection with content
@@ -616,12 +619,12 @@ def rename_collection(user: User, collection_id: int, title: str) -> bool:
    Rename a collection (ie. change its title).
    """
    query_set: Union[Iterator[Collection], QuerySet] = Collection.objects.filter(
        pk=collection_id, owner=user, deleted_at__isnull=True
        pk=collection_id, deleted_at__isnull=True
    )
    collection_instance = query_set.first()
    if not collection_instance:
        return False
    _check_project_permission(user, collection_instance.project, "collection.rename")
    _check_project_permission(user, collection_instance.project, "collection.write")
    collection_instance.title = title
    collection_instance.save()
    return True
@@ -635,12 +638,12 @@ def rename_resource(user: User, resource_id: int, title: str) -> bool:
    Rename a resource (ie. change its title).
    """
    query_set: Union[Iterator[Resource], QuerySet] = Resource.objects.filter(
        pk=resource_id, ptr_owner=user, deleted_at__isnull=True
        pk=resource_id, deleted_at__isnull=True
    )
    resource_instance = query_set.first()
    if not resource_instance:
        return False
    _check_project_permission(user, resource_instance.project, "resource.rename")
    _check_project_permission(user, resource_instance.project, "resource.write")
    resource_instance.title = title
    resource_instance.save()
    return True
@@ -653,13 +656,11 @@ def rename_meta(user: User, meta_id: int, title: str) -> bool:
    """
    Rename a metadata (ie. change its title).
    """
    query_set: Union[Iterator[Metadata], QuerySet] = Metadata.objects.filter(
        pk=meta_id, owner=user
    )
    query_set: Union[Iterator[Metadata], QuerySet] = Metadata.objects.filter(pk=meta_id)
    meta_instance = query_set.first()
    if not meta_instance:
        return False
    _check_project_permission(user, meta_instance.project, "metadata.rename")
    _check_project_permission(user, meta_instance.project, "metadata.write")
    meta_instance.title = title
    meta_instance.save()
    return True
@@ -707,7 +708,10 @@ def resources(
    if limit_to < limit_from:
        return []
    query_set: Union[Iterator[Resource], QuerySet] = Resource.objects.filter(
        collections__id=collection_id, ptr_owner=user, deleted_at__isnull=True
        collections__id=collection_id,
        deleted_at__isnull=True,
        ptr_project__projectaccess__user=user,
        ptr_project__projectaccess__role__permissions__label="resource.read",
    )
    for item in query_set[limit_from:limit_to]:
        data.append(serializers.resource(item, include_metas=bool(include_metas)))
@@ -737,11 +741,12 @@ def resource(user: User, resource_id: int) -> Union[Dict, None]:
    ```
    """
    query_set: Union[Iterator[Resource], QuerySet] = Resource.objects.filter(
        pk=resource_id, ptr_owner=user, deleted_at__isnull=True
        pk=resource_id, deleted_at__isnull=True
    )
    resource_instance = query_set.first()
    if not resource_instance:
        return None
    _check_project_permission(user, resource_instance.ptr_project, "resource.read")
    return serializers.resource(resource_instance)


@@ -756,11 +761,15 @@ def add_resource_to_collection(
    """
    try:
        collection_instance = Collection.objects.get(
            owner=user, id=collection_id, deleted_at__isnull=True
            id=collection_id, deleted_at__isnull=True
        )
        resource_instance = Resource.objects.get(
            ptr_owner=user, id=resource_id, deleted_at__isnull=True
            id=resource_id,
            deleted_at__isnull=True,
            ptr_project=collection_instance.project,
        )
        _check_project_permission(user, collection_instance.project, "collection.write")
        _check_project_permission(user, resource_instance.ptr_project, "resource.read")
        collection_instance.resources.add(resource_instance)
        return True
    except (
@@ -783,11 +792,15 @@ def remove_resource_from_collection(
    """
    try:
        collection_instance = Collection.objects.get(
            owner=user, id=collection_id, deleted_at__isnull=True
            id=collection_id, deleted_at__isnull=True
        )
        resource_instance = Resource.objects.get(
            ptr_owner=user, id=resource_id, deleted_at__isnull=True
            id=resource_id,
            deleted_at__isnull=True,
            ptr_project=collection_instance.project,
        )
        _check_project_permission(user, collection_instance.project, "collection.write")
        _check_project_permission(user, resource_instance.ptr_project, "resource.read")
        collection_instance.resources.remove(resource_instance)
        return True
    except (
@@ -806,13 +819,13 @@ def delete_resource(user: User, resource_id: int) -> bool:
    """
    Permanently delete a resource given its id.
    """
    # TODO: remove file on drive if last owner
    query_set: Union[Iterator[Resource], QuerySet] = Resource.objects.filter(
        pk=resource_id, ptr_owner=user, deleted_at__isnull=True
        pk=resource_id, deleted_at__isnull=True
    )
    resource_instance = query_set.first()
    if not resource_instance:
        return True
    _check_project_permission(user, resource_instance.ptr_project, "resource.delete")
    resource_instance.soft_delete()
    return True

@@ -820,7 +833,7 @@ def delete_resource(user: User, resource_id: int) -> bool:
delete_resource.rpc_groups = ["Resources"]


def simple_search(user: User, query: str) -> Dict[str, List]:
def simple_search(user: User, query: str, project_id: int) -> Dict[str, List]:
    """
    Performs a simple search on resources and collections, based on their titles.

@@ -858,14 +871,17 @@ def simple_search(user: User, query: str) -> Dict[str, List]:
    }
    ```
    """
    project = Project.objects.filter(pk=project_id).first()
    _check_project_permission(user, project, "collection.read")
    _check_project_permission(user, project, "resource.read")
    results = {"collections": [], "resources": []}
    collections_set: Union[Iterator[Collection], QuerySet] = Collection.objects.filter(
        owner=user, title__icontains=query, deleted_at__isnull=True
        title__icontains=query, deleted_at__isnull=True, project=project
    )
    for collection_instance in collections_set.distinct():
        results["collections"].append(serializers.collection(collection_instance))
    resources_set: Union[Iterator[Resource], QuerySet] = Resource.objects.filter(
        ptr_owner=user, title__icontains=query, deleted_at__isnull=True
        title__icontains=query, deleted_at__isnull=True, ptr_project=project
    )
    for resource_instance in resources_set.distinct():
        results["resources"].append(
@@ -898,7 +914,9 @@ def advanced_search_terms(user: User) -> List[str]:
advanced_search_terms.rpc_groups = ["Search"]


def advanced_search(user: User, search_terms: List[Dict]) -> Dict[str, List]:
def advanced_search(
    user: User, search_terms: List[Dict], project_id: int
) -> Dict[str, List]:
    """
    Performs a complex search using terms such as 'contains', 'is', 'does_not_contain'.

@@ -936,10 +954,15 @@ def advanced_search(user: User, search_terms: List[Dict]) -> Dict[str, List]:
    """
    if len(search_terms) > 10:
        raise ServiceException("Too many search terms.")
    project = Project.objects.filter(pk=project_id).first()
    _check_project_permission(user, project, "collection.read")
    _check_project_permission(user, project, "resource.read")
    # TODO: add tags search
    results = {"collections": [], "resources": []}
    # Search Resources first
    resources_set = Resource.objects.filter(ptr_owner=user, deleted_at__isnull=True)
    resources_set = Resource.objects.filter(
        ptr_project=project, deleted_at__isnull=True
    )
    for search_term in search_terms:
        if (
            "property" in search_term
@@ -983,7 +1006,9 @@ def advanced_search(user: User, search_terms: List[Dict]) -> Dict[str, List]:
        )

    # Search collections second
    collections_set = Collection.objects.filter(owner=user, deleted_at__isnull=True)
    collections_set = Collection.objects.filter(
        project=project, deleted_at__isnull=True
    )
    for search_term in search_terms:
        if (
            "property" in search_term
@@ -1030,7 +1055,7 @@ def advanced_search(user: User, search_terms: List[Dict]) -> Dict[str, List]:
advanced_search.rpc_groups = ["Search"]


def upload_infos(user: User, sha256_hash: str) -> Dict:
def upload_infos(user: User, sha256_hash: str, project_id: int) -> Dict:
    """
    Get information for an upload based on the file hash.

@@ -1048,9 +1073,11 @@ def upload_infos(user: User, sha256_hash: str) -> Dict:
    """
    infos = {"status": "not available", "id": None, "available_chunks": []}
    if re.match("[A-Fa-f0-9]{64}", sha256_hash) is not None:
        project = Project.objects.filter(pk=project_id).first()
        _check_project_permission(user, project, "file.read")
        try:
            file_instance = File.objects.get(
                hash=sha256_hash, owner=user, deleted_at__isnull=True
                hash=sha256_hash, project=project, deleted_at__isnull=True
            )
            infos["status"] = "available"
            infos["id"] = file_instance.id
@@ -1094,12 +1121,14 @@ def supported_file_types(user: User) -> List[Dict]:
supported_file_types.rpc_groups = ["Utilities"]


def add_metadataset(user: User, title: str) -> int:
def add_metadataset(user: User, title: str, project_id: int) -> int:
    """
    Create new metadata set from title.
    """
    project = Project.objects.filter(pk=project_id).first()
    _check_project_permission(user, project, "metadataset.add")
    metadataset_instance, created = MetadataSet.objects.get_or_create(
        owner=user, title=title
        project=project, title=title
    )
    return metadataset_instance.id

@@ -1121,8 +1150,9 @@ def add_metadata(
            meta_type = MetadataType.objects.get(pk=metadata_type_id)
        else:
            meta_type = None
        _check_project_permission(user, metas_set.project, "metadata.add")
        metadata_instance, created = Metadata.objects.get_or_create(
            owner=user, title=title, set=metas_set, data_type=meta_type
            project=metas_set.project, title=title, set=metas_set, data_type=meta_type
        )
        return metadata_instance.id
    except (
@@ -1142,11 +1172,13 @@ def remove_meta_from_resource(user: User, resource_id: int, meta_value_id: int)
    Remove a meta from a resource given their ids.
    """
    query_set: Union[Iterator[Resource], QuerySet] = Resource.objects.filter(
        pk=resource_id, ptr_owner=user, deleted_at__isnull=True
        pk=resource_id, deleted_at__isnull=True
    )
    resource_instance = query_set.first()
    if not resource_instance:
        return False
    # this is a resource.write permission, not a metadata.write
    _check_project_permission(user, resource_instance.ptr_project, "resource.write")
    for meta_value in resource_instance.metadataresourcevalue_set.all():
        if meta_value.id == meta_value_id:
            meta_value.delete()
@@ -1203,11 +1235,12 @@ def remove_meta_from_collection(
    Remove a meta from a collection given their ids.
    """
    query_set: Union[Iterator[Collection], QuerySet] = Collection.objects.filter(
        pk=collection_id, owner=user, deleted_at__isnull=True
        pk=collection_id, deleted_at__isnull=True
    )
    collection_instance = query_set.first()
    if not collection_instance:
        return False
    _check_project_permission(user, collection_instance.project, "collection.write")
    for meta_value in collection_instance.metadatacollectionvalue_set.all():
        if meta_value.id == meta_value_id:
            meta_value.delete()
@@ -1263,8 +1296,9 @@ def change_collection_meta_value(
    """
    try:
        meta_value_instance = MetadataCollectionValue.objects.get(pk=meta_value_id)
        if meta_value_instance.collection.owner.id != user.id:
            return False
        _check_project_permission(
            user, meta_value_instance.metadata.project, "collection.write"
        )
        meta_value_instance.value = meta_value
        meta_value_instance.save()
        return True
@@ -1281,8 +1315,9 @@ def change_resource_meta_value(user: User, meta_value_id: int, meta_value: str)
    """
    try:
        meta_value_instance = MetadataResourceValue.objects.get(pk=meta_value_id)
        if meta_value_instance.resource.ptr_owner_id != user.id:
            return False
        _check_project_permission(
            user, meta_value_instance.metadata.project, "resource.write"
        )
        meta_value_instance.value = meta_value
        meta_value_instance.save()
        return True
@@ -1349,16 +1384,18 @@ def ancestors_from_collection(
    """
    breadcrumb = []
    query_set: Union[Iterator[Collection], QuerySet] = Collection.objects.filter(
        pk=collection_id, owner=user, deleted_at__isnull=True
        pk=collection_id, deleted_at__isnull=True
    )
    collection_instance: Collection = query_set.first()
    project = collection_instance.project
    _check_project_permission(user, project, "collection.read")
    if not collection_instance:
        return breadcrumb
    current_collection = collection_instance
    while True:
        if current_collection.parent:
            if (
                current_collection.parent.owner == user
                current_collection.parent.project == project
                and not current_collection.deleted_at
            ):
                breadcrumb.append(
@@ -1428,13 +1465,15 @@ def ancestors_from_resource(user: User, resource_id: int) -> List[List[dict]]:
    """
    ancestors = []
    query_set: Union[Iterator[Resource], QuerySet] = Resource.objects.filter(
        pk=resource_id, ptr_owner=user, deleted_at__isnull=True
        pk=resource_id, deleted_at__isnull=True
    )
    resource_instance = query_set.first()
    if not resource_instance:
        return ancestors
    project = resource_instance.ptr_project
    _check_project_permission(user, project, "collection.read")
    for collection_instance in resource_instance.collections.all():
        if collection_instance.owner == user:
        if collection_instance.project == project:
            ancestors.append(
                ancestors_from_collection(
                    user, collection_instance.id, include_self=True
@@ -1473,11 +1512,12 @@ def publish_collection(user: User, collection_id: int) -> bool:
    Mark a collection as public
    """
    query_set: Union[Iterator[Collection], QuerySet] = Collection.objects.filter(
        pk=collection_id, owner=user, deleted_at__isnull=True
        pk=collection_id, deleted_at__isnull=True
    )
    collection_instance: Collection = query_set.first()
    if not collection_instance:
        return False
    _check_project_permission(user, collection_instance.project, "collection.write")
    collection_instance.public_access = True
    collection_instance.save()
    return True
@@ -1491,11 +1531,12 @@ def unpublish_collection(user: User, collection_id: int) -> bool:
    Mark a collection as private
    """
    query_set: Union[Iterator[Collection], QuerySet] = Collection.objects.filter(
        pk=collection_id, owner=user, deleted_at__isnull=True
        pk=collection_id, deleted_at__isnull=True
    )
    collection_instance: Collection = query_set.first()
    if not collection_instance:
        return False
    _check_project_permission(user, collection_instance.project, "collection.write")
    collection_instance.public_access = False
    collection_instance.save()
    return True
@@ -1521,7 +1562,7 @@ def move_collection(
    if child_collection_id == parent_collection_id:  # no loop !
        return False
    query_set: Union[Iterator[Collection], QuerySet] = Collection.objects.filter(
        pk=child_collection_id, owner=user, deleted_at__isnull=True
        pk=child_collection_id, deleted_at__isnull=True
    )
    child_collection_instance: Collection = query_set.first()
    if not child_collection_instance:
@@ -1533,7 +1574,7 @@ def move_collection(
        )
    else:
        query_set: Union[Iterator[Collection], QuerySet] = Collection.objects.filter(
            pk=parent_collection_id, owner=user, deleted_at__isnull=True
            pk=parent_collection_id, deleted_at__isnull=True
        )
    parent_collection_instance: Collection = query_set.first()
    if not parent_collection_instance:
@@ -1541,6 +1582,12 @@ def move_collection(
    if parent_collection_instance in child_collection_instance.descendants():
        return False  # don't cut the branch !

    _check_project_permission(
        user, parent_collection_instance.project, "collection.read"
    )
    _check_project_permission(
        user, child_collection_instance.project, "collection.write"
    )
    child_collection_instance.parent = parent_collection_instance
    child_collection_instance.save()
    return True
@@ -1549,7 +1596,9 @@ def move_collection(
move_collection.rpc_groups = ["Collections"]


def set_tag(user: User, uid: str, label: str = None, ark: str = None) -> dict:
def set_tag(
    user: User, uid: str, project_id: int, label: str = None, ark: str = None
) -> dict:
    """
    Get or create a Tag by uid (unique identifier). 'label' is an optional human-readable name.

@@ -1564,7 +1613,9 @@ def set_tag(user: User, uid: str, label: str = None, ark: str = None) -> dict:
    }
    ```
    """
    tag_instance, created = Tag.objects.get_or_create(owner=user, uid=uid)
    project = Project.objects.filter(pk=project_id).filter()
    _check_project_permission(user, project, "tag.add")
    tag_instance, created = Tag.objects.get_or_create(project=project, uid=uid)
    tag_instance.ark = ark
    tag_instance.label = label
    tag_instance.save()
@@ -1581,7 +1632,8 @@ def remove_tag(user: User, uid: str) -> bool:
    Beware: This will remove ALL associations with the tag.
    """
    try:
        tag_instance = Tag.objects.get(uid=uid, owner=user)
        tag_instance = Tag.objects.get(uid=uid)
        _check_project_permission(user, tag_instance.project, "tag.delete")
        tag_instance.delete()
        return True
    except (Tag.DoesNotExist, Tag.MultipleObjectsReturned):
@@ -1591,9 +1643,9 @@ def remove_tag(user: User, uid: str) -> bool:
remove_tag.rpc_groups = ["Tags"]


def tags(user: User) -> List[dict]:
def tags(user: User, project_id: int) -> List[dict]:
    """
    Returns all tags available to the current user.
    Returns all tags available in the project.

    Example output:

@@ -1614,8 +1666,10 @@ def tags(user: User) -> List[dict]:
    ]
    ```
    """
    project = Project.objects.filter(project_id).first()
    _check_project_permission(user, project, "tag.read")
    tags_list = []
    for tag_instance in Tag.objects.filter(owner=user):
    for tag_instance in Tag.objects.filter(project=project):
        tags_list.append(serializers.tag(tag_instance))
    return tags_list

@@ -1629,9 +1683,11 @@ def add_tag_to_collection(user: User, tag_uid: str, collection_id: int) -> bool:
    """
    try:
        collection_instance = Collection.objects.get(
            owner=user, id=collection_id, deleted_at__isnull=True
            pk=collection_id, deleted_at__isnull=True
        )
        tag_instance = Tag.objects.get(owner=user, uid=tag_uid)
        project = collection_instance.project
        _check_project_permission(user, project, "collection.write")
        tag_instance = Tag.objects.get(project=project, uid=tag_uid)
        collection_instance.tags.add(tag_instance)
        return True
    except (
@@ -1652,9 +1708,11 @@ def remove_tag_from_collection(user: User, tag_uid: str, collection_id: int) ->
    """
    try:
        collection_instance = Collection.objects.get(
            owner=user, id=collection_id, deleted_at__isnull=True
            pk=collection_id, deleted_at__isnull=True
        )
        tag_instance = Tag.objects.get(owner=user, uid=tag_uid)
        project = collection_instance.project
        _check_project_permission(user, project, "collection.write")
        tag_instance = Tag.objects.get(project=project, uid=tag_uid)
        collection_instance.tags.remove(tag_instance)
        return True
    except (
@@ -1675,9 +1733,11 @@ def add_tag_to_resource(user: User, tag_uid: str, resource_id: int) -> bool:
    """
    try:
        resource_instance = Resource.objects.get(
            ptr_owner=user, id=resource_id, deleted_at__isnull=True
            id=resource_id, deleted_at__isnull=True
        )
        tag_instance = Tag.objects.get(owner=user, uid=tag_uid)
        project = resource_instance.ptr_project
        _check_project_permission(user, project, "resource.write")
        tag_instance = Tag.objects.get(project=project, uid=tag_uid)
        resource_instance.tags.add(tag_instance)
        return True
    except (
@@ -1698,9 +1758,11 @@ def remove_tag_from_resource(user: User, tag_uid: str, resource_id: int) -> bool
    """
    try:
        resource_instance = Resource.objects.get(
            ptr_owner=user, id=resource_id, deleted_at__isnull=True
            id=resource_id, deleted_at__isnull=True
        )
        tag_instance = Tag.objects.get(owner=user, uid=tag_uid)
        project = resource_instance.ptr_project
        _check_project_permission(user, project, "resource.write")
        tag_instance = Tag.objects.get(project=project, uid=tag_uid)
        resource_instance.tags.remove(tag_instance)
        return True
    except (
@@ -1781,18 +1843,22 @@ def set_representative_resource(
    """
    try:
        collection_instance = Collection.objects.get(
            pk=collection_id, owner=user, deleted_at__isnull=True
            pk=collection_id, deleted_at__isnull=True
        )
        if not resource_id:
            collection_instance.representative = None
            collection_instance.save()
            return True
        resource_instance = Resource.objects.get(
            pk=resource_id, ptr_owner=user, deleted_at__isnull=True
            pk=resource_id, deleted_at__isnull=True
        )
        _check_project_permission(user, collection_instance.project, "collection.write")
        _check_project_permission(user, resource_instance.ptr_project, "resource.read")
        if resource_instance.ptr_project_id == collection_instance.project_id:
            collection_instance.representative = resource_instance
            collection_instance.save()
            return True
        return False
    except (Collection.DoesNotExist, Resource.DoesNotExist):
        return False

@@ -1818,18 +1884,21 @@ def replace_file(user: User, from_resource_id: int, to_resource_id: int) -> bool
    """
    try:
        from_resource_instance = Resource.objects.get(
            ptr_owner=user, pk=from_resource_id, deleted_at__isnull=True
            pk=from_resource_id, deleted_at__isnull=True
        )
        if not from_resource_instance.file:

            return False
        to_resource_instance = Resource.objects.get(
            ptr_owner=user, pk=to_resource_id, deleted_at__isnull=True
            pk=to_resource_id, deleted_at__isnull=True
        )
        if not to_resource_instance.file:

            return False

        _check_project_permission(
            user, from_resource_instance.ptr_project, "resource.read"
        )
        _check_project_permission(
            user, to_resource_instance.ptr_project, "resource.write"
        )
        try:
            exif_set = MetadataSet.objects.get(title="ExifTool")
            # remove to_resource exif metas
@@ -1872,7 +1941,8 @@ def set_is_oai_record(
    will be used in OAI-PMH requests.
    """
    try:
        collection_instance = Collection.objects.get(pk=collection_id, owner=user)
        collection_instance = Collection.objects.get(pk=collection_id)
        _check_project_permission(user, collection_instance.project, "collection.write")
        collection_instance.is_oai_record = is_oai_record
        # TODO: fetch and save ARK identifier
        collection_instance.save()