mirror of
https://github.com/Steffo99/sophon.git
synced 2024-12-22 23:04:21 +00:00
✨ Properly check permissions for Projects
This commit is contained in:
parent
a7ae9f28f5
commit
95f4981dec
3 changed files with 45 additions and 23 deletions
|
@ -9,19 +9,6 @@ import json
|
|||
import abc
|
||||
|
||||
|
||||
class RelatedToProject(metaclass=abc.ABCMeta):
|
||||
"""
|
||||
A model which is related to :class:`.Project` in some way.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_project(self) -> "Project":
|
||||
"""
|
||||
:return: The project this object is related to.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class DataSource(models.Model):
|
||||
"""
|
||||
A :class:`.DataSource` is a web service which provides access to statistical information sourced by multiple data
|
||||
|
@ -312,15 +299,12 @@ class DataFlow(models.Model):
|
|||
return f"[{self.datasource}] {self.id}"
|
||||
|
||||
|
||||
class Project(models.Model, RelatedToProject):
|
||||
class Project(models.Model):
|
||||
"""
|
||||
A research :class:`.Project` is a work which may use zero or more :class:`.DataSource`\\ s to prove or disprove an
|
||||
hypothesis.
|
||||
"""
|
||||
|
||||
def get_project(self):
|
||||
return self
|
||||
|
||||
slug = models.SlugField(
|
||||
"Slug",
|
||||
help_text="Unique alphanumeric string which identifies the project.",
|
||||
|
@ -349,6 +333,7 @@ class Project(models.Model, RelatedToProject):
|
|||
("PRIVATE", "🔒 Private"),
|
||||
],
|
||||
default="INTERNAL",
|
||||
max_length=16,
|
||||
)
|
||||
|
||||
owner = models.ForeignKey(
|
||||
|
@ -371,5 +356,24 @@ class Project(models.Model, RelatedToProject):
|
|||
blank=True,
|
||||
)
|
||||
|
||||
def get_contributors(self):
|
||||
return {self.owner, *self.collaborators.values()}
|
||||
|
||||
def can_be_viewed_by(self, user):
|
||||
if self.visibility == "PUBLIC":
|
||||
return True
|
||||
elif self.visibility == "INTERNAL":
|
||||
return not user.is_anonymous()
|
||||
elif self.visibility == "PRIVATE":
|
||||
return user in self.get_contributors()
|
||||
else:
|
||||
raise ValueError(f"Unknown visibility value: {self.visibility}")
|
||||
|
||||
def can_be_edited_by(self, user):
|
||||
return user in self.get_contributors()
|
||||
|
||||
def can_be_administrated_by(self, user):
|
||||
return user == self.owner
|
||||
|
||||
def __str__(self):
|
||||
return self.slug
|
||||
|
|
18
sophon/core/permissions.py
Normal file
18
sophon/core/permissions.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
import logging
|
||||
from rest_framework import permissions
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ProjectPermissions(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj):
|
||||
if view.action == "retrieve":
|
||||
return obj.can_be_viewed_by(request.user)
|
||||
elif view.action == "update":
|
||||
return obj.can_be_edited_by(request.user)
|
||||
elif view.action == "partial_update":
|
||||
return obj.can_be_edited_by(request.user)
|
||||
elif view.action == "destroy":
|
||||
return obj.can_be_administrated_by(request.user)
|
||||
log.warning(f"Rejecting permissions for unknown action: {view.action}")
|
||||
return False
|
|
@ -1,5 +1,5 @@
|
|||
from rest_framework import viewsets, decorators, response
|
||||
from . import models, serializers
|
||||
from rest_framework import viewsets, decorators, response, permissions
|
||||
from . import models, serializers, permissions as custom_permissions
|
||||
from datetime import datetime
|
||||
from logging import getLogger
|
||||
|
||||
|
@ -12,7 +12,7 @@ class ProjectViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = models.Project.objects.all()
|
||||
serializer_class = serializers.ProjectSerializer
|
||||
permission_classes = []
|
||||
permission_classes = [custom_permissions.ProjectPermissions]
|
||||
|
||||
|
||||
class DataFlowViewSet(viewsets.ModelViewSet):
|
||||
|
@ -21,7 +21,7 @@ class DataFlowViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = models.DataFlow.objects.all()
|
||||
serializer_class = serializers.DataFlowSerializer
|
||||
permission_classes = []
|
||||
permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
|
||||
|
||||
|
||||
class DataSourceViewSet(viewsets.ModelViewSet):
|
||||
|
@ -30,10 +30,10 @@ class DataSourceViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = models.DataSource.objects.all()
|
||||
serializer_class = serializers.DataSourceSerializer
|
||||
permission_classes = []
|
||||
permission_classes = [permissions.DjangoModelPermissionsOrAnonReadOnly]
|
||||
|
||||
@decorators.action(methods=["post"], detail=True)
|
||||
def sync(self, request, pk):
|
||||
def sync(self, request, *args, **kwargs):
|
||||
"""
|
||||
Syncronize the :class:`.models.DataFlow`\\ s with the ones stored in the server of the
|
||||
:class:`.models.DataSource`\\ .
|
||||
|
|
Loading…
Reference in a new issue