Skip to content

Feature roles api #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion pycaprio/core/adapters/http_adapter.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from typing import IO, Union
from typing import List
from typing import Optional

from pycaprio.core.clients.retryable_client import RetryableInceptionClient
from pycaprio.core.interfaces.adapter import BaseInceptionAdapter
from pycaprio.core.interfaces.client import BaseInceptionClient
from pycaprio.core.interfaces.types import authentication_type
from pycaprio.core.mappings import AnnotationState
from pycaprio.core.mappings import InceptionFormat
from pycaprio.core.mappings import DocumentState
from pycaprio.core.objects.role import Role
from pycaprio.core.objects.annotation import Annotation
from pycaprio.core.objects.document import Document
from pycaprio.core.objects.project import Project
Expand All @@ -17,6 +17,7 @@
from pycaprio.core.schemas.document import DocumentSchema
from pycaprio.core.schemas.project import ProjectSchema
from pycaprio.core.schemas.curation import CurationSchema
from pycaprio.core.schemas.role import RoleSchema


class HttpInceptionAdapter(BaseInceptionAdapter):
Expand Down Expand Up @@ -215,6 +216,21 @@ def delete_curation(self, project: Union[Project, int], document: Union[Document
self.client.delete(f"/projects/{project_id}/documents/{document_id}/curation")
return True

def list_roles(self, project: Union[Project, int], user_id: str) -> List[Role]:
project_id = self._get_object_id(project)
response = self.client.get(f"/projects/{project_id}/permissions/{user_id}")
return RoleSchema().load(response.json()["body"], many=True)

def assign_roles(self, project: Union[Project, int], user_id: str, roles: List[str]) -> List[Role]:
project_id = self._get_object_id(project)
response = self.client.post(f"/projects/{project_id}/permissions/{user_id}", data={"roles": roles})
return RoleSchema().load(response.json()["body"], many=True)

def delete_roles(self, project: Union[Project, int], user_id: str, roles: List[str]) -> List[Role]:
project_id = self._get_object_id(project)
response = self.client.delete(f"/projects/{project_id}/permissions/{user_id}", data={"roles": roles})
return RoleSchema().load(response.json()["body"], many=True)

@staticmethod
def _get_object_id(o: Union[int, Project, Document, Annotation]) -> int:
object_id_mappings = {
Expand Down
4 changes: 2 additions & 2 deletions pycaprio/core/clients/retryable_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ def post(
) -> requests.Response:
return self.request("post", url, data=data, form_data=form_data, files=files)

def delete(self, url: str) -> requests.Response:
return self.request("delete", url)
def delete(self, url: str, data: Optional[dict] = None) -> requests.Response:
return self.request("delete", url, data=data)

def request(self, method: str, url: str, **kwargs) -> requests.Response:
retries = 0
Expand Down
30 changes: 30 additions & 0 deletions pycaprio/core/interfaces/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from pycaprio.core.objects.document import Document
from pycaprio.core.objects.project import Project
from pycaprio.core.objects.curation import Curation
from pycaprio.core.objects.role import RoleType


class BaseInceptionAdapter(metaclass=ABCMeta):
Expand Down Expand Up @@ -250,3 +251,32 @@ def delete_curation(self, project: Union[Project, int], document: Union[Document
:param project: Project/Project id.
"""
pass # pragma: no cover

@abstractmethod
def list_roles(self, project: Union[Project, int], userId: str) -> List[RoleType]:
"""
List permissions for a user in the given project (non AERO)
:param project: Project/Project id.
:param userId: Username.
"""
pass # pragma: no cover

@abstractmethod
def assign_roles(self, project: Union[Project, int], userId: str, role: List[RoleType]) -> List[RoleType]:
"""
Assign roles to a user in the given project (non-AERO)
:param project: Project/Project id.
:param userId: Username.
:param role: List of Roles [See PermissionRoles in mappings]
"""
pass # pragma: no cover

@abstractmethod
def delete_roles(self, project: Union[Project, int], userId: str, role: List[RoleType]) -> List[RoleType]:
"""
Delete roles to a user in the given project (non-AERO)
:param project: Project/Project id.
:param userId: Username.
:param role: List of Roles [See PermissionRoles in mappings]
"""
pass # pragma: no cover
2 changes: 1 addition & 1 deletion pycaprio/core/interfaces/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def post(self, url: str, json: dict, files: dict) -> requests.Response:
pass # pragma: no cover

@abstractmethod
def delete(self, url: str) -> requests.Response:
def delete(self, url: str, json: dict) -> requests.Response:
"""
Issues an authenticated DELETE request to Inception
:param url: relative url to make request
Expand Down
7 changes: 7 additions & 0 deletions pycaprio/core/mappings.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,10 @@ class DocumentState:
ANNOTATION_COMPLETE = "ANNOTATION-COMPLETE"
CURATION_IN_PROGRESS = "CURATION-IN-PROGRESS"
CURATION_COMPLETE = "CURATION-COMPLETE"


class RoleType:
# https://github.com/inception-project/inception/blob/main/inception/inception-model/src/main/java/de/tudarmstadt/ukp/clarin/webanno/model/PermissionLevel.java
ANNOTATOR = "ANNOTATOR"
CURATOR = "CURATOR"
MANAGER = "MANAGER"
1 change: 1 addition & 0 deletions pycaprio/core/objects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
from pycaprio.core.objects.document import Document
from pycaprio.core.objects.project import Project
from pycaprio.core.objects.curation import Curation
from pycaprio.core.objects.role import Role
21 changes: 21 additions & 0 deletions pycaprio/core/objects/role.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
__any__ = ["Role"]

import typing
from pycaprio.core.mappings import RoleType


class Role:
"""
INCEpTION's Permissions object
"""

def __init__(self, project_id: int, userId: str, roles: typing.List[RoleType]):
self.project_id = project_id
self.userId = userId
self.roles = roles

def __repr__(self):
return f"<Role #ProjectId: {self.project_id}, UserId: {self.userId}, Roles: {self.roles}>"

def __str__(self):
return repr(self)
24 changes: 24 additions & 0 deletions pycaprio/core/schemas/role.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from typing import Union
from typing import List
from pycaprio.core.interfaces.schema import BaseInceptionSchema
from pycaprio.core.objects.role import Role

serialized_type = Union[List[dict], dict]
deserialized_type = Union[List[Role], Role]


class RoleSchema(BaseInceptionSchema):
"""
Schema to serialize/deserialize Roles.
Documentation is described in 'BaseInceptionSchema'.
"""

def load(self, roles_dict: serialized_type, many: bool = False) -> deserialized_type:
if many:
return [self.load(project, many=False) for project in roles_dict]
return Role(project_id=roles_dict["project"], userId=roles_dict["user"], roles=roles_dict["role"])

def dump(self, roles: deserialized_type, many: bool = False) -> serialized_type:
if many:
return [self.dump(p, many=False) for p in roles]
return {"projectId": roles.project_id, "user": roles.userId, "role": roles.roles}
2 changes: 1 addition & 1 deletion pycaprio/mappings.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# flake8: noqa
from pycaprio.core.mappings import InceptionFormat, DocumentState, AnnotationState # pragma: no cover
from pycaprio.core.mappings import InceptionFormat, DocumentState, AnnotationState, RoleType # pragma: no cover