Ejemplo n.º 1
0
    def get(self, request, *args, **kwargs):
        self.show_recent = kwargs.pop('show_recent', False)

        content = kwargs.pop('content', None)
        if not content:
            return HttpResponseBadRequest('No content type supplied')
        self.model = SEARCH_MODEL_NAMES_REVERSE.get(content, None)
        if not self.model:
            return HttpResponseBadRequest(
                'Unknown content type supplied: "%s"' % content)

        self.page_size = int(
            request.GET.get('page_size', self.default_page_size))
        if not is_number(self.page_size):
            return HttpResponseBadRequest(
                'Malformed parameter: "page_size": %s' % self.page_size)
        self.page_size = max(self.min_page_size,
                             min(self.max_page_size, self.page_size))

        self.offset_timestamp = request.GET.get('offset_timestamp',
                                                self.default_offset_timestamp)
        if self.offset_timestamp is not None and not is_number(
                self.offset_timestamp):
            return HttpResponseBadRequest(
                'Malformed parameter: "offset_timestamp"')
        if self.offset_timestamp is not None and isinstance(
                self.offset_timestamp, six.string_types):
            self.offset_timestamp = float(self.offset_timestamp)

        return super(TypedContentWidgetView, self).get(request, *args,
                                                       **kwargs)
Ejemplo n.º 2
0
    def get(self, request, *args, **kwargs):
        """ Accepted GET-params: 
            `page_size` int (optional): Number of items to be returned. If a value larger than
                `self.max_page_size` is supplied, `self.max_page_size`is used instead.
                Default: `self.default_page_size`
            `offset_timestamp` float (optional): If supplied, only items older than the given 
                timestamp are returned. Items with the exact timestamp are excluded.
                Use this parameter in conjunction with the return value `last_timestamp` for 
                pagination.
            `only_mine` bool (optional): if True, will only show objects that belong to groups 
                or projects the `user` is a member of.  If False, will include all visible items 
                in this portal for the user.
        """
        # require authenticated user
        self.user = request.user
        if not request.user.is_authenticated:
            return HttpResponseForbidden('Not authenticated.')
        content = kwargs.pop('content', None)
        if content:
            self.filter_model = SEARCH_MODEL_NAMES_REVERSE.get(content, None)
            if not self.filter_model:
                return HttpResponseBadRequest(
                    'Unknown content type supplied: "%s"' % content)

        self.page_size = int(
            request.GET.get('page_size', self.default_page_size))
        if not is_number(self.page_size):
            return HttpResponseBadRequest(
                'Malformed parameter: "page_size": %s' % self.page_size)
        self.page_size = max(self.min_page_size,
                             min(self.max_page_size, self.page_size))

        self.offset_timestamp = request.GET.get('offset_timestamp',
                                                self.default_offset_timestamp)
        if self.offset_timestamp is not None and not is_number(
                self.offset_timestamp):
            return HttpResponseBadRequest(
                'Malformed parameter: "offset_timestamp"')
        if self.offset_timestamp is not None and isinstance(
                self.offset_timestamp, six.string_types):
            self.offset_timestamp = float(self.offset_timestamp)

        self.only_mine = request.GET.get('only_mine', self.only_mine_default)
        if isinstance(self.only_mine, six.string_types):
            self.only_mine = bool(json.loads(self.only_mine))

        items = self.get_items()
        response = self.render_to_response(items)
        return response
Ejemplo n.º 3
0
    def get(self, request, *args, **kwargs):
        self.show_recent = kwargs.pop('show_recent', False)
        if self.show_recent:
            self.offset_model_field = 'visited'
        else:
            self.offset_model_field = 'created'

        content = kwargs.pop('content', None)
        if not content:
            return HttpResponseBadRequest('No content type supplied')
        self.model = SEARCH_MODEL_NAMES_REVERSE.get(content, None)
        if not self.model:
            return HttpResponseBadRequest(
                'Unknown content type supplied: "%s"' % content)

        return super(TypedContentWidgetView, self).get(request, *args,
                                                       **kwargs)
Ejemplo n.º 4
0
    def get_items(self):
        """ Returns a paginated list of items as mixture of different models, in sorted order """
        single_querysets = []
        for content_type in self.content_types:
            content_model = SEARCH_MODEL_NAMES_REVERSE.get(content_type, None)
            if content_model is None:
                if settings.DEBUG:
                    raise ImproperlyConfigured(
                        'Could not find content model for timeline content type "%s"'
                        % content_type)
                continue
            single_querysets.append(
                self._get_queryset_for_model(
                    content_model,
                    self.content_type_filter_fields[content_type]))

        items = self._mix_items_from_querysets(*single_querysets)
        return items
