api.py 3.5 KB

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