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

remove public_owner references in rpc methods

parent 87638d3b
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -157,9 +157,9 @@ def make_iiif(f: models.File):

def delete_exif_metas(f: models.File) -> int:
    deleted_counter = 0
    public_owner = User.objects.get(username="public_user")
    public_project = models.fetch_public_project()
    exiftools_metas_set = models.MetadataSet.objects.filter(
        title="ExifTool", owner=public_owner
        title="ExifTool", project=public_project
    ).first()
    for meta_value in models.MetadataResourceValue.objects.filter(
        resource=f, metadata__set=exiftools_metas_set
@@ -173,23 +173,23 @@ def set_exif_metas(f: models.File) -> int:
    """
    Will run Exiftool on given models.File.local_path().
    Extracted data is then converted to Metadatas.
    ExifTool MetadataSet and Metadatas alway have public_owner
    as owner.
    ExifTool MetadataSet and Metadatas always have public_project
    as project.
    """
    added_counter = 0
    public_owner = User.objects.get(username="public_user")
    public_project = models.fetch_public_project()
    exiftools_metas = image_metadatas(f.local_path())
    if "ExifTool:Error" not in exiftools_metas:
        # first delete ExifTool metas
        delete_exif_metas(f)
        # then insert new metas from extracted data
        exiftools_metas_set = models.MetadataSet.objects.filter(
            title="ExifTool", owner=public_owner
            title="ExifTool", project=public_project
        ).first()
        if exiftools_metas_set:
            for key in exiftools_metas:
                metadata, created = models.Metadata.objects.get_or_create(
                    title=key, set=exiftools_metas_set, owner=public_owner
                    title=key, set=exiftools_metas_set, project=public_project
                )
                models.MetadataResourceValue.objects.get_or_create(
                    metadata=metadata,
+18 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ from resources.models import Project, Role, ProjectAccess, Permission
def migrate_property():
    permission_instances = []
    obj_types = ["collection", "resource", "metadata", "metadataset", "file", "tag"]
    permissions = ["read", "write", "delete"]
    permissions = ["add", "read", "write", "delete"]
    for obj_type in obj_types:
        for permission in permissions:
            perm, created = Permission.objects.get_or_create(
@@ -61,6 +61,23 @@ def migrate_property():
                    project.pk, user.pk
                )
            )
    # allow read access to public_project for all users
    # (ie. allow access to exif and OCR metas)
    public_user = User.objects.get(username="public_user")
    public_project = Project.objects.get(projectaccess__user=public_user)
    public_read_role, created = Role.objects.get_or_create(
        label="public_reader", project=public_project
    )
    for permission_label in [
        "collection.read",
        "resource.read",
        "metadata.read",
        "metadataset.read",
        "file.read",
        "tag.read",
    ]:
        permission = Permission.objects.get(label=permission_label)
        public_read_role.permissions.add(permission)


class Migration(migrations.Migration):
+15 −11
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ from typing import Iterator, Union, List
from django.db.models.signals import post_save
from django.dispatch import receiver
from subprocess import call
from functools import lru_cache


def hash_to_iiif_path(file_hash: str) -> str:
@@ -61,9 +62,12 @@ class Project(models.Model):
        return self.label


@lru_cache()
def fetch_public_project() -> Project:
    project, created = Project.objects.get_or_create(label="public project")
    return project
    public_owner = User.objects.get(username="public_user")
    # there should be one public project after migrations
    public_project = Project.objects.filter(projectaccess__user=public_owner).first()
    return public_project


class Tag(models.Model):
@@ -271,12 +275,12 @@ class File(Resource):
        """
        Fetch OCR output if available. None if not available.
        """
        public_owner = User.objects.get(username="public_user")
        public_project = fetch_public_project()
        metas_set, created = MetadataSet.objects.get_or_create(
            title="OCR", owner=public_owner
            title="OCR", project=public_project
        )
        meta, created = Metadata.objects.get_or_create(
            owner=public_owner, title="tesseract output", set=metas_set
            title="tesseract output", set=metas_set, project=public_project
        )
        try:
            meta_value = MetadataResourceValue.objects.get(metadata=meta, resource=self)
@@ -299,12 +303,12 @@ class File(Resource):
        if ocr_return_code == 0:
            with open(self.local_path() + ".ocr.txt", "r") as ocr:
                content = ocr.read()
                public_owner = User.objects.get(username="public_user")
                public_project = fetch_public_project()
                metas_set, created = MetadataSet.objects.get_or_create(
                    title="OCR", owner=public_owner
                    title="OCR", project=public_project
                )
                meta, created = Metadata.objects.get_or_create(
                    owner=public_owner, title="tesseract output", set=metas_set
                    project=public_project, title="tesseract output", set=metas_set
                )
                (_, created,) = MetadataResourceValue.objects.get_or_create(
                    metadata=meta, resource=self, value=content.strip()
@@ -317,12 +321,12 @@ class File(Resource):
            if pdftotext_return_code == 0:
                with open(self.local_path() + ".pdftotext.txt", "r") as text_layer:
                    content = text_layer.read()
                    public_owner = User.objects.get(username="public_user")
                    public_project = fetch_public_project()
                    metas_set, created = MetadataSet.objects.get_or_create(
                        title="OCR", owner=public_owner
                        title="OCR", project=public_project
                    )
                    meta, created = Metadata.objects.get_or_create(
                        owner=public_owner, title="pdftotext output", set=metas_set
                        project=public_project, title="pdftotext output", set=metas_set
                    )
                    (_, created,) = MetadataResourceValue.objects.get_or_create(
                        metadata=meta, resource=self, value=content.strip()
+57 −24
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ from resources.models import (
    Project,
    ProjectAccess,
    APIKey,
    fetch_public_project,
)
from django.contrib.auth.models import User
from django.db.models import QuerySet
@@ -28,10 +29,19 @@ class ServiceException(Exception):
    pass


def _check_project_permission(user: User, project: Project, permission: str) -> bool:
def _check_project_permission(
    user: User, project: Union[Project, int], permission: str
) -> bool:
    """
    Will raise a ServiceException if user has no access to given project/permission.
    Will raise a ServiceException if:
        - user has no access to given project/permission
        - project is int and no such pk exists
    """
    if isinstance(project, int):
        try:
            project = Project.objects.get(pk=project)
        except Project.DoesNotExist:
            raise ServiceException("no such project")
    access = ProjectAccess.objects.filter(
        user=user, project=project, role__permissions__label=permission
    ).first()
@@ -88,9 +98,11 @@ def projects_permissions(user: User) -> List[Dict]:
projects_permissions.rpc_groups = ["Utilities"]


def metadatasets(user: User) -> List[Dict]:
def metadatasets(user: User, project_id: int) -> List[Dict]:
    """
    Get the list of all the user's metadata sets.
    Get the list of all the user's metadata sets. This includes
    metadatas sets for the given project_id, as well as the "public"
    metadatas sets (exiftool, ocr, etc).
    For each metadatas set, the number of metadatas is given in metas_count

    Example output:
@@ -102,14 +114,19 @@ def metadatasets(user: User) -> List[Dict]:
    ]
    ```
    """
    try:
        project = Project.objects.get(pk=project_id)
        _check_project_permission(user, project, "metadataset.read")
        data = []
    public_owner = User.objects.get(username="public_user")
        # Get the project metadatasets AND the public metadatasets
        query_set: Iterator[MetadataSet] = MetadataSet.objects.filter(
        owner=user
    ) | MetadataSet.objects.filter(owner=public_owner)
            project=project
        ) | MetadataSet.objects.filter(project=fetch_public_project())
        for item in query_set:
            data.append(serializers.metadataset(item))
        return data
    except Project.DoesNotExist:
        raise ServiceException("no such project")


metadatasets.rpc_groups = ["Metadatas"]
@@ -145,10 +162,9 @@ def metadatas(user: User, metadata_set_id: int) -> List[Dict]:
    ```
    """
    data = []
    public_owner = User.objects.get(username="public_user")
    query_set: Union[Iterator[MetadataSet], QuerySet] = MetadataSet.objects.filter(
        owner=user, id=metadata_set_id
    ) | MetadataSet.objects.filter(owner=public_owner, id=metadata_set_id)
        project__projectaccess__user=user, id=metadata_set_id
    ) | MetadataSet.objects.filter(project=fetch_public_project(), id=metadata_set_id)
    metadata_set: MetadataSet = query_set.first()
    if metadata_set:
        for metadata_instance in Metadata.objects.filter(
@@ -178,10 +194,11 @@ def metadata(user: User, metadata_id: int) -> Union[Dict, None]:
    }
    ```
    """
    public_owner = User.objects.get(username="public_user")
    query_set: Union[Iterator[Collection], QuerySet] = Metadata.objects.filter(
        pk=metadata_id, owner=user
    ) | Metadata.objects.filter(pk=metadata_id, owner=public_owner)
        pk=metadata_id,
        project__projectaccess__user=user,
        project__projectaccess__role__permissions__label="metadata.read",
    )
    metadata_instance = query_set.first()
    if not metadata_instance:
        return None
@@ -1088,11 +1105,20 @@ def add_meta_to_resource(
    if meta_value == "" or meta_value is None:
        return False
    try:
        public_owner = User.objects.get(username="public_user")
        resource_instance = Resource.objects.get(
            ptr_owner=user, id=resource_id, deleted_at__isnull=True
            pk=resource_id,
            deleted_at__isnull=True,
            ptr_project__projectaccess__user=user,
            ptr_project__projectaccess__role__permission__label="resource.read",
        )
        # Adding a meta value to a resource is a resource.write, NOT a metadata.write.
        # No need to go further.
        _check_project_permission(user, resource_instance.ptr_project, "resource.write")
        meta = Metadata.objects.get(
            pk=meta_id,
            project__projectaccess__user=user,
            project__projectaccess__role__permission__label="metadata.read",
        )
        meta = Metadata.objects.get(owner__in=[public_owner, user], id=meta_id)
        meta_value_instance, created = MetadataResourceValue.objects.get_or_create(
            metadata=meta, resource=resource_instance, value=meta_value
        )
@@ -1140,11 +1166,18 @@ def add_meta_to_collection(
    if meta_value == "" or meta_value is None:
        return False
    try:
        public_owner = User.objects.get(username="public_user")
        collection_instance = Collection.objects.get(
            owner=user, id=collection_id, deleted_at__isnull=True
            pk=collection_id,
            deleted_at__isnull=True,
            project__projectaccess__user=user,
            project__projectaccess__role__permission__label="collection.read",
        )
        meta = Metadata.objects.get(
            id=meta_id,
            project__projectaccess__user=user,
            project__projectaccess__role__permission__label="metadata.read",
        )
        meta = Metadata.objects.get(owner__in=[public_owner, user], id=meta_id)
        _check_project_permission(user, collection_instance.project, "collection.write")
        meta_value_instance, created = MetadataCollectionValue.objects.get_or_create(
            metadata=meta, collection=collection_instance, value=meta_value
        )