Skip to content

Commit

Permalink
🔧 Abstract permissions, add ResearchTag and ResearchGroup viewsets
Browse files Browse the repository at this point in the history
  • Loading branch information
Steffo99 committed Aug 7, 2021
1 parent 584a248 commit 09d2452
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 29 deletions.
48 changes: 27 additions & 21 deletions backend/sophon/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,24 @@ class ResearchGroup(models.Model):
max_length=16,
)

def can_be_edited_by(self, user) -> bool:
if user.is_superuser:
return True

elif user in self.members:
return True

return False

def can_be_administrated_by(self, user) -> bool:
if user.is_superuser:
return True

elif user in self.owner:
return True

return False

def __str__(self):
return f"{self.slug}"

Expand Down Expand Up @@ -420,6 +438,15 @@ class ResearchTag(models.Model):
on_delete=models.CASCADE,
)

def can_be_administrated_by(self, user) -> bool:
if user.is_superuser:
return True

elif user == self.owner:
return True

return False

def __str__(self):
return f"[{self.name}]"

Expand Down Expand Up @@ -482,13 +509,6 @@ class ResearchProject(models.Model):
)

def can_be_viewed_by(self, user) -> bool:
"""
Check whether an user should be allowed to **view** the project contents.
:param user: The user to check permissions for.
:return: :data:`True` if the user can view the details, or :data:`False` if they cannot.
"""

if user.is_superuser:
return True

Expand All @@ -503,13 +523,6 @@ def can_be_viewed_by(self, user) -> bool:
raise ValueError(f"Unknown visibility value: {self.visibility}")

def can_be_edited_by(self, user) -> bool:
"""
Check whether an user should be allowed to **edit** the project details.
:param user: The user to check permissions for.
:return: :data:`True` if the user can edit the details, or :data:`False` if they cannot.
"""

if user.is_superuser:
return True

Expand All @@ -519,13 +532,6 @@ def can_be_edited_by(self, user) -> bool:
return False

def can_be_administrated_by(self, user) -> bool:
"""
Check whether an user should be allowed to **administrate** the project.
:param user: The user to check permissions for.
:return: :data:`True` if the user can administrate the project, or :data:`False` if they cannot.
"""

if user.is_superuser:
return True

Expand Down
47 changes: 47 additions & 0 deletions backend/sophon/core/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,53 @@ class Meta:
)


class ResearchTagPublicSerializer(serializers.ModelSerializer):
"""
Serializer for users who are not owners of a :class:`.models.ResearchTag`.
"""

# TODO: Add a list of projects with the tag

class Meta:
model = models.ResearchTag
fields = (
"slug",
"name",
"description",
"color",
"owner",
)
read_only_fields = (
"slug",
"name",
"description",
"color",
"owner",
)


class ResearchTagAdminSerializer(serializers.ModelSerializer):
"""
Serializer for users who are owners of a :class:`.models.ResearchTag`.
"""

# TODO: Add a list of projects with the tag

class Meta:
model = models.ResearchTag
fields = (
"slug",
"name",
"description",
"color",
"owner",
)
read_only_fields = (
"slug",
"owner",
)


class ResearchProjectViewerSerializer(serializers.ModelSerializer):
"""
Serializer for users who are not collaborators of a :class:`~.models.ResearchProject`, but have permissions to view it.
Expand Down
2 changes: 2 additions & 0 deletions backend/sophon/core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
router.register("datasources", views.DataSourceViewSet)
router.register("dataflows", views.DataFlowViewSet)
router.register("projects", views.ResearchProjectViewSet)
router.register("tags", views.ResearchTagViewSet)
router.register("groups", views.ResearchGroupViewSet)

urlpatterns = [
path("", include(router.urls)),
Expand Down
71 changes: 66 additions & 5 deletions backend/sophon/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

from rest_framework import viewsets, decorators, response, permissions, request as r

from . import models, serializers, permissions as custom_permissions
from . import models, serializers
from .. import permissions as custom_permissions

log = getLogger(__name__)

Expand All @@ -15,10 +16,10 @@ def permission_classes(self):
return {
"list": [],
"create": [permissions.IsAuthenticated],
"retrieve": [custom_permissions.CanViewProject],
"update": [custom_permissions.CanEditProject],
"partial_update": [custom_permissions.CanEditProject],
"destroy": [custom_permissions.CanAdministrateProject],
"retrieve": [custom_permissions.CanView],
"update": [custom_permissions.CanEdit],
"partial_update": [custom_permissions.CanEdit],
"destroy": [custom_permissions.CanAdministrate],
"metadata": [],
None: [],
}[self.action]
Expand All @@ -41,6 +42,66 @@ def get_serializer_class(self):
return serializers.ResearchProjectPublicSerializer


class ResearchGroupViewSet(viewsets.ModelViewSet):
queryset = models.ResearchGroup.objects.all()

@property
def permission_classes(self):
return {
"list": [],
"create": [permissions.IsAuthenticated],
"retrieve": [permissions.IsAuthenticated],
"update": [custom_permissions.CanAdministrate],
"partial_update": [custom_permissions.CanAdministrate],
"destroy": [custom_permissions.CanAdministrate],
"metadata": [],
None: [],
}[self.action]

def get_serializer_class(self):
if self.action == "list":
return serializers.ResearchGroupPublicSerializer
elif self.action == "create":
return serializers.ResearchGroupAdminSerializer
else:
group = self.get_object()
user = self.request.user
if group.can_be_administrated_by(user):
return serializers.ResearchGroupAdminSerializer
else:
return serializers.ResearchGroupPublicSerializer


class ResearchTagViewSet(viewsets.ModelViewSet):
queryset = models.ResearchTag.objects.all()

@property
def permission_classes(self):
return {
"list": [],
"create": [permissions.IsAuthenticated],
"retrieve": [permissions.IsAuthenticated],
"update": [custom_permissions.CanAdministrate],
"partial_update": [custom_permissions.CanAdministrate],
"destroy": [custom_permissions.CanAdministrate],
"metadata": [],
None: [],
}[self.action]

def get_serializer_class(self):
if self.action == "list":
return serializers.ResearchTagPublicSerializer
elif self.action == "create":
return serializers.ResearchTagAdminSerializer
else:
group = self.get_object()
user = self.request.user
if group.can_be_administrated_by(user):
return serializers.ResearchTagAdminSerializer
else:
return serializers.ResearchTagPublicSerializer


class DataFlowViewSet(viewsets.ModelViewSet):
"""
Viewset for :class:`.models.DataFlow` instances.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
log = logging.getLogger(__name__)


class CanAdministrateProject(permissions.BasePermission):
class CanAdministrate(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return obj.can_be_administrated_by(request.user)


class CanEditProject(permissions.BasePermission):
class CanEdit(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return obj.can_be_edited_by(request.user)


class CanViewProject(permissions.BasePermission):
class CanView(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return obj.can_be_viewed_by(request.user)

0 comments on commit 09d2452

Please sign in to comment.