From f10d42b22fed5eca222bfeb872da7765f4cf6980 Mon Sep 17 00:00:00 2001 From: Erwan Rouchet <rouchet@teklia.com> Date: Wed, 12 Sep 2018 15:59:55 +0200 Subject: [PATCH] Add and use mixin methods for right checking --- arkindex/dataimport/api.py | 45 ++++++++++++++------------------------ arkindex/project/mixins.py | 14 ++++++++++++ 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/arkindex/dataimport/api.py b/arkindex/dataimport/api.py index bf764b476f..587a12fbda 100644 --- a/arkindex/dataimport/api.py +++ b/arkindex/dataimport/api.py @@ -1,4 +1,5 @@ from django.db.models import Sum +from django.http.response import Http404 from django.shortcuts import get_object_or_404 from django.core.exceptions import PermissionDenied from django.conf import settings @@ -41,14 +42,13 @@ class DataImportsList(CorpusACLMixin, ListCreateAPIView): if serializer.validated_data['mode'] not in (DataImportMode.Images, ): raise ValidationError('Unsupported mode for now, sorry.') - if not self.request.user.is_admin and \ - Right.Write not in serializer.validated_data['corpus'].get_acl_rights(self.request.user): + if not self.has_write_access(serializer.validated_data['corpus']): raise PermissionDenied return super().perform_create(serializer) -class DataImportDetails(RetrieveUpdateDestroyAPIView): +class DataImportDetails(CorpusACLMixin, RetrieveUpdateDestroyAPIView): """ Retrieve and edit a data import """ @@ -61,8 +61,7 @@ class DataImportDetails(RetrieveUpdateDestroyAPIView): def perform_update(self, serializer): dataimport = serializer.instance - if not self.request.user.is_admin and \ - Right.Write not in dataimport.corpus.get_acl_rights(self.request.user): + if not self.has_write_access(dataimport.corpus): raise PermissionDenied if dataimport.state not in (DataImportState.Created, DataImportState.Configured): @@ -86,8 +85,7 @@ class DataImportDetails(RetrieveUpdateDestroyAPIView): dataimport.save() def perform_destroy(self, instance): - if not self.request.user.is_admin and \ - Right.Write not in instance.corpus.get_acl_rights(self.request.user): + if not self.has_write_access(instance.corpus): raise PermissionDenied if instance.state == DataImportState.Running: raise ValidationError("Cannot delete a workflow while it is running") @@ -109,7 +107,7 @@ class DataImportFailures(ListAPIView): ).prefetch_related('dataimport__revision__repo', 'element').order_by('path', 'line') -class DataImportDemo(CreateAPIView): +class DataImportDemo(CorpusACLMixin, CreateAPIView): """ Create, configure and start an Images workflow from a single DataFile """ @@ -136,7 +134,7 @@ class DataImportDemo(CreateAPIView): volume = get_object_or_404(Element, **filters) - assert self.request.user.is_admin or Right.Write in volume.corpus.get_acl_rights(self.request.user), \ + assert self.has_write_access(volume.corpus), \ 'Corpus is not writable' # Start the import @@ -167,7 +165,7 @@ class DataFileList(CorpusACLMixin, ListAPIView): return DataFile.objects.filter(corpus=self.get_corpus(self.kwargs['pk'])) -class DataFileRetrieve(RetrieveUpdateDestroyAPIView): +class DataFileRetrieve(CorpusACLMixin, RetrieveUpdateDestroyAPIView): """ Get one file """ @@ -178,19 +176,17 @@ class DataFileRetrieve(RetrieveUpdateDestroyAPIView): return DataFile.objects.filter(corpus__in=Corpus.objects.readable(self.request.user)) def perform_update(self, serializer): - if not self.request.user.is_admin and \ - Right.Write not in serializer.instance.corpus.get_acl_rights(self.request.user): + if not self.has_write_access(serializer.instance.corpus): raise PermissionDenied return super().perform_update(serializer) def perform_destroy(self, instance): - if not self.request.user.is_admin and \ - Right.Write not in instance.corpus.get_acl_rights(self.request.user): + if not self.has_write_access(instance.corpus): raise PermissionDenied return super().perform_destroy(instance) -class DataFileUpload(APIView): +class DataFileUpload(CorpusACLMixin, APIView): """ Upload a new file to a corpus """ @@ -200,15 +196,10 @@ class DataFileUpload(APIView): def post(self, request, pk=None, format=None): if 'file' not in request.FILES: raise ValidationError({'file': ['No file was sent in the request']}) - corpus_qs = Corpus.objects.filter(id=pk) - if not corpus_qs.exists(): + try: + corpus = self.get_corpus(pk, right=Right.Write) + except Http404: raise ValidationError({'corpus': ['Corpus not found']}) - corpus = corpus_qs.get() - - # Check corpus is writable for current user - if not self.request.user.is_admin and \ - Right.Write not in corpus.get_acl_rights(self.request.user): - raise PermissionDenied file_obj = request.FILES['file'] @@ -293,7 +284,7 @@ class AvailableRepositoriesList(ListCreateAPIView): return Response(data={'import_id': str(dataimport.id)}, status=status.HTTP_201_CREATED) -class RepositoryRetrieve(RetrieveUpdateDestroyAPIView): +class RepositoryRetrieve(CorpusACLMixin, RetrieveUpdateDestroyAPIView): permission_classes = (IsAuthenticated, ) serializer_class = RepositorySerializer @@ -304,14 +295,12 @@ class RepositoryRetrieve(RetrieveUpdateDestroyAPIView): ) def perform_update(self, serializer): - if not self.request.user.is_admin and \ - Right.Write not in serializer.instance.corpus.get_acl_rights(self.request.user): + if not self.has_write_access(serializer.instance.corpus): raise PermissionDenied return super().perform_update(self, serializer) def perform_destroy(self, instance): - if not self.request.user.is_admin and \ - Right.Write not in instance.corpus.get_acl_rights(self.request.user): + if not self.has_write_access(instance.corpus): raise PermissionDenied return super().perform_destroy(self, instance) diff --git a/arkindex/project/mixins.py b/arkindex/project/mixins.py index 36c8236310..6b0232a0a4 100644 --- a/arkindex/project/mixins.py +++ b/arkindex/project/mixins.py @@ -10,3 +10,17 @@ class CorpusACLMixin(object): if right not in corpus.get_acl_rights(self.request.user): raise PermissionDenied() return corpus + + def has_read_access(self, corpus): + assert isinstance(corpus, Corpus) + return corpus.public or self.request.user.is_admin or Right.Read in corpus.get_acl_rights(self.request.user) + + def has_write_access(self, corpus): + assert isinstance(corpus, Corpus) + return self.request.user.is_admin or self.request.user.is_anonymous and \ + Right.Write in corpus.get_acl_rights(self.request.user) + + def has_admin_access(self, corpus): + assert isinstance(corpus, Corpus) + return self.request.user.is_admin or self.request.user.is_anonymous and \ + Right.Admin in corpus.get_acl_rights(self.request.user) -- GitLab