From e159bf971bc0aea1aea38635a907cdf80ed9293f Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Wed, 27 May 2020 16:40:08 +0300 Subject: [PATCH] Collection/item viewsets: enforce access. --- django_etesync/permissions.py | 46 +++++++++++++++++++++++++++++++++++ django_etesync/views.py | 4 +-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/django_etesync/permissions.py b/django_etesync/permissions.py index c371743..611977b 100644 --- a/django_etesync/permissions.py +++ b/django_etesync/permissions.py @@ -36,3 +36,49 @@ class IsCollectionAdmin(permissions.BasePermission): except Collection.DoesNotExist: # If the collection does not exist, we want to 404 later, not permission denied. return True + + +class IsCollectionAdminOrReadOnly(permissions.BasePermission): + """ + Custom permission to only allow owners of a collection to edit it + """ + message = 'Only collection admins can edit collections.' + code = 'admin_access_required' + + def has_permission(self, request, view): + collection_uid = view.kwargs.get('collection_uid', None) + + # Allow creating new collections + if collection_uid is None: + return True + + try: + collection = view.get_collection_queryset().get(uid=collection_uid) + if request.method in permissions.SAFE_METHODS: + return True + + return is_collection_admin(collection, request.user) + except Collection.DoesNotExist: + # If the collection does not exist, we want to 404 later, not permission denied. + return True + + +class HasWriteAccessOrReadOnly(permissions.BasePermission): + """ + Custom permission to restrict write + """ + message = 'You need write access to write to this collection' + code = 'no_write_access' + + def has_permission(self, request, view): + collection_uid = view.kwargs['collection_uid'] + try: + collection = view.get_collection_queryset().get(uid=collection_uid) + if request.method in permissions.SAFE_METHODS: + return True + else: + member = collection.members.get(user=request.user) + return member.accessLevel != AccessLevels.READ_ONLY + except Collection.DoesNotExist: + # If the collection does not exist, we want to 404 later, not permission denied. + return True diff --git a/django_etesync/views.py b/django_etesync/views.py index fd91aed..148081a 100644 --- a/django_etesync/views.py +++ b/django_etesync/views.py @@ -127,7 +127,7 @@ class BaseViewSet(viewsets.ModelViewSet): class CollectionViewSet(BaseViewSet): allowed_methods = ['GET', 'POST', 'DELETE'] - permission_classes = BaseViewSet.permission_classes + permission_classes = BaseViewSet.permission_classes + (permissions.IsCollectionAdminOrReadOnly, ) queryset = Collection.objects.all() serializer_class = CollectionSerializer lookup_field = 'uid' @@ -196,7 +196,7 @@ class CollectionViewSet(BaseViewSet): class CollectionItemViewSet(BaseViewSet): allowed_methods = ['GET', 'POST', 'PUT'] - permission_classes = BaseViewSet.permission_classes + permission_classes = BaseViewSet.permission_classes + (permissions.HasWriteAccessOrReadOnly, ) queryset = CollectionItem.objects.all() serializer_class = CollectionItemSerializer lookup_field = 'uid'