diff --git a/cvat/apps/authentication/auth.py b/cvat/apps/authentication/auth.py index 0da83216e8ed..aec58fc9cb99 100644 --- a/cvat/apps/authentication/auth.py +++ b/cvat/apps/authentication/auth.py @@ -6,6 +6,9 @@ from django.conf import settings import rules from . import AUTH_ROLE +from rest_framework.permissions import (BasePermission, IsAuthenticated, + IsAdminUser) + def register_signals(): from django.db.models.signals import post_migrate, post_save @@ -67,6 +70,11 @@ def is_job_annotator(db_user, db_job): return has_rights # AUTH PERMISSIONS RULES +rules.add_perm('engine.role.user', has_user_role) +rules.add_perm('engine.role.admin', has_admin_role) +rules.add_perm('engine.role.annotator', has_annotator_role) +rules.add_perm('engine.role.observer', has_observer_role) + rules.add_perm('engine.task.create', has_admin_role | has_user_role) rules.add_perm('engine.task.access', has_admin_role | has_observer_role | is_task_owner | is_task_annotator) @@ -78,3 +86,43 @@ def is_job_annotator(db_user, db_job): is_job_owner | is_job_annotator) rules.add_perm('engine.job.change', has_admin_role | is_job_owner | is_job_annotator) + +class AdminRolePermission(BasePermission): + def has_permission(self, request, view): + return request.user.has_perm("engine.role.admin") + +class UserRolePermission(BasePermission): + def has_permission(self, request, view): + return request.user.has_perm("engine.role.user") + +class AnnotatorRolePermission(BasePermission): + def has_permission(self, request, view): + return request.user.has_perm("engine.role.annotator") + +class ObserverRolePermission(BasePermission): + def has_permission(self, request, view): + return request.user.has_perm("engine.role.observer") + +class TaskCreatePermission(BasePermission): + def has_permission(self, request, view): + return request.user.has_perm("engine.task.create") + +class TaskAccessPermission(BasePermission): + def has_object_permission(self, request, view, obj): + return request.user.has_perm("engine.task.access", obj) + +class TaskChangePermission(BasePermission): + def has_object_permission(self, request, view, obj): + return request.user.has_perm("engine.task.change", obj) + +class TaskDeletePermission(BasePermission): + def has_object_permission(self, request, view, obj): + return request.user.has_perm("engine.task.delete", obj) + +class JobAccessPermission(BasePermission): + def has_object_permission(self, request, view, obj): + return request.user.has_perm("engine.job.access", obj) + +class JobChangePermission(BasePermission): + def has_object_permission(self, request, view, obj): + return request.user.has_perm("engine.job.change", obj) diff --git a/cvat/apps/engine/urls.py b/cvat/apps/engine/urls.py index 511b46741289..99ced59fbb23 100644 --- a/cvat/apps/engine/urls.py +++ b/cvat/apps/engine/urls.py @@ -27,7 +27,7 @@ #path('create/task', views.create_task), #path('get/task//frame/', views.get_frame), path('check/task/', views.check_task), - path('delete/task/', views.delete_task), + #path('delete/task/', views.delete_task), path('update/task/', views.update_task), path('get/job/', views.get_job), path('get/task/', views.get_task), diff --git a/cvat/apps/engine/views.py b/cvat/apps/engine/views.py index d88a09f0e1e8..28cacd389abe 100644 --- a/cvat/apps/engine/views.py +++ b/cvat/apps/engine/views.py @@ -38,6 +38,8 @@ ExceptionSerializer, AboutSerializer, JobSerializer, ImageMetaSerializer, RqStatusSerializer, TaskDataSerializer, PluginSerializer) from django.contrib.auth.models import User +from cvat.apps.authentication import auth +from rest_framework.permissions import SAFE_METHODS # Server REST API @@ -94,6 +96,29 @@ class TaskViewSet(viewsets.ModelViewSet): queryset = Task.objects.all() serializer_class = TaskSerializer + def get_permissions(self): + http_method = self.request.method + permissions = [auth.IsAuthenticated] + + if http_method in auth.SAFE_METHODS: + permissions.append(auth.TaskAccessPermission) + elif http_method in ["POST"]: + permissions.append(auth.TaskCreatePermission) + elif http_method in ["PATCH", "PUT"]: + permissions.append(auth.TaskChangePermission) + elif http_method in ["DELETE"]: + permissions.append(auth.TaskDeletePermission) + else: + permissions.append(auth.AdminRolePermission) + + return [perm() for perm in permissions] + + def perform_create(self, serializer): + if self.request.data.get('owner', None): + serializer.save() + else: + serializer.save(owner=self.request.user) + def perform_destroy(self, instance): task_dirname = instance.get_task_dirname() super().perform_destroy(instance) @@ -177,19 +202,24 @@ def frame(self, request, pk, frame): return HttpResponseBadRequest(str(e)) - - def perform_create(self, serializer): - if self.request.data.get('owner', None): - serializer.save() - else: - serializer.save(owner=self.request.user) - - class JobViewSet(viewsets.GenericViewSet, mixins.RetrieveModelMixin, mixins.UpdateModelMixin): queryset = Job.objects.all() serializer_class = JobSerializer + def get_permissions(self): + http_method = self.request.method + permissions = [auth.IsAuthenticated] + + if http_method in SAFE_METHODS: + permissions.append(auth.JobAccessPermission) + elif http_method in ["PATCH", "PUT"]: + permissions.append(auth.JobChangePermission) + else: + permissions.append(auth.AdminRolePermission) + + return [perm() for perm in permissions] + #@action(detail=True, methods=['GET', 'DELETE', 'POST'], serializer_class=None) @action(detail=True, methods=['GET'], serializer_class=None) def annotations(self, request, pk): @@ -201,6 +231,17 @@ class UserViewSet(viewsets.GenericViewSet, mixins.ListModelMixin, queryset = User.objects.all() serializer_class = UserSerializer + def get_permissions(self): + http_method = self.request.method + permissions = [auth.IsAuthenticated] + + if self.action in ["self"]: + pass + else: + permissions.append(auth.AdminRolePermission) + + return [perm() for perm in permissions] + @action(detail=False, methods=['GET'], serializer_class=UserSerializer) def self(self, request): serializer = UserSerializer(request.user, context={ "request": request })