diff --git a/ifbcatsandbox_api/permissions.py b/ifbcatsandbox_api/permissions.py index 0c5194bc..a6ebb848 100644 --- a/ifbcatsandbox_api/permissions.py +++ b/ifbcatsandbox_api/permissions.py @@ -1,4 +1,5 @@ # Imports +from django.db.models import ManyToManyField from rest_framework import permissions # Custom permission class for updating user profiles @@ -25,9 +26,15 @@ def has_object_permission(self, request, view, obj): # Custom permissions class for updating object -class PubliclyReadableEditableByOwner(permissions.BasePermission): - owner_field = 'user_profile' - """Allow everyone to see, but only owner to update/delete.""" +class PubliclyReadableEditableBySomething(permissions.BasePermission): + class Meta: + abstract = True + + """Allow everyone to see, but only target to update/delete.""" + target = None + + def __init__(self, *args, **kwargs): + assert self.target is not None, "target cannot be None" def has_object_permission(self, request, view, obj): """Check the user is trying to update their own object.""" @@ -38,12 +45,10 @@ def has_object_permission(self, request, view, obj): # Check that the user owns the object, i.e. the user_profile associated # with the object is assigned to the user making the request. # (returns True if the object being updated etc. has a user profile id that matches the request) - return getattr(obj, self.owner_field).id == request.user.id - - -# Custom permissions class for updating object -class PubliclyReadableEditableByCoordinator(permissions.BasePermission): - owner_field = 'coordinator' + target_attr = getattr(obj, self.target) + if isinstance(obj._meta.get_field(self.target), ManyToManyField): + return target_attr.filter(id=request.user.id).exists() + return target_attr.id == request.user.id # Custom permissions class for updating object @@ -57,3 +62,23 @@ def has_object_permission(self, request, view, obj): return True return False + + +class PubliclyReadableEditableByOwner(PubliclyReadableEditableBySomething): + target = 'user_profile' + + +class PubliclyReadableEditableByCoordinator(PubliclyReadableEditableBySomething): + target = 'coordinator' + + +class PubliclyReadableEditableByTrainer(PubliclyReadableEditableBySomething): + target = 'trainers' + + +class PubliclyReadableEditableByMember(PubliclyReadableEditableBySomething): + target = 'members' + + +class PubliclyReadableEditableByContact(PubliclyReadableEditableBySomething): + target = 'contactId' diff --git a/ifbcatsandbox_api/views.py b/ifbcatsandbox_api/views.py index 21faa479..491916e5 100644 --- a/ifbcatsandbox_api/views.py +++ b/ifbcatsandbox_api/views.py @@ -193,7 +193,11 @@ class EventViewSet(viewsets.ModelViewSet): serializer_class = serializers.EventSerializer queryset = models.Event.objects.all() - permission_classes = (permissions.PubliclyReadableEditableByOwner, IsAuthenticatedOrReadOnly) + permission_classes = ( + permissions.PubliclyReadableEditableByOwner, + permissions.PubliclyReadableEditableByContact, + IsAuthenticatedOrReadOnly, + ) def perform_create(self, serializer): """Sets the user profile to the logged-in user.""" @@ -229,6 +233,13 @@ class TrainingEventViewSet(EventViewSet): serializer_class = serializers.TrainingEventSerializer queryset = models.TrainingEvent.objects.all() + permission_classes = ( + permissions.PubliclyReadableEditableByTrainer, + permissions.PubliclyReadableEditableByContact, + permissions.PubliclyReadableEditableByOwner, + IsAuthenticatedOrReadOnly, + ) + search_fields = EventViewSet.search_fields + ( 'audienceTypes__audienceType', 'audienceRoles__audienceRole', @@ -415,7 +426,11 @@ class ProjectViewSet(viewsets.ModelViewSet): queryset = models.Project.objects.all() lookup_field = 'name' - permission_classes = (permissions.PubliclyReadableEditableByOwner, IsAuthenticatedOrReadOnly) + permission_classes = ( + permissions.PubliclyReadableEditableByOwner, + permissions.PubliclyReadableEditableByMember, + IsAuthenticatedOrReadOnly, + ) def perform_create(self, serializer): """Sets the user profile to the logged-in user.""" @@ -458,6 +473,11 @@ class ComputingFacilityViewSet(ResourceViewSet): serializer_class = serializers.ComputingFacilitySerializer queryset = models.ComputingFacility.objects.all() + permission_classes = ( + permissions.PubliclyReadableEditableByOwner, + permissions.PubliclyReadableEditableByMember, + IsAuthenticatedOrReadOnly, + ) search_fields = ResourceViewSet.search_fields + ( 'homepage', @@ -496,7 +516,11 @@ class TeamViewSet(viewsets.ModelViewSet): queryset = models.Team.objects.all() lookup_field = 'name' - permission_classes = (permissions.PubliclyReadableEditableByOwner, IsAuthenticatedOrReadOnly) + permission_classes = ( + permissions.PubliclyReadableEditableByOwner, + permissions.PubliclyReadableEditableByMember, + IsAuthenticatedOrReadOnly, + ) def perform_create(self, serializer): """Sets the user profile to the logged-in user.""" @@ -547,7 +571,11 @@ class ServiceViewSet(viewsets.ModelViewSet): queryset = models.Service.objects.all() lookup_field = 'name' - permission_classes = (permissions.PubliclyReadableEditableByOwner, IsAuthenticatedOrReadOnly) + permission_classes = ( + permissions.PubliclyReadableEditableByOwner, + permissions.PubliclyReadableEditableByMember, + IsAuthenticatedOrReadOnly, + ) # TODO: : add to "search_fields" below: 'team', 'providedBy' search_fields = (