diff --git a/backend/api/serializers.py b/backend/api/serializers.py index 4290e2c0..29699250 100644 --- a/backend/api/serializers.py +++ b/backend/api/serializers.py @@ -108,6 +108,7 @@ class DocumentSerializer(serializers.ModelSerializer): class ImageSerializer(serializers.ModelSerializer): annotations = serializers.SerializerMethodField() annotation_approver = serializers.SerializerMethodField() + filename = serializers.FilePathField(path='.') def get_annotations(self, instance): request = self.context.get('request') diff --git a/backend/api/tests/api/test_image.py b/backend/api/tests/api/test_image.py new file mode 100644 index 00000000..31172ce3 --- /dev/null +++ b/backend/api/tests/api/test_image.py @@ -0,0 +1,53 @@ +from rest_framework import status +from rest_framework.reverse import reverse + +from ...models import DOCUMENT_CLASSIFICATION +from .utils import CRUDMixin, make_image, make_user, prepare_project + + +class TestImageListAPI(CRUDMixin): + + def setUp(self): + self.project = prepare_project(task=DOCUMENT_CLASSIFICATION) + self.non_member = make_user() + make_image(self.project.item) + self.url = reverse(viewname='image_list', args=[self.project.item.id]) + + def test_allows_project_member_to_list_images(self): + for member in self.project.users: + self.assert_fetch(member, status.HTTP_200_OK) + + def test_denies_non_project_member_to_list_images(self): + self.assert_fetch(self.non_member, status.HTTP_403_FORBIDDEN) + + def test_denies_unauthenticated_user_to_list_images(self): + self.assert_fetch(expected=status.HTTP_403_FORBIDDEN) + + +class TestImageDetail(CRUDMixin): + + def setUp(self): + self.project = prepare_project(task=DOCUMENT_CLASSIFICATION) + self.non_member = make_user() + image = make_image(self.project.item) + self.url = reverse(viewname='image_detail', args=[self.project.item.id, image.id]) + + def test_allows_project_member_to_get_image(self): + for member in self.project.users: + self.assert_fetch(member, status.HTTP_200_OK) + + def test_denies_non_project_member_to_get_image(self): + self.assert_fetch(self.non_member, status.HTTP_403_FORBIDDEN) + + def test_denies_unauthenticated_user_to_get_image(self): + self.assert_fetch(expected=status.HTTP_403_FORBIDDEN) + + def test_allows_project_admin_to_delete_image(self): + self.assert_delete(self.project.users[0], status.HTTP_204_NO_CONTENT) + + def test_denies_non_project_admin_to_delete_image(self): + for member in self.project.users[1:]: + self.assert_delete(member, status.HTTP_403_FORBIDDEN) + + def test_denies_non_project_member_to_delete_image(self): + self.assert_delete(self.non_member, status.HTTP_403_FORBIDDEN) diff --git a/backend/api/tests/api/utils.py b/backend/api/tests/api/utils.py index 2b37e2a7..469cc0c4 100644 --- a/backend/api/tests/api/utils.py +++ b/backend/api/tests/api/utils.py @@ -92,6 +92,10 @@ def make_doc(project): return mommy.make('Document', project=project) +def make_image(project): + return mommy.make('Image', project=project) + + def make_comment(doc, user): return mommy.make('Comment', document=doc, user=user) diff --git a/backend/api/urls.py b/backend/api/urls.py index 0913a186..4e23747b 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -52,6 +52,16 @@ urlpatterns_project = [ view=views.DocumentDetail.as_view(), name='doc_detail' ), + path( + route='images', + view=views.ImageList.as_view(), + name='image_list' + ), + path( + route='images/', + view=views.ImageDetail.as_view(), + name='image_detail' + ), path( route='docs//approve-labels', view=views.ApproveLabelsAPI.as_view(), diff --git a/backend/api/views/__init__.py b/backend/api/views/__init__.py index 22e7829b..6a84885e 100644 --- a/backend/api/views/__init__.py +++ b/backend/api/views/__init__.py @@ -4,6 +4,7 @@ from .comment import * from .document import * from .export_dataset import * from .health import * +from .image import * from .import_dataset import * from .import_export import * from .label import *