Skip to content
This repository has been archived by the owner on Aug 11, 2021. It is now read-only.

Commit

Permalink
OpenConceptLab/ocl_issues#147: Users can view public collections that…
Browse files Browse the repository at this point in the history
… are marked private if the user query is specified
  • Loading branch information
karuhanga committed Aug 26, 2019
1 parent 675bf27 commit 0af4d15
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 75 deletions.
10 changes: 1 addition & 9 deletions ocl/collection/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,4 @@


class CollectionSearchFilter(HaystackSearchFilter):
def get_filters(self, request, view):
filters = super(CollectionSearchFilter, self).get_filters(request, view)
if view.parent_resource:
filters.update({'owner': view.parent_resource.mnemonic})
filters.update({'ownerType': view.parent_resource.resource_type()})
else:
filters.update({'public_can_view': True})

return filters
pass
58 changes: 15 additions & 43 deletions ocl/collection/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import logging
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.db import IntegrityError
from django.db.models import Q

from collection.validation_messages import HEAD_OF_CONCEPT_ADDED_TO_COLLECTION, CONCEPT_ADDED_TO_COLLECTION_FMT, \
HEAD_OF_MAPPING_ADDED_TO_COLLECTION, MAPPING_ADDED_TO_COLLECTION_FMT
Expand All @@ -9,32 +11,25 @@
CollectionVersionListSerializer, CollectionVersionCreateSerializer, CollectionVersionDetailSerializer, \
CollectionVersionUpdateSerializer, \
CollectionReferenceSerializer
from concepts.models import Concept, ConceptVersion
from mappings.models import MappingVersion
from sources.models import SourceVersion
from concepts.serializers import ConceptListSerializer
from concepts.models import Concept
from django.http import HttpResponse, HttpResponseForbidden
from mappings.models import Mapping
from mappings.serializers import MappingDetailSerializer
from oclapi.mixins import ListWithHeadersMixin
from oclapi.permissions import CanViewConceptDictionary, CanEditConceptDictionary, CanViewConceptDictionaryVersion, \
CanEditConceptDictionaryVersion, HasOwnership
from oclapi.permissions import HasAccessToVersionedObject
from oclapi.views import ResourceVersionMixin, ResourceAttributeChildMixin, ConceptDictionaryUpdateMixin, \
ConceptDictionaryCreateMixin, ConceptDictionaryExtrasView, ConceptDictionaryExtraRetrieveUpdateDestroyView, \
BaseAPIView
from oclapi.models import ACCESS_TYPE_EDIT, ACCESS_TYPE_VIEW
ConceptDictionaryCreateMixin, ConceptDictionaryExtrasView, ConceptDictionaryExtraRetrieveUpdateDestroyView
from oclapi.models import ACCESS_TYPE_NONE
from rest_framework import mixins, status
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, get_object_or_404, DestroyAPIView
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView
from rest_framework.response import Response
from users.models import UserProfile
from orgs.models import Organization
from tasks import export_collection, add_references
from celery_once import AlreadyQueued
from django.shortcuts import get_list_or_404
from collection.filters import CollectionSearchFilter
from tasks import update_collection_in_solr, delete_resources_from_collection_in_solr
from django.core.exceptions import ValidationError
from tasks import delete_resources_from_collection_in_solr

logger = logging.getLogger('oclapi')

