You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
3.3 KiB

4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
3 years ago
  1. from django.conf import settings
  2. from django.contrib.auth.mixins import UserPassesTestMixin
  3. from django.db.models import Subquery
  4. from django.shortcuts import get_object_or_404
  5. from rest_framework.permissions import (SAFE_METHODS, BasePermission,
  6. IsAdminUser)
  7. from .models import Project, Role, RoleMapping
  8. class ProjectMixin:
  9. @classmethod
  10. def get_project_id(self, request, view):
  11. return view.kwargs.get('project_id') or request.query_params.get('project_id')
  12. class IsAdminUserAndWriteOnly(BasePermission):
  13. def has_permission(self, request, view):
  14. if request.method in SAFE_METHODS:
  15. return True
  16. return IsAdminUser().has_permission(request, view)
  17. class ProjectAdminMixin(UserPassesTestMixin):
  18. def test_func(self):
  19. return self.request.user.is_superuser or is_in_role(
  20. role_name=IsProjectAdmin.role_name,
  21. user_id=self.request.user.id,
  22. project_id=self.kwargs['project_id'],
  23. )
  24. class IsOwnAnnotation(ProjectMixin, BasePermission):
  25. def has_permission(self, request, view):
  26. if request.user.is_superuser:
  27. return True
  28. project_id = self.get_project_id(request, view)
  29. annotation_id = view.kwargs.get('annotation_id')
  30. project = get_object_or_404(Project, pk=project_id)
  31. model = project.get_annotation_class()
  32. annotation = model.objects.filter(id=annotation_id, user=request.user)
  33. return annotation.exists()
  34. class IsOwnComment(ProjectMixin, BasePermission):
  35. @classmethod
  36. def has_object_permission(cls, request, view, obj):
  37. if request.user.is_superuser:
  38. return True
  39. return obj.user.id == request.user.id
  40. class RolePermission(ProjectMixin, BasePermission):
  41. UNSAFE_METHODS = ('POST', 'PATCH', 'DELETE')
  42. unsafe_methods_check = True
  43. role_name = ''
  44. def has_permission(self, request, view):
  45. if request.user.is_superuser:
  46. return True
  47. if self.unsafe_methods_check and request.method in self.UNSAFE_METHODS:
  48. return request.user.is_superuser
  49. project_id = self.get_project_id(request, view)
  50. if not project_id and request.method in SAFE_METHODS:
  51. return True
  52. return is_in_role(self.role_name, request.user.id, project_id)
  53. class IsProjectAdmin(RolePermission):
  54. unsafe_methods_check = False
  55. role_name = settings.ROLE_PROJECT_ADMIN
  56. class IsAnnotatorAndReadOnly(RolePermission):
  57. role_name = settings.ROLE_ANNOTATOR
  58. class IsAnnotator(RolePermission):
  59. unsafe_methods_check = False
  60. role_name = settings.ROLE_ANNOTATOR
  61. class IsAnnotationApproverAndReadOnly(RolePermission):
  62. role_name = settings.ROLE_ANNOTATION_APPROVER
  63. class IsAnnotationApprover(RolePermission):
  64. unsafe_methods_check = False
  65. role_name = settings.ROLE_ANNOTATION_APPROVER
  66. def is_in_role(role_name, user_id, project_id):
  67. return RoleMapping.objects.filter(
  68. user_id=user_id,
  69. project_id=project_id,
  70. role_id=Subquery(Role.objects.filter(name=role_name).values('id')),
  71. ).exists()
  72. IsInProjectReadOnlyOrAdmin = (IsAnnotatorAndReadOnly | IsAnnotationApproverAndReadOnly | IsProjectAdmin)
  73. IsInProjectOrAdmin = (IsAnnotator | IsAnnotationApprover | IsProjectAdmin)