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

Use CRUD semantics for access control. Fix missing file.upload permission

parent 3bd9fa53
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -37,11 +37,12 @@ def set_base_permissions():
        "permission",
        "project",
    ]
    permissions = ["add", "read", "write", "delete"]
    permissions = ["create", "read", "update", "delete"]
    for obj_type in obj_types:
        for permission in permissions:
            Permission.objects.get_or_create(label="{}.{}".format(obj_type, permission))
    Permission.objects.get_or_create(label="file.download_source")
    Permission.objects.get_or_create(label="file.upload")


def set_root():
+54 −42
Original line number Diff line number Diff line
@@ -407,7 +407,7 @@ def add_collection(
        raise ServiceException("use project_id OR parent_id")
    if project_id:
        # no parent available, add collection at project root
        _check_project_permission(user, project_id, "collection.add")
        _check_project_permission(user, project_id, "collection.create")
        parent = Collection.objects.filter(title="root", parent_id=None).first()
    else:
        # fetch parent, check parent's project add access
@@ -420,7 +420,7 @@ def add_collection(
        if not parent:
            return None
        else:
            _check_project_permission(user, parent.project, "collection.add")
            _check_project_permission(user, parent.project, "collection.create")

    collection_instance, created = Collection.objects.get_or_create(
        title=title, parent=parent, project_id=project_id or parent.project.pk
@@ -498,7 +498,7 @@ def add_collection_from_path(user: User, path: str, project_id: int) -> List[Dic
    project = Project.objects.filter(pk=project_id).first()
    if not project:
        raise ServiceException("no such project")
    _check_project_permission(user, project, "collection.add")
    _check_project_permission(user, project, "collection.create")
    hierarchy = []
    previous_dir = Collection.objects.get(title="root", parent=None)
    for dir_name in path.split("/"):
@@ -615,7 +615,7 @@ def rename_collection(user: User, collection_id: int, title: str) -> bool:
    collection_instance = query_set.first()
    if not collection_instance:
        return False
    _check_project_permission(user, collection_instance.project, "collection.write")
    _check_project_permission(user, collection_instance.project, "collection.update")
    collection_instance.title = title
    collection_instance.save()
    return True
@@ -632,7 +632,7 @@ def rename_resource(user: User, resource_id: int, title: str) -> bool:
    resource_instance = query_set.first()
    if not resource_instance:
        return False
    _check_project_permission(user, resource_instance.project, "resource.write")
    _check_project_permission(user, resource_instance.project, "resource.update")
    resource_instance.title = title
    resource_instance.save()
    return True
@@ -647,7 +647,7 @@ def rename_meta(user: User, meta_id: int, title: str) -> bool:
    meta_instance = query_set.first()
    if not meta_instance:
        return False
    _check_project_permission(user, meta_instance.project, "metadata.write")
    _check_project_permission(user, meta_instance.project, "metadata.update")
    meta_instance.title = title
    meta_instance.save()
    return True
@@ -749,7 +749,9 @@ def add_resource_to_collection(
            deleted_at__isnull=True,
            ptr_project=collection_instance.project,
        )
        _check_project_permission(user, collection_instance.project, "collection.write")
        _check_project_permission(
            user, collection_instance.project, "collection.update"
        )
        _check_project_permission(user, resource_instance.ptr_project, "resource.read")
        collection_instance.resources.add(resource_instance)
        return True
@@ -778,7 +780,9 @@ def remove_resource_from_collection(
            deleted_at__isnull=True,
            ptr_project=collection_instance.project,
        )
        _check_project_permission(user, collection_instance.project, "collection.write")
        _check_project_permission(
            user, collection_instance.project, "collection.update"
        )
        _check_project_permission(user, resource_instance.ptr_project, "resource.read")
        collection_instance.resources.remove(resource_instance)
        return True
@@ -1094,7 +1098,7 @@ 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")
    _check_project_permission(user, project, "metadataset.create")
    metadataset_instance, created = MetadataSet.objects.get_or_create(
        project=project, title=title
    )
@@ -1116,7 +1120,7 @@ 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")
        _check_project_permission(user, metas_set.project, "metadata.create")
        metadata_instance, created = Metadata.objects.get_or_create(
            project=metas_set.project, title=title, set=metas_set, data_type=meta_type
        )
@@ -1141,8 +1145,8 @@ def remove_meta_from_resource(user: User, resource_id: int, meta_value_id: int)
    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")
    # this is a resource.update permission, not a metadata.update
    _check_project_permission(user, resource_instance.ptr_project, "resource.update")
    for meta_value in resource_instance.metadataresourcevalue_set.all():
        if meta_value.id == meta_value_id:
            meta_value.delete()
@@ -1166,9 +1170,11 @@ def add_meta_to_resource(
            ptr_project__projectaccess__user=user,
            ptr_project__projectaccess__role__permissions__label="resource.read",
        )
        # Adding a meta value to a resource is a resource.write, NOT a metadata.write.
        # Adding a meta value to a resource is a resource.update, NOT a metadata.update.
        # No need to go further.
        _check_project_permission(user, resource_instance.ptr_project, "resource.write")
        _check_project_permission(
            user, resource_instance.ptr_project, "resource.update"
        )
        meta = Metadata.objects.get(
            pk=meta_id,
            project__projectaccess__user=user,
@@ -1200,7 +1206,7 @@ def remove_meta_from_collection(
    collection_instance = query_set.first()
    if not collection_instance:
        return False
    _check_project_permission(user, collection_instance.project, "collection.write")
    _check_project_permission(user, collection_instance.project, "collection.update")
    for meta_value in collection_instance.metadatacollectionvalue_set.all():
        if meta_value.id == meta_value_id:
            meta_value.delete()
@@ -1229,7 +1235,9 @@ def add_meta_to_collection(
            project__projectaccess__user=user,
            project__projectaccess__role__permissions__label="metadata.read",
        )
        _check_project_permission(user, collection_instance.project, "collection.write")
        _check_project_permission(
            user, collection_instance.project, "collection.update"
        )
        meta_value_instance, created = MetadataCollectionValue.objects.get_or_create(
            metadata=meta, collection=collection_instance, value=meta_value
        )
@@ -1253,7 +1261,7 @@ def change_collection_meta_value(
    try:
        meta_value_instance = MetadataCollectionValue.objects.get(pk=meta_value_id)
        _check_project_permission(
            user, meta_value_instance.metadata.project, "collection.write"
            user, meta_value_instance.metadata.project, "collection.update"
        )
        meta_value_instance.value = meta_value
        meta_value_instance.save()
@@ -1270,7 +1278,7 @@ 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)
        _check_project_permission(
            user, meta_value_instance.metadata.project, "resource.write"
            user, meta_value_instance.metadata.project, "resource.update"
        )
        meta_value_instance.value = meta_value
        meta_value_instance.save()
@@ -1463,7 +1471,7 @@ def publish_collection(user: User, collection_id: int) -> bool:
    collection_instance: Collection = query_set.first()
    if not collection_instance:
        return False
    _check_project_permission(user, collection_instance.project, "collection.write")
    _check_project_permission(user, collection_instance.project, "collection.update")
    collection_instance.public_access = True
    collection_instance.save()
    return True
@@ -1480,7 +1488,7 @@ def unpublish_collection(user: User, collection_id: int) -> bool:
    collection_instance: Collection = query_set.first()
    if not collection_instance:
        return False
    _check_project_permission(user, collection_instance.project, "collection.write")
    _check_project_permission(user, collection_instance.project, "collection.update")
    collection_instance.public_access = False
    collection_instance.save()
    return True
@@ -1528,7 +1536,7 @@ def move_collection(
        user, parent_collection_instance.project, "collection.read"
    )
    _check_project_permission(
        user, child_collection_instance.project, "collection.write"
        user, child_collection_instance.project, "collection.update"
    )
    child_collection_instance.parent = parent_collection_instance
    child_collection_instance.save()
@@ -1554,7 +1562,7 @@ def set_tag(
    ```
    """
    project = Project.objects.filter(pk=project_id).first()
    _check_project_permission(user, project, "tag.add")
    _check_project_permission(user, project, "tag.create")
    tag_instance, created = Tag.objects.get_or_create(project=project, uid=uid)
    tag_instance.ark = ark
    tag_instance.label = label
@@ -1620,7 +1628,7 @@ def add_tag_to_collection(user: User, tag_uid: str, collection_id: int) -> bool:
            pk=collection_id, deleted_at__isnull=True
        )
        project = collection_instance.project
        _check_project_permission(user, project, "collection.write")
        _check_project_permission(user, project, "collection.update")
        tag_instance = Tag.objects.get(project=project, uid=tag_uid)
        collection_instance.tags.add(tag_instance)
        return True
@@ -1643,7 +1651,7 @@ def remove_tag_from_collection(user: User, tag_uid: str, collection_id: int) ->
            pk=collection_id, deleted_at__isnull=True
        )
        project = collection_instance.project
        _check_project_permission(user, project, "collection.write")
        _check_project_permission(user, project, "collection.update")
        tag_instance = Tag.objects.get(project=project, uid=tag_uid)
        collection_instance.tags.remove(tag_instance)
        return True
@@ -1666,7 +1674,7 @@ def add_tag_to_resource(user: User, tag_uid: str, resource_id: int) -> bool:
            id=resource_id, deleted_at__isnull=True
        )
        project = resource_instance.ptr_project
        _check_project_permission(user, project, "resource.write")
        _check_project_permission(user, project, "resource.update")
        tag_instance = Tag.objects.get(project=project, uid=tag_uid)
        resource_instance.tags.add(tag_instance)
        return True
@@ -1689,7 +1697,7 @@ def remove_tag_from_resource(user: User, tag_uid: str, resource_id: int) -> bool
            id=resource_id, deleted_at__isnull=True
        )
        project = resource_instance.ptr_project
        _check_project_permission(user, project, "resource.write")
        _check_project_permission(user, project, "resource.update")
        tag_instance = Tag.objects.get(project=project, uid=tag_uid)
        resource_instance.tags.remove(tag_instance)
        return True
@@ -1725,7 +1733,9 @@ def set_representative_resource(
        resource_instance = Resource.objects.get(
            pk=resource_id, deleted_at__isnull=True
        )
        _check_project_permission(user, collection_instance.project, "collection.write")
        _check_project_permission(
            user, collection_instance.project, "collection.update"
        )
        _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
@@ -1768,7 +1778,7 @@ def replace_file(user: User, from_resource_id: int, to_resource_id: int) -> bool
            user, from_resource_instance.ptr_project, "resource.read"
        )
        _check_project_permission(
            user, to_resource_instance.ptr_project, "resource.write"
            user, to_resource_instance.ptr_project, "resource.update"
        )
        try:
            exif_set = MetadataSet.objects.get(title="ExifTool")
@@ -1811,7 +1821,9 @@ def set_is_oai_record(
    """
    try:
        collection_instance = Collection.objects.get(pk=collection_id)
        _check_project_permission(user, collection_instance.project, "collection.write")
        _check_project_permission(
            user, collection_instance.project, "collection.update"
        )
        collection_instance.is_oai_record = is_oai_record
        # TODO: fetch and save ARK identifier
        collection_instance.save()
@@ -1876,29 +1888,29 @@ def list_permissions(user: User) -> List[Dict]:

    ```
    [
        {'id': 1, 'label': 'collection.add'},
        {'id': 1, 'label': 'collection.create'},
        {'id': 2, 'label': 'collection.read'},
        {'id': 3, 'label': 'collection.write'},
        {'id': 3, 'label': 'collection.update'},
        {'id': 4, 'label': 'collection.delete'},
        {'id': 5, 'label': 'resource.add'},
        {'id': 5, 'label': 'resource.create'},
        {'id': 6, 'label': 'resource.read'},
        {'id': 7, 'label': 'resource.write'},
        {'id': 7, 'label': 'resource.update'},
        {'id': 8, 'label': 'resource.delete'},
        {'id': 9, 'label': 'metadata.add'},
        {'id': 9, 'label': 'metadata.create'},
        {'id': 10, 'label': 'metadata.read'},
        {'id': 11, 'label': 'metadata.write'},
        {'id': 11, 'label': 'metadata.update'},
        {'id': 12, 'label': 'metadata.delete'},
        {'id': 13, 'label': 'metadataset.add'},
        {'id': 13, 'label': 'metadataset.create'},
        {'id': 14, 'label': 'metadataset.read'},
        {'id': 15, 'label': 'metadataset.write'},
        {'id': 15, 'label': 'metadataset.update'},
        {'id': 16, 'label': 'metadataset.delete'},
        {'id': 17, 'label': 'file.add'},
        {'id': 17, 'label': 'file.create'},
        {'id': 18, 'label': 'file.read'},
        {'id': 19, 'label': 'file.write'},
        {'id': 19, 'label': 'file.update'},
        {'id': 20, 'label': 'file.delete'},
        {'id': 21, 'label': 'tag.add'},
        {'id': 21, 'label': 'tag.create'},
        {'id': 22, 'label': 'tag.read'},
        {'id': 23, 'label': 'tag.write'},
        {'id': 23, 'label': 'tag.update'},
        {'id': 24, 'label': 'tag.delete'},
        {'id': 25, 'label': 'file.download_source'}
    ]
@@ -1965,7 +1977,7 @@ def set_role(

    Requires superuser.
    """
    project = _check_project_permission(user, project_id, "permission.write")
    project = _check_project_permission(user, project_id, "permission.update")
    role, created = Role.objects.get_or_create(
        label=role_label.strip(), project=project
    )
+1 −0
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ def upload_partial(request: HttpRequest) -> HttpResponse:
    project = _get_project_from_request(request)
    if not project:
        return HttpResponse("Bad Request", status=400)
    _check_project_permission(user, project, "file.upload")
    # optional header, used to create collections
    origin_dir = request.headers.get("X-origin-dir", None)