Expand All @@ -53,22 +48,16 @@ def get_version_detail_serializer(self, obj, data=None, files=None, partial=Fals

def get_queryset(self):
owner = self.get_owner()
if not self.kwargs:
return self.queryset
if not owner:
return self.queryset.filter(~Q(public_access=ACCESS_TYPE_NONE))
elif 'collection' in self.kwargs:
return Collection.objects.filter(parent_id=owner.id, mnemonic=self.kwargs['collection'])
return self.model.objects.filter(parent_id=owner.id, mnemonic=self.kwargs['collection'])
else:
return self.queryset.filter(parent_id=owner.id)
owner_query = Q(parent_id=owner.id, parent_type=ContentType.objects.get_for_model(owner))
return self.queryset.filter(owner_query)

def get_owner(self):
owner = None
if 'user' in self.kwargs:
owner_id = self.kwargs['user']
owner = UserProfile.objects.get(mnemonic=owner_id)
elif 'org' in self.kwargs:
owner_id = self.kwargs['org']
owner = Organization.objects.get(mnemonic=owner_id)
return owner
return self.parent_resource


class CollectionVersionBaseView(ResourceVersionMixin):
Expand Down Expand Up @@ -290,31 +279,14 @@ def get(self, request, *args, **kwargs):
self.serializer_class = CollectionDetailSerializer if self.is_verbose(request) else CollectionListSerializer
self.contains_uri = request.QUERY_PARAMS.get('contains', None)
self.user = request.QUERY_PARAMS.get('user', None)
# Running the filter_backends seems to reset changes made to the queryset.
# Therefore, remove the filter_backends when the 'contains' parameter is passed, and
# apply the appropriate public_access filter in get_queryset
# TODO correct the behavior of filter_backends, and remove this hack to get around it
if self.contains_uri != None:
self.filter_backends=[]
if self.user != None:
self.filter_backends=[]
collection_list = self.list(request, *args, **kwargs)
return collection_list

def get_queryset(self):
queryset = super(CollectionListView, self).get_queryset()
# If the 'contains' parameter is used, the filter_backends have been cleared to prevent
# reset of the queryset. Therefore, add a public_access filter to the queryset.
# TODO correct the behavior of filter_backends, and remove this hack to get around it
if self.contains_uri != None:
if self.contains_uri is not None:
from django_mongodb_engine.query import A
queryset = queryset.filter(references=A('expression', self.contains_uri), public_access__in=[ACCESS_TYPE_EDIT, ACCESS_TYPE_VIEW])
if self.user:
if self.user != 'root':
from users.models import UserProfile
user_profile = UserProfile.objects.filter(mnemonic=self.user)
if user_profile:
queryset = queryset.filter(parent_id__in=[user_profile[0].id] + user_profile[0].organizations, public_access__in=[ACCESS_TYPE_EDIT, ACCESS_TYPE_VIEW])
queryset = queryset.filter(references=A('expression', self.contains_uri))
return queryset

def get_csv_rows(self, queryset=None):
Expand Down
3 changes: 1 addition & 2 deletions ocl/concepts/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from django.core.exceptions import ValidationError
from django.db.models import Q
from django.db.models.query import EmptyQuerySet
from django.http import Http404
from django.views.decorators.csrf import csrf_exempt
from rest_framework import mixins, status
from rest_framework.generics import (RetrieveAPIView, get_object_or_404, UpdateAPIView,
DestroyAPIView, RetrieveUpdateDestroyAPIView, CreateAPIView,
DestroyAPIView, RetrieveUpdateDestroyAPIView,
ListCreateAPIView, ListAPIView)
from rest_framework.response import Response
from concepts.filters import LimitSourceVersionFilter, PublicConceptsSearchFilter, LimitCollectionVersionFilter
Expand Down
6 changes: 3 additions & 3 deletions ocl/oclapi/filters.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.conf import settings
from haystack.inputs import Raw
from haystack.query import RelatedSearchQuerySet, SearchQuerySet
from haystack.query import RelatedSearchQuerySet
from rest_framework.filters import BaseFilterBackend


Expand Down Expand Up @@ -128,7 +128,7 @@ def _filter_queryset(self, request, queryset, view, sqs):
sqs = sqs.order_by(default_sort)
sqs = sqs.models(view.model)
if hasattr(sqs, 'load_all_queryset'):
sqs = sqs.load_all_queryset(view.model, queryset)
sqs = sqs.load_all().load_all_queryset(view.model, queryset)
return SearchQuerySetWrapper(sqs)

if hasattr(view, 'default_order_by'):
Expand All @@ -138,4 +138,4 @@ def _filter_queryset(self, request, queryset, view, sqs):

class HaystackSearchFilter(BaseHaystackSearchFilter):
def filter_queryset(self, request, queryset, view):
return self._filter_queryset(request, queryset, view, SearchQuerySet())
return self._filter_queryset(request, queryset, view, RelatedSearchQuerySet())
9 changes: 1 addition & 8 deletions ocl/sources/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,4 @@


class SourceSearchFilter(HaystackSearchFilter):
def get_filters(self, request, view):
filters = super(SourceSearchFilter, self).get_filters(request, view)
if view.parent_resource:
filters.update({'owner': view.parent_resource.mnemonic})
filters.update({'ownerType': view.parent_resource.resource_type()})
else:
filters.update({'public_can_view': True})
return filters
pass
26 changes: 16 additions & 10 deletions ocl/sources/views.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,26 @@
import logging

from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.db import IntegrityError
from django.db.models import Q
from django.db.models.query import EmptyQuerySet
from django.http import HttpResponse, HttpResponseForbidden
from rest_framework import mixins, status
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, get_object_or_404, DestroyAPIView
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView
from django.shortcuts import get_list_or_404
from rest_framework.response import Response
from concepts.models import ConceptVersion, Concept
from mappings.models import Mapping
from collection.models import CollectionVersion
from concepts.serializers import ConceptVersionDetailSerializer
from mappings.models import MappingVersion
from mappings.serializers import MappingVersionDetailSerializer
from oclapi.mixins import ListWithHeadersMixin
from oclapi.models import ACCESS_TYPE_NONE
from oclapi.permissions import HasAccessToVersionedObject, CanEditConceptDictionaryVersion, CanViewConceptDictionary, \
CanViewConceptDictionaryVersion, CanEditConceptDictionary, HasOwnership
from oclapi.views import ResourceVersionMixin, ResourceAttributeChildMixin, ConceptDictionaryUpdateMixin, ConceptDictionaryCreateMixin, ConceptDictionaryExtrasView, ConceptDictionaryExtraRetrieveUpdateDestroyView, parse_updated_since_param, parse_boolean_query_param
from sources.filters import SourceSearchFilter
from sources.models import Source, SourceVersion
from oclapi.rawqueries import RawQueries
from sources.serializers import SourceCreateSerializer, SourceListSerializer, SourceDetailSerializer, SourceVersionDetailSerializer, SourceVersionListSerializer, SourceVersionCreateSerializer, SourceVersionUpdateSerializer
from tasks import export_source
from celery_once import AlreadyQueued
from users.models import UserProfile
from orgs.models import Organization
from django.db.models import Q

INCLUDE_CONCEPTS_PARAM = 'includeConcepts'
INCLUDE_MAPPINGS_PARAM = 'includeMappings'
Expand All @@ -49,6 +42,19 @@ class SourceBaseView():
def get_detail_serializer(self, obj, data=None, files=None, partial=False):
return SourceDetailSerializer(obj, data, files, partial)

def get_queryset(self):
owner = self.get_owner()
if not owner:
return self.queryset.filter(~Q(public_access=ACCESS_TYPE_NONE))
elif 'source' in self.kwargs:
return self.model.objects.filter(parent_id=owner.id, mnemonic=self.kwargs['source'])
else:
owner_query = Q(parent_id=owner.id, parent_type=ContentType.objects.get_for_model(owner))
return self.queryset.filter(owner_query)

def get_owner(self):
return self.parent_resource


class SourceRetrieveUpdateDestroyView(SourceBaseView,
ConceptDictionaryUpdateMixin,
Expand Down

0 comments on commit 0af4d15

Please sign in to comment.