def paginate(self, request, on_results=None, paginator_cls=Paginator, default_per_page=100, **kwargs): per_page = int(request.GET.get("per_page", default_per_page)) input_cursor = request.GET.get("cursor") if input_cursor: input_cursor = Cursor.from_string(input_cursor) else: input_cursor = None assert per_page <= max(100, default_per_page) paginator = paginator_cls(**kwargs) cursor_result = paginator.get_result(limit=per_page, cursor=input_cursor) # map results based on callback if on_results: results = on_results(cursor_result.results) headers = {} headers["Link"] = ", ".join( [ self.build_cursor_link(request, "previous", cursor_result.prev), self.build_cursor_link(request, "next", cursor_result.next), ] ) return Response(results, headers=headers)
def paginate(self, request, on_results=None, paginator_cls=Paginator, **kwargs): per_page = int(request.GET.get('per_page', 100)) input_cursor = request.GET.get('cursor') if input_cursor: input_cursor = Cursor.from_string(input_cursor) assert per_page <= 100 paginator = paginator_cls(**kwargs) cursor_result = paginator.get_result( limit=per_page, cursor=input_cursor, ) # map results based on callback if on_results: results = on_results(cursor_result.results) headers = {} headers['Link'] = ', '.join([ self.build_cursor_link(request, 'previous', cursor_result.prev), self.build_cursor_link(request, 'next', cursor_result.next), ]) return Response(results, headers=headers)
def _build_query_params_from_request(self, request, project): query_kwargs = { 'project': project, 'sort_by': request.GET.get('sort', DEFAULT_SORT_OPTION), } limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: try: query_kwargs.update(parse_query(project, query, request.user)) except InvalidQuery as e: raise ValidationError( u'Your search query could not be parsed: {}'.format( e.message) ) return query_kwargs
def paginate( self, request, on_results=None, paginator=None, paginator_cls=Paginator, default_per_page=100, max_per_page=100, **paginator_kwargs ): assert (paginator and not paginator_kwargs) or (paginator_cls and paginator_kwargs) per_page = int(request.GET.get('per_page', default_per_page)) input_cursor = request.GET.get('cursor') if input_cursor: input_cursor = Cursor.from_string(input_cursor) else: input_cursor = None assert per_page <= max(max_per_page, default_per_page) if not paginator: paginator = paginator_cls(**paginator_kwargs) cursor_result = paginator.get_result( limit=per_page, cursor=input_cursor, ) # map results based on callback if on_results: results = on_results(cursor_result.results) else: results = cursor_result.results response = Response(results) self.add_cursor_headers(request, response, cursor_result) return response
def build_query_params_from_request(request, organization, projects, environments): query_kwargs = { 'projects': projects, 'sort_by': request.GET.get('sort', DEFAULT_SORT_OPTION), } limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: try: search_filters = convert_query_values( parse_search_query(query), projects, request.user, environments, ) except InvalidSearchQuery as e: raise ValidationError(u'Your search query could not be parsed: {}'.format(e.message)) validate_search_filter_permissions(organization, search_filters) query_kwargs['search_filters'] = search_filters return query_kwargs
def _build_query_params_from_request(self, request, project): query_kwargs = { 'project': project, } if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: raise ValidationError('invalid status') if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: try: query_kwargs.update(parse_query(project, query, request.user)) except InvalidQuery as e: raise ValidationError(u'Your search query could not be parsed: {}'.format(e.message)) return query_kwargs
def get(self, request, project_id): """ List a project's aggregates Return a list of aggregates bound to a project. {method} {path}?id=1&id=2&id=3 A default query of 'is:resolved' is applied. To return results with other statuses send an new query value (i.e. ?query= for all results). Any standard Sentry structured search query can be passed via the ``query`` parameter. """ project = Project.objects.get_from_cache( id=project_id, ) assert_perm(project, request.user, request.auth) query_kwargs = { 'project': project, } if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: return Response('{"error": "invalid status"}', status=400) if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags # TODO: dates should include timestamps date_from = request.GET.get('since') time_from = request.GET.get('until') date_filter = request.GET.get('date_filter') date_to = request.GET.get('dt') time_to = request.GET.get('tt') limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: return Response('{"error": "invalid limit"}', status=400) today = timezone.now() # date format is Y-m-d if any(x is not None for x in [date_from, time_from, date_to, time_to]): date_from, date_to = parse_date(date_from, time_from), parse_date(date_to, time_to) else: date_from = today - timedelta(days=5) date_to = None query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved') if query is not None: query_kwargs.update(parse_query(query, request.user)) cursor_result = search.query(**query_kwargs) context = list(cursor_result) GroupMeta.objects.populate_cache(context) response = Response(serialize(context, request.user)) response['Link'] = ', '.join([ self.build_cursor_link(request, 'previous', cursor_result.prev), self.build_cursor_link(request, 'next', cursor_result.next), ]) return response
def get(self, request, project): """ List a Project's Aggregates ``````````````````````````` Return a list of aggregates bound to a project. All parameters are supplied as query string parameters. A default query of ``is:resolved`` is applied. To return results with other statuses send an new query value (i.e. ``?query=`` for all results). The ``statsPeriod`` parameter can be used to select the timeline stats which should be present. Possible values are: '' (disable), '24h', '14d' :qparam string statsPeriod: an optional stat period (can be one of ``"24h"``, ``"14d"``, and ``""``). :qparam querystring query: an optional Sentry structured search query. If not provided an implied ``"is:resolved"`` is assumed.) :pparam string organization_slug: the slug of the organization the groups belong to. :pparam string project_slug: the slug of the project the groups belong to. :auth: required """ query_kwargs = { 'project': project, } stats_period = request.GET.get('statsPeriod') if stats_period not in (None, '', '24h', '14d'): return Response({"detail": ERR_INVALID_STATS_PERIOD}, status=400) elif stats_period is None: # default stats_period = '24h' elif stats_period == '': # disable stats stats_period = None if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: return Response('{"detail": "invalid status"}', status=400) if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags # TODO: dates should include timestamps date_from = request.GET.get('since') date_to = request.GET.get('until') date_filter = request.GET.get('date_filter') limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: return Response('{"detail": "invalid limit"}', status=400) if date_from: date_from = self._parse_date(date_from) if date_to: date_to = self._parse_date(date_to) query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if len(query) == 32: # check to see if we've got an event ID try: matching_event = EventMapping.objects.filter( project=project, event_id=query, ).select_related('group')[0] except IndexError: pass else: return Response( serialize( [matching_event.group], request.user, StreamGroupSerializer(stats_period=stats_period))) if query is not None: query_kwargs.update(parse_query(project, query, request.user)) cursor_result = search.query(**query_kwargs) results = list(cursor_result) context = serialize(results, request.user, StreamGroupSerializer(stats_period=stats_period)) # HACK: remove auto resolved entries if query_kwargs.get('status') == GroupStatus.UNRESOLVED: context = [r for r in context if r['status'] == 'unresolved'] response = Response(context) response['Link'] = ', '.join([ self.build_cursor_link(request, 'previous', cursor_result.prev), self.build_cursor_link(request, 'next', cursor_result.next), ]) return response
def _get_group_list(request, project): query_kwargs = { 'project': project, } status = request.GET.get('status', '0') if status: query_kwargs['status'] = int(status) if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') or request.session.get('streamsort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION # Save last sort in session if sort_by != request.session.get('streamsort'): request.session['streamsort'] = sort_by query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags else: query_kwargs['tags'] = {} date_from = request.GET.get('df') time_from = request.GET.get('tf') date_to = request.GET.get('dt') time_to = request.GET.get('tt') date_filter = request.GET.get('date_type') today = timezone.now() # date format is Y-m-d if any(x is not None for x in [date_from, time_from, date_to, time_to]): date_from, date_to = parse_date(date_from, time_from), parse_date(date_to, time_to) else: date_from = today - datetime.timedelta(days=5) date_to = None query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter cursor = request.GET.get('cursor') if cursor: try: query_kwargs['cursor'] = Cursor.from_string(cursor) except ValueError: # XXX(dcramer): ideally we'd error, but this is an internal API so # we'd rather just throw it away logging.info('Throwing away invalid cursor: %s', cursor) query_kwargs['limit'] = EVENTS_PER_PAGE query = request.GET.get('query', '') if query is not None: query_result = parse_query(query, request.user) # Disclaimer: the following code is disgusting if query_result.get('query'): query_kwargs['query'] = query_result['query'] if query_result.get('tags'): query_kwargs['tags'].update(query_result['tags']) results = app.search.query(**query_kwargs) return { 'event_list': results[:EVENTS_PER_PAGE], 'date_from': date_from, 'date_to': date_to, 'today': today, 'sort': sort_by, 'date_type': date_filter, 'next_cursor': results.next, 'prev_cursor': results.prev, }
def _build_query_params_from_request(self, request, project): query_kwargs = { 'project': project, } if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: raise ValidationError('invalid status') if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags # TODO: dates should include timestamps date_from = request.GET.get('since') date_to = request.GET.get('until') date_filter = request.GET.get('date_filter') limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') if date_from: date_from = self._parse_date(date_from) if date_to: date_to = self._parse_date(date_to) query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: query_kwargs.update(parse_query(project, query, request.user)) return query_kwargs
def _get_group_list(request, project): query_kwargs = {"project": project} status = request.GET.get("status", "0") if status: query_kwargs["status"] = int(status) if request.user.is_authenticated() and request.GET.get("bookmarks"): query_kwargs["bookmarked_by"] = request.user if request.user.is_authenticated() and request.GET.get("assigned"): query_kwargs["assigned_to"] = request.user sort_by = request.GET.get("sort") or request.session.get("streamsort") if sort_by is None: sort_by = DEFAULT_SORT_OPTION # Save last sort in session if sort_by != request.session.get("streamsort"): request.session["streamsort"] = sort_by query_kwargs["sort_by"] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs["tags"] = tags else: query_kwargs["tags"] = {} date_from = request.GET.get("df") time_from = request.GET.get("tf") date_to = request.GET.get("dt") time_to = request.GET.get("tt") date_filter = request.GET.get("date_type") today = timezone.now() # date format is Y-m-d if any(x is not None for x in [date_from, time_from, date_to, time_to]): date_from, date_to = parse_date(date_from, time_from), parse_date(date_to, time_to) else: date_from = today - datetime.timedelta(days=5) date_to = None query_kwargs["date_from"] = date_from query_kwargs["date_to"] = date_to if date_filter: query_kwargs["date_filter"] = date_filter cursor = request.GET.get("cursor") if cursor: try: query_kwargs["cursor"] = Cursor.from_string(cursor) except ValueError: # XXX(dcramer): ideally we'd error, but this is an internal API so # we'd rather just throw it away logging.info("Throwing away invalid cursor: %s", cursor) query_kwargs["limit"] = EVENTS_PER_PAGE query = request.GET.get("query", "") if query is not None: query_result = parse_query(query, request.user) # Disclaimer: the following code is disgusting if query_result.get("query"): query_kwargs["query"] = query_result["query"] if query_result.get("tags"): query_kwargs["tags"].update(query_result["tags"]) results = app.search.query(**query_kwargs) return { "event_list": results[:EVENTS_PER_PAGE], "date_from": date_from, "date_to": date_to, "today": today, "sort": sort_by, "date_type": date_filter, "next_cursor": results.next, "prev_cursor": results.prev, }
def get(self, request, project): """ List a project's aggregates Return a list of aggregates bound to a project. {method} {path} A default query of 'is:resolved' is applied. To return results with other statuses send an new query value (i.e. ?query= for all results). Any standard Sentry structured search query can be passed via the ``query`` parameter. """ query_kwargs = { 'project': project, } if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: return Response('{"detail": "invalid status"}', status=400) if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags # TODO: dates should include timestamps date_from = request.GET.get('since') time_from = request.GET.get('until') date_filter = request.GET.get('date_filter') date_to = request.GET.get('dt') time_to = request.GET.get('tt') limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: return Response('{"detail": "invalid limit"}', status=400) today = timezone.now() # date format is Y-m-d if any(x is not None for x in [date_from, time_from, date_to, time_to]): date_from, date_to = parse_date(date_from, time_from), parse_date( date_to, time_to) else: date_from = today - timedelta(days=5) date_to = None query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved') if query is not None: query_kwargs.update(parse_query(query, request.user)) cursor_result = search.query(**query_kwargs) context = list(cursor_result) response = Response( serialize(context, request.user, StreamGroupSerializer())) response['Link'] = ', '.join([ self.build_cursor_link(request, 'previous', cursor_result.prev), self.build_cursor_link(request, 'next', cursor_result.next), ]) return response
def _get_group_list(request, project): query_kwargs = { 'project': project, } status = request.GET.get('status', '0') if status: query_kwargs['status'] = int(status) if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') or request.session.get('streamsort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION # Save last sort in session if sort_by != request.session.get('streamsort'): request.session['streamsort'] = sort_by query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags else: query_kwargs['tags'] = {} date_from = request.GET.get('df') time_from = request.GET.get('tf') date_to = request.GET.get('dt') time_to = request.GET.get('tt') date_filter = request.GET.get('date_type') today = timezone.now() # date format is Y-m-d if any(x is not None for x in [date_from, time_from, date_to, time_to]): date_from, date_to = parse_date(date_from, time_from), parse_date( date_to, time_to) else: date_from = today - datetime.timedelta(days=5) date_to = None query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter cursor = request.GET.get('cursor') if cursor: try: query_kwargs['cursor'] = Cursor.from_string(cursor) except ValueError: # XXX(dcramer): ideally we'd error, but this is an internal API so # we'd rather just throw it away logging.info('Throwing away invalid cursor: %s', cursor) query_kwargs['limit'] = EVENTS_PER_PAGE query = request.GET.get('query', '') if query is not None: for key, value in parse_query(query, request.user).iteritems(): if key == 'tags': query_kwargs['tags'].update(value) else: query_kwargs[key] = value results = app.search.query(**query_kwargs) return { 'event_list': results[:EVENTS_PER_PAGE], 'date_from': date_from, 'date_to': date_to, 'today': today, 'sort': sort_by, 'date_type': date_filter, 'next_cursor': results.next, 'prev_cursor': results.prev, }
def get(self, request, project): """ List a project's aggregates Return a list of aggregates bound to a project. {method} {path} A default query of 'is:resolved' is applied. To return results with other statuses send an new query value (i.e. ?query= for all results). Any standard Sentry structured search query can be passed via the ``query`` parameter. The ``statsPeriod`` parameter can be used to select the timeline stats which should be present. Possible values are: '' (disable), '24h', '14d' """ query_kwargs = { 'project': project, } stats_period = request.GET.get('statsPeriod') if stats_period not in (None, '', '24h', '14d'): return Response({"detail": ERR_INVALID_STATS_PERIOD}, status=400) elif stats_period is None: # default stats_period = '24h' elif stats_period == '': # disable stats stats_period = None if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: return Response('{"detail": "invalid status"}', status=400) if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags # TODO: dates should include timestamps date_from = request.GET.get('since') date_to = request.GET.get('until') date_filter = request.GET.get('date_filter') limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: return Response('{"detail": "invalid limit"}', status=400) if date_from: date_from = self._parse_date(date_from) if date_to: date_to = self._parse_date(date_to) query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if len(query) == 32: # check to see if we've got an event ID try: matching_event = EventMapping.objects.filter( project=project, event_id=query, ).select_related('group')[0] except IndexError: pass else: return Response(serialize( [matching_event.group], request.user, StreamGroupSerializer( stats_period=stats_period ) )) if query is not None: query_kwargs.update(parse_query(query, request.user)) cursor_result = search.query(**query_kwargs) results = list(cursor_result) # HACK: remove auto resolved entries if query_kwargs.get('status') == STATUS_UNRESOLVED: results = [ r for r in results if not r.is_resolved() ] response = Response(serialize( results, request.user, StreamGroupSerializer( stats_period=stats_period ) )) response['Link'] = ', '.join([ self.build_cursor_link(request, 'previous', cursor_result.prev), self.build_cursor_link(request, 'next', cursor_result.next), ]) return response
def _build_query_params_from_request(self, request, project): query_kwargs = { 'project': project, } if request.GET.get('status'): try: query_kwargs['status'] = STATUS_CHOICES[request.GET['status']] except KeyError: raise ValidationError('invalid status') if request.user.is_authenticated() and request.GET.get('bookmarks'): query_kwargs['bookmarked_by'] = request.user if request.user.is_authenticated() and request.GET.get('assigned'): query_kwargs['assigned_to'] = request.user sort_by = request.GET.get('sort') if sort_by is None: sort_by = DEFAULT_SORT_OPTION query_kwargs['sort_by'] = sort_by tags = {} for tag_key in TagKey.objects.all_keys(project): if request.GET.get(tag_key): tags[tag_key] = request.GET[tag_key] if tags: query_kwargs['tags'] = tags # TODO: dates should include timestamps date_from = request.GET.get('since') date_to = request.GET.get('until') date_filter = request.GET.get('date_filter') limit = request.GET.get('limit') if limit: try: query_kwargs['limit'] = int(limit) except ValueError: raise ValidationError('invalid limit') if date_from: date_from = self._parse_date(date_from) if date_to: date_to = self._parse_date(date_to) query_kwargs['date_from'] = date_from query_kwargs['date_to'] = date_to if date_filter: query_kwargs['date_filter'] = date_filter # TODO: proper pagination support cursor = request.GET.get('cursor') if cursor: query_kwargs['cursor'] = Cursor.from_string(cursor) query = request.GET.get('query', 'is:unresolved').strip() if query: query_kwargs.update(parse_query(project, query, request.user)) return query_kwargs