Skip to content

Commit 45495cf

Browse files
committed
Make identification task attribute able on list if user has annotated on task
1 parent b7f04a1 commit 45495cf

File tree

5 files changed

+83
-2
lines changed

5 files changed

+83
-2
lines changed

api/mixins.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from typing import Optional
2+
3+
from tigacrafting.models import IdentificationTask
4+
5+
class IdentificationTaskNestedAttribute():
6+
def get_parent_lookup_url_kwarg(self) -> str:
7+
return 'observation_uuid'
8+
9+
def get_identification_task_obj(self) -> Optional[IdentificationTask]:
10+
if task_id := self.kwargs.get(self.get_parent_lookup_url_kwarg(), None):
11+
return IdentificationTask.objects.get(pk=task_id)
12+
13+
def get_permissions(self):
14+
return [
15+
permission(identification_task=self.get_identification_task_obj())
16+
for permission in self.permission_classes
17+
]

api/permissions.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Optional
2+
13
from django.contrib.auth import get_user_model
24
from django.core.exceptions import MultipleObjectsReturned
35

@@ -190,6 +192,15 @@ def has_permission(self, request, view):
190192
})
191193

192194
class BaseIdentificationTaskAttributePermissions(BaseIdentificationTaskPermissions):
195+
def __init__(self, identification_task, *args, **kwargs):
196+
self.identification_task = identification_task
197+
super().__init__(*args, **kwargs)
198+
199+
def has_permission(self, request, view):
200+
if view.action == 'list' and self.identification_task:
201+
if self._check_is_annotator(request, view, obj=self.identification_task):
202+
return True
203+
return super().has_permission(request, view)
193204
pass
194205

195206
class AnnotationPermissions(BaseIdentificationTaskAttributePermissions):

api/tests/integration/identification_tasks/annotations/list.tavern.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,31 @@ stages:
5555
method: "GET"
5656
headers:
5757
Authorization: "Bearer {jwt_token_user_can_view:s}"
58+
response:
59+
status_code: 200
60+
json: !force_format_include "{response_list_data_validation}"
61+
62+
---
63+
64+
test_name: Annotation can be lsit by users without permissions if from a identification task they have annotate.
65+
66+
includes:
67+
- !include schema.yml
68+
69+
marks:
70+
- usefixtures:
71+
- api_live_url
72+
- endpoint
73+
- annotation
74+
- jwt_token_user
75+
76+
stages:
77+
- name: User without perm view can retrieve if annotation from the same task
78+
request:
79+
url: "{api_live_url}/{endpoint}/"
80+
method: "GET"
81+
headers:
82+
Authorization: "Bearer {jwt_token_user:s}"
5883
response:
5984
status_code: 200
6085
json: !force_format_include "{response_list_data_validation}"

api/tests/integration/identification_tasks/predictions/list.tavern.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,33 @@ stages:
5656
method: "GET"
5757
headers:
5858
Authorization: "Bearer {jwt_token_user_can_view:s}"
59+
response:
60+
status_code: 200
61+
json: !force_format_include "{response_list_data_validation}"
62+
63+
64+
---
65+
66+
test_name: Predictions can be list by users without permissions if from a identification task they have annotate.
67+
68+
includes:
69+
- !include schema.yml
70+
71+
marks:
72+
- usefixtures:
73+
- api_live_url
74+
- endpoint
75+
- annotation
76+
- photo_prediction
77+
- jwt_token_user
78+
79+
stages:
80+
- name: User without perm view can list if annotation from the same task
81+
request:
82+
url: "{api_live_url}/{endpoint}/"
83+
method: "GET"
84+
headers:
85+
Authorization: "Bearer {jwt_token_user:s}"
5986
response:
6087
status_code: 200
6188
json: !force_format_include "{response_list_data_validation}"

api/views.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
AnnotationFilter,
5656
TaxonFilter
5757
)
58+
from .mixins import IdentificationTaskNestedAttribute
5859
from .serializers import (
5960
PartnerSerializer,
6061
CampaignSerializer,
@@ -565,7 +566,7 @@ def assign_next(self, request):
565566
)
566567
]
567568
)
568-
class PhotoPredictionViewSet(NestedViewSetMixin, CreateModelMixin, RetrieveModelMixin, ListModelMixin, UpdateModelMixin, DestroyModelMixin, GenericNoMobileViewSet):
569+
class PhotoPredictionViewSet(IdentificationTaskNestedAttribute, NestedViewSetMixin, CreateModelMixin, RetrieveModelMixin, ListModelMixin, UpdateModelMixin, DestroyModelMixin, GenericNoMobileViewSet):
569570
queryset = PhotoPrediction.objects.all()
570571
permission_classes = (PhotoPredictionPermissions, )
571572

@@ -597,7 +598,7 @@ def get_serializer_context(self):
597598
)
598599
]
599600
)
600-
class AnnotationViewSet(NestedViewSetMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, GenericNoMobileViewSet):
601+
class AnnotationViewSet(IdentificationTaskNestedAttribute, NestedViewSetMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, GenericNoMobileViewSet):
601602
queryset = ExpertReportAnnotation.objects.is_annotation().select_related(
602603
'user',
603604
'report',

0 commit comments

Comments
 (0)