Skip to content

Commit

Permalink
Add permissions for REST API.
Browse files Browse the repository at this point in the history
  • Loading branch information
nmanovic committed Feb 10, 2019
1 parent dcbbcb7 commit 6b7f69d
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 9 deletions.
48 changes: 48 additions & 0 deletions cvat/apps/authentication/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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)
2 changes: 1 addition & 1 deletion cvat/apps/engine/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#path('create/task', views.create_task),
#path('get/task/<int:tid>/frame/<int:frame>', views.get_frame),
path('check/task/<int:tid>', views.check_task),
path('delete/task/<int:tid>', views.delete_task),
#path('delete/task/<int:tid>', views.delete_task),
path('update/task/<int:tid>', views.update_task),
path('get/job/<int:jid>', views.get_job),
path('get/task/<int:tid>', views.get_task),
Expand Down
57 changes: 49 additions & 8 deletions cvat/apps/engine/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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):
Expand All @@ -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 })
Expand Down

0 comments on commit 6b7f69d

Please sign in to comment.