Ejemplo n.º 5
0
def get_searchresult_by_args(portal, model_type, slug, user=None):
    """ Retrieves a HaystackMapResult just as the API would, for a given shortid
        in the form of `<classid>.<instanceid>` (see `itemid_from_searchresult()`). """

    # monkey-hack: if the portal id is 0, we have an external item, so look up the external models
    if settings.COSINNUS_EXTERNAL_CONTENT_ENABLED and portal == EXTERNAL_CONTENT_PORTAL_ID:
        from cosinnus.models.map import EXTERNAL_SEARCH_MODEL_NAMES_REVERSE
        model = EXTERNAL_SEARCH_MODEL_NAMES_REVERSE.get(model_type, None)
    else:
        model = SEARCH_MODEL_NAMES_REVERSE.get(model_type, None)

    if model_type == 'people':
        sqs = SearchQuerySet().models(model).filter_and(slug=slug)
    elif model_type == 'events':
        group_slug, slug = slug.split('*', 1)
        sqs = SearchQuerySet().models(model).filter_and(portal=portal,
                                                        group_slug=group_slug,
                                                        slug=slug)
    else:
        sqs = SearchQuerySet().models(model).filter_and(portal=portal,
                                                        slug=slug)
    if user:
        # filter for read access by this user
        sqs = filter_searchqueryset_for_read_access(sqs, user)

    # hack: haystack seems to be unable to filter *exact* on `slug` (even when using __exact).
    # this affects slugs like `my-slug` vs `my-slug-2`.
    # so we manually post-filter on slug to get an exact match
    if len(sqs) > 1:
        sqs = [result for result in sqs if result.slug == slug]

    if len(sqs) != 1:
        logger.warn(
            'Got a DetailMap request where %d indexed results were found!' %
            len(sqs),
            extra={
                'portal': portal,
                'model': model,
                'slug': slug,
            })
        return None
    return sqs[0]
Ejemplo n.º 6
0
    def get_items(self):
        """ Returns a paginated list of items as mixture of different models, in sorted order """
        if self.filter_model:
            single_querysets = [
                self._get_queryset_for_model(self.filter_model)
            ]
        else:
            single_querysets = []
            for content_type in self.content_types:
                content_model = SEARCH_MODEL_NAMES_REVERSE.get(
                    content_type, None)
                if content_model is None:
                    if settings.DEBUG:
                        logger.warn(
                            'Could not find content model for timeline content type "%s"'
                            % content_type)
                    continue
                single_querysets.append(
                    self._get_queryset_for_model(content_model))

        items = self._mix_items_from_querysets(*single_querysets)
        return items
Ejemplo n.º 7
0
def map_detail_endpoint(request):
    """ Maps API object detail endpoint using pSQL results. For parameters see ``MAP_DETAIL_PARAMETERS``
        returns JSON with the contents of type ``DetailedMapResult``
    """
    params = _collect_parameters(request.GET, MAP_DETAIL_PARAMETERS)
    portal = params['portal']
    slug = params['slug']
    model_type = params['type']

    if not is_number(portal) or portal < 0:
        return HttpResponseBadRequest(
            '``portal`` param must be a positive number!')
    if not slug:
        return HttpResponseBadRequest('``slug`` param must be supplied!')
    slug = force_text(slug)  # stringify is necessary for number-only slugs
    if not model_type or not isinstance(model_type, six.string_types):
        return HttpResponseBadRequest(
            '``type`` param must be supplied and be a string!')

    if portal == 0:
        portal = CosinnusPortal.get_current().id

    # try to retrieve the requested object
    model = SEARCH_MODEL_NAMES_REVERSE.get(model_type, None)
    if model is None:
        return HttpResponseBadRequest(
            '``type`` param indicated an invalid data model type!')

    # TODO: for groups/projects we should really use the cache here.
    if model_type == 'people':
        # UserProfiles are retrieved independent of the portal
        obj = get_object_or_None(get_user_profile_model(), user__username=slug)
    elif model_type == 'events':
        group_slug, event_slug = slug.split('*', 1)
        obj = get_object_or_None(model,
                                 group__portal__id=portal,
                                 group__slug=group_slug,
                                 slug=event_slug)
    else:
        obj = get_object_or_None(model, portal__id=portal, slug=slug)
    if obj is None:
        return HttpResponseNotFound(
            'No item found that matches the requested type and slug (obj: %s, %s, %s).'
            % (escape(force_text(model)), portal, slug))

    # check read permission
    if not model_type in SEARCH_MODEL_TYPES_ALWAYS_READ_PERMISSIONS and not check_object_read_access(
            obj, request.user):
        return HttpResponseForbidden(
            'You do not have permission to access this item.')

    # get the basic result data from the search index (as it is already prepared and faster to access there)
    haystack_result = get_searchresult_by_args(portal, model_type, slug)
    if not haystack_result:
        return HttpResponseNotFound(
            'No item found that matches the requested type and slug (index: %s, %s, %s).'
            % (portal, model_type, slug))

    # format data
    result_model = SEARCH_RESULT_DETAIL_TYPE_MAP[model_type]
    result = result_model(haystack_result, obj, request.user)

    data = {
        'result': result,
    }
    return JsonResponse(data)