diff --git a/backend/api/views/project.py b/backend/api/views/project.py index 4a22ae81..57ac61c0 100644 --- a/backend/api/views/project.py +++ b/backend/api/views/project.py @@ -3,7 +3,7 @@ from rest_framework import generics, status from rest_framework.permissions import IsAdminUser, IsAuthenticated from rest_framework.response import Response -from members.permissions import IsInProjectReadOnlyOrAdmin +from members.permissions import IsProjectAdmin, IsProjectStaffAndReadOnly from ..models import Project from ..serializers import ProjectPolymorphicSerializer @@ -45,4 +45,4 @@ class ProjectDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Project.objects.all() serializer_class = ProjectPolymorphicSerializer lookup_url_kwarg = 'project_id' - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] diff --git a/backend/api/views/tag.py b/backend/api/views/tag.py index ac30a814..d03e2e3b 100644 --- a/backend/api/views/tag.py +++ b/backend/api/views/tag.py @@ -1,7 +1,7 @@ from rest_framework import generics from rest_framework.permissions import IsAuthenticated -from members.permissions import IsInProjectReadOnlyOrAdmin +from members.permissions import IsProjectAdmin, IsProjectStaffAndReadOnly from ..models import Tag from ..serializers import TagSerializer @@ -10,7 +10,7 @@ from ..serializers import TagSerializer class TagList(generics.ListCreateAPIView): serializer_class = TagSerializer pagination_class = None - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] def get_queryset(self): return Tag.objects.filter(project=self.kwargs['project_id']) @@ -23,4 +23,4 @@ class TagDetail(generics.DestroyAPIView): queryset = Tag.objects.all() serializer_class = TagSerializer lookup_url_kwarg = 'tag_id' - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] diff --git a/backend/auto_labeling/views.py b/backend/auto_labeling/views.py index 34b9b7b4..e98b27e5 100644 --- a/backend/auto_labeling/views.py +++ b/backend/auto_labeling/views.py @@ -16,7 +16,7 @@ from rest_framework.response import Response from rest_framework.views import APIView from api.models import Project -from members.permissions import IsInProjectOrAdmin, IsProjectAdmin +from members.permissions import IsProjectMember, IsProjectAdmin from .pipeline.execution import execute_pipeline, get_label_collection from .exceptions import AWSTokenError, SampleDataException, TemplateMappingError, URLConnectionError from .models import AutoLabelingConfig @@ -143,7 +143,7 @@ class LabelMapperTesting(APIView): class AutomatedLabeling(generics.CreateAPIView): - permission_classes = [IsAuthenticated & IsInProjectOrAdmin] + permission_classes = [IsAuthenticated & IsProjectMember] swagger_schema = None def create(self, request, *args, **kwargs): diff --git a/backend/examples/views/comment.py b/backend/examples/views/comment.py index 96ed6eae..2457a4e6 100644 --- a/backend/examples/views/comment.py +++ b/backend/examples/views/comment.py @@ -3,14 +3,14 @@ from rest_framework import filters, generics, status from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response -from members.permissions import IsInProjectOrAdmin +from members.permissions import IsProjectMember from examples.models import Comment from examples.permissions import IsOwnComment from examples.serializers import CommentSerializer class CommentList(generics.ListCreateAPIView): - permission_classes = [IsAuthenticated & IsInProjectOrAdmin] + permission_classes = [IsAuthenticated & IsProjectMember] serializer_class = CommentSerializer filter_backends = (DjangoFilterBackend, filters.SearchFilter) filterset_fields = ['example'] @@ -38,4 +38,4 @@ class CommentDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Comment.objects.all() serializer_class = CommentSerializer lookup_url_kwarg = 'comment_id' - permission_classes = [IsAuthenticated & IsInProjectOrAdmin & IsOwnComment] + permission_classes = [IsAuthenticated & IsProjectMember & IsOwnComment] diff --git a/backend/examples/views/example.py b/backend/examples/views/example.py index b7128ea4..e3f4152b 100644 --- a/backend/examples/views/example.py +++ b/backend/examples/views/example.py @@ -11,12 +11,12 @@ from api.models import Project from examples.filters import ExampleFilter from examples.models import Example from examples.serializers import ExampleSerializer -from members.permissions import IsInProjectReadOnlyOrAdmin +from members.permissions import IsProjectAdmin, IsProjectStaffAndReadOnly class ExampleList(generics.ListCreateAPIView): serializer_class = ExampleSerializer - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter) ordering_fields = ('created_at', 'updated_at') search_fields = ('text', 'filename') @@ -55,4 +55,4 @@ class ExampleDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Example.objects.all() serializer_class = ExampleSerializer lookup_url_kwarg = 'example_id' - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] diff --git a/backend/examples/views/example_state.py b/backend/examples/views/example_state.py index ea182b43..59f19867 100644 --- a/backend/examples/views/example_state.py +++ b/backend/examples/views/example_state.py @@ -5,12 +5,12 @@ from rest_framework.permissions import IsAuthenticated from api.models import Project from examples.models import Example, ExampleState from examples.serializers import ExampleStateSerializer -from members.permissions import IsInProjectOrAdmin +from members.permissions import IsProjectMember class ExampleStateList(generics.ListCreateAPIView): serializer_class = ExampleStateSerializer - permission_classes = [IsAuthenticated & IsInProjectOrAdmin] + permission_classes = [IsAuthenticated & IsProjectMember] @property def can_confirm_per_user(self): diff --git a/backend/label_types/views.py b/backend/label_types/views.py index 8297b3c6..3b041424 100644 --- a/backend/label_types/views.py +++ b/backend/label_types/views.py @@ -10,7 +10,7 @@ from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView -from members.permissions import IsInProjectReadOnlyOrAdmin, IsProjectAdmin +from members.permissions import IsProjectAdmin, IsProjectStaffAndReadOnly from .models import LabelType, CategoryType, SpanType, RelationType from .exceptions import LabelValidationError from .serializers import (CategoryTypeSerializer, LabelSerializer, @@ -31,7 +31,7 @@ class LabelList(generics.ListCreateAPIView): filter_backends = [DjangoFilterBackend] serializer_class = LabelSerializer pagination_class = None - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] def get_queryset(self): return self.model.objects.filter(project=self.kwargs['project_id']) @@ -54,7 +54,7 @@ class CategoryTypeDetail(generics.RetrieveUpdateDestroyAPIView): queryset = CategoryType.objects.all() serializer_class = CategoryTypeSerializer lookup_url_kwarg = 'label_id' - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] class SpanTypeList(LabelList): @@ -66,7 +66,7 @@ class SpanTypeDetail(generics.RetrieveUpdateDestroyAPIView): queryset = SpanType.objects.all() serializer_class = SpanTypeSerializer lookup_url_kwarg = 'label_id' - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] class RelationTypeList(LabelList): @@ -78,7 +78,7 @@ class RelationTypeDetail(generics.RetrieveUpdateDestroyAPIView): queryset = RelationType.objects.all() serializer_class = RelationTypesSerializer lookup_url_kwarg = 'relation_type_id' - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] class LabelUploadAPI(APIView): diff --git a/backend/labels/views.py b/backend/labels/views.py index e2cc8fb2..c1e0f702 100644 --- a/backend/labels/views.py +++ b/backend/labels/views.py @@ -8,7 +8,7 @@ from rest_framework.response import Response from api.models import Project from labels.models import Category, Span, TextLabel, Relation -from members.permissions import IsInProjectOrAdmin, IsInProjectReadOnlyOrAdmin +from members.permissions import IsProjectMember from .permissions import CanEditLabel from .serializers import CategorySerializer, SpanSerializer, TextLabelSerializer, RelationSerializer @@ -16,7 +16,7 @@ from .serializers import CategorySerializer, SpanSerializer, TextLabelSerializer class BaseListAPI(generics.ListCreateAPIView): label_class = None pagination_class = None - permission_classes = [IsAuthenticated & IsInProjectOrAdmin] + permission_classes = [IsAuthenticated & IsProjectMember] swagger_schema = None @property @@ -56,10 +56,10 @@ class BaseDetailAPI(generics.RetrieveUpdateDestroyAPIView): def get_permissions(self): if self.project.collaborative_annotation: - self.permission_classes = [IsAuthenticated & IsInProjectOrAdmin] + self.permission_classes = [IsAuthenticated & IsProjectMember] else: self.permission_classes = [ - IsAuthenticated & IsInProjectOrAdmin & partial(CanEditLabel, self.queryset) + IsAuthenticated & IsProjectMember & partial(CanEditLabel, self.queryset) ] return super().get_permissions() @@ -102,7 +102,7 @@ class TextLabelDetailAPI(BaseDetailAPI): class RelationList(generics.ListCreateAPIView): serializer_class = RelationSerializer pagination_class = None - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & IsProjectMember] def get_queryset(self): project = get_object_or_404(Project, pk=self.kwargs['project_id']) @@ -122,4 +122,4 @@ class RelationDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Relation.objects.all() serializer_class = RelationSerializer lookup_url_kwarg = 'annotation_id' - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & IsProjectMember] diff --git a/backend/members/permissions.py b/backend/members/permissions.py index 80c6a977..81d69112 100644 --- a/backend/members/permissions.py +++ b/backend/members/permissions.py @@ -50,5 +50,5 @@ class IsAnnotationApprover(RolePermission): role_name = settings.ROLE_ANNOTATION_APPROVER -IsInProjectReadOnlyOrAdmin = (IsAnnotatorAndReadOnly | IsAnnotationApproverAndReadOnly | IsProjectAdmin) -IsInProjectOrAdmin = (IsAnnotator | IsAnnotationApprover | IsProjectAdmin) +IsProjectMember = (IsAnnotator | IsAnnotationApprover | IsProjectAdmin) +IsProjectStaffAndReadOnly = (IsAnnotatorAndReadOnly | IsAnnotationApproverAndReadOnly) diff --git a/backend/metrics/views.py b/backend/metrics/views.py index 6effdf08..6b665c89 100644 --- a/backend/metrics/views.py +++ b/backend/metrics/views.py @@ -9,11 +9,11 @@ from examples.models import Example, ExampleState from label_types.models import LabelType, CategoryType, SpanType from labels.models import Label, Category, Span from members.models import Member -from members.permissions import IsInProjectReadOnlyOrAdmin +from members.permissions import IsProjectAdmin, IsProjectStaffAndReadOnly class ProgressAPI(APIView): - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] def get(self, request, *args, **kwargs): examples = Example.objects.filter(project=self.kwargs['project_id']).values('id') @@ -23,7 +23,7 @@ class ProgressAPI(APIView): class MemberProgressAPI(APIView): - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] def get(self, request, *args, **kwargs): examples = Example.objects.filter(project=self.kwargs['project_id']).values('id') @@ -33,7 +33,7 @@ class MemberProgressAPI(APIView): class LabelDistribution(abc.ABC, APIView): - permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin] + permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)] model = Label label_type = LabelType