events.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import uuid
  2. from typing import Optional
  3. from django.db.models import OuterRef, Subquery, Window
  4. from django.db.models.functions import Lag
  5. from django.http import Http404
  6. from glitchtip.api.authentication import AuthHttpRequest
  7. from ..models import IssueEvent
  8. from ..schema import IssueEventDetailSchema, IssueEventJsonSchema, IssueEventSchema
  9. from . import router
  10. def get_queryset(
  11. request: AuthHttpRequest,
  12. issue_id: Optional[int] = None,
  13. organization_slug: Optional[str] = None,
  14. project_slug: Optional[str] = None,
  15. ):
  16. user_id = request.auth
  17. qs = IssueEvent.objects.filter(issue__project__organization__users=user_id)
  18. if issue_id:
  19. qs = qs.filter(issue_id=issue_id)
  20. if organization_slug:
  21. qs = qs.filter(issue__project__organization__slug=organization_slug)
  22. if project_slug:
  23. qs = qs.filter(issue__project__slug=project_slug)
  24. return qs.select_related("issue").order_by("-received")
  25. @router.get(
  26. "/issues/{int:issue_id}/events/", response=list[IssueEventSchema], by_alias=True
  27. )
  28. async def list_issue_event(request: AuthHttpRequest, issue_id: int):
  29. return [obj async for obj in get_queryset(request, issue_id=issue_id)]
  30. @router.get(
  31. "/issues/{int:issue_id}/events/latest/",
  32. response=IssueEventDetailSchema,
  33. by_alias=True,
  34. )
  35. async def get_latest_issue_event(request: AuthHttpRequest, issue_id: int):
  36. qs = get_queryset(request, issue_id)
  37. qs = qs.annotate(
  38. previous=Window(expression=Lag("id"), order_by="received"),
  39. )
  40. obj = await qs.afirst()
  41. if not obj:
  42. raise Http404()
  43. obj.next = None # We know the next after "latest" must be None
  44. return obj
  45. @router.get(
  46. "/issues/{int:issue_id}/events/{event_id}/",
  47. response=IssueEventDetailSchema,
  48. by_alias=True,
  49. )
  50. async def get_issue_event(request: AuthHttpRequest, issue_id: int, event_id: uuid.UUID):
  51. qs = get_queryset(request, issue_id)
  52. qs = qs.annotate(
  53. previous=Subquery(
  54. qs.filter(received__lt=OuterRef("received")).values("id")[:1]
  55. ),
  56. next=Subquery(qs.filter(received__gt=OuterRef("received")).values("id")[:1]),
  57. )
  58. try:
  59. return await qs.filter(id=event_id).aget()
  60. except IssueEvent.DoesNotExist:
  61. raise Http404()
  62. @router.get(
  63. "/projects/{slug:organization_slug}/{slug:project_slug}/events/",
  64. response=list[IssueEventSchema],
  65. by_alias=True,
  66. )
  67. async def list_project_issue_event(
  68. request: AuthHttpRequest,
  69. organization_slug: str,
  70. project_slug: str,
  71. ):
  72. return [
  73. obj
  74. async for obj in get_queryset(
  75. request, organization_slug=organization_slug, project_slug=project_slug
  76. )
  77. ]
  78. @router.get(
  79. "/projects/{slug:organization_slug}/{slug:project_slug}/events/{event_id}/",
  80. response=IssueEventDetailSchema,
  81. by_alias=True,
  82. )
  83. async def get_project_issue_event(
  84. request: AuthHttpRequest,
  85. organization_slug: str,
  86. project_slug: str,
  87. event_id: uuid.UUID,
  88. ):
  89. qs = get_queryset(
  90. request, organization_slug=organization_slug, project_slug=project_slug
  91. )
  92. qs = qs.annotate(
  93. previous=Subquery(
  94. qs.filter(received__lt=OuterRef("received")).values("id")[:1]
  95. ),
  96. next=Subquery(qs.filter(received__gt=OuterRef("received")).values("id")[:1]),
  97. )
  98. try:
  99. return await qs.aget(id=event_id)
  100. except IssueEvent.DoesNotExist:
  101. raise Http404()
  102. @router.get(
  103. "/organizations/{slug:organization_slug}/issues/{int:issue_id}/events/{event_id}/json/",
  104. response=IssueEventJsonSchema,
  105. by_alias=True,
  106. )
  107. async def get_event_json(
  108. request: AuthHttpRequest, organization_slug: str, issue_id: int, event_id: uuid.UUID
  109. ):
  110. qs = get_queryset(request, organization_slug=organization_slug, issue_id=issue_id)
  111. try:
  112. return await qs.aget(id=event_id)
  113. except IssueEvent.DoesNotExist:
  114. raise Http404()