views.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. from django.shortcuts import get_object_or_404
  2. from rest_framework import viewsets, views, mixins
  3. from rest_framework.decorators import action
  4. from rest_framework.response import Response
  5. from .models import Issue, Event, EventStatus
  6. from .serializers import (
  7. IssueSerializer,
  8. EventSerializer,
  9. EventDetailSerializer,
  10. )
  11. from .filters import IssueFilter
  12. from .permissions import IssuePermission, EventPermission
  13. class IssueViewSet(
  14. mixins.ListModelMixin,
  15. mixins.RetrieveModelMixin,
  16. mixins.UpdateModelMixin,
  17. mixins.DestroyModelMixin,
  18. viewsets.GenericViewSet,
  19. ):
  20. """
  21. View and bulk update issues.
  22. # Bulk updates
  23. Submit PUT request to bulk update Issue statuses
  24. ## Query Parameters
  25. - id (int) — a list of IDs of the issues to be removed. This parameter shall be repeated for each issue.
  26. - query (string) — querystring for structured search. Example: "is:unresolved" searches for status=unresolved.
  27. """
  28. queryset = Issue.objects.all()
  29. serializer_class = IssueSerializer
  30. filterset_class = IssueFilter
  31. permission_classes = [IssuePermission]
  32. def get_queryset(self):
  33. if not self.request.user.is_authenticated:
  34. return self.queryset.none()
  35. qs = (
  36. super()
  37. .get_queryset()
  38. .filter(project__team__members__user=self.request.user)
  39. )
  40. if "organization_slug" in self.kwargs:
  41. qs = qs.filter(
  42. project__organization__slug=self.kwargs["organization_slug"],
  43. )
  44. if "project_slug" in self.kwargs:
  45. qs = qs.filter(project__slug=self.kwargs["project_slug"],)
  46. queries = self.request.GET.get("query")
  47. if queries:
  48. # First look for structured queries
  49. for query in queries.split():
  50. query_part = query.split(":", 1)
  51. if len(query_part) == 2:
  52. # Remove query from queries
  53. queries = queries.replace(query, "").strip()
  54. query_name, query_value = query_part
  55. if query_name == "is":
  56. qs = qs.filter(status=EventStatus.from_string(query_value))
  57. if queries:
  58. # Anything left is full text search
  59. qs = qs.filter(search_vector=queries)
  60. qs = (
  61. qs.select_related("project")
  62. .defer("search_vector")
  63. .prefetch_related("userreport_set")
  64. )
  65. return qs
  66. def bulk_update(self, request, *args, **kwargs):
  67. queryset = self.get_queryset()
  68. ids = request.GET.getlist("id")
  69. queryset = queryset.filter(id__in=ids)
  70. status = EventStatus.from_string(request.data.get("status"))
  71. queryset.update(status=status)
  72. return Response({"status": status.label})
  73. class EventViewSet(viewsets.ReadOnlyModelViewSet):
  74. queryset = Event.objects.all()
  75. serializer_class = EventSerializer
  76. permission_classes = [EventPermission]
  77. def get_serializer_class(self):
  78. if self.action in ["retrieve", "latest"]:
  79. return EventDetailSerializer
  80. return super().get_serializer_class()
  81. def get_queryset(self):
  82. if not self.request.user.is_authenticated:
  83. return self.queryset.none()
  84. qs = (
  85. super()
  86. .get_queryset()
  87. .filter(issue__project__team__members__user=self.request.user)
  88. )
  89. if "issue_pk" in self.kwargs:
  90. qs = qs.filter(issue=self.kwargs["issue_pk"])
  91. if "organization_slug" in self.kwargs:
  92. qs = qs.filter(
  93. issue__project__organization__slug=self.kwargs["organization_slug"],
  94. )
  95. if "project_slug" in self.kwargs:
  96. qs = qs.filter(issue__project__slug=self.kwargs["project_slug"],)
  97. qs = qs.prefetch_related("tags__key")
  98. return qs
  99. @action(detail=False, methods=["get"])
  100. def latest(self, request, *args, **kwargs):
  101. instance = self.get_queryset().first()
  102. serializer = self.get_serializer(instance)
  103. return Response(serializer.data)
  104. class EventJsonView(views.APIView):
  105. """
  106. Represents a "raw" view of the event
  107. Not significantly different from event API view in usage but format is very different.
  108. Exists mainly for Sentry API compatibility
  109. """
  110. permission_classes = [EventPermission]
  111. def get(self, request, org, issue, event, format=None):
  112. event = get_object_or_404(
  113. Event,
  114. pk=event,
  115. issue__project__organization__slug=org,
  116. issue__project__team__members__user=self.request.user,
  117. )
  118. return Response(event.event_json())