test_api.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. from django.test import TestCase
  2. from django.urls import reverse
  3. from model_bakery import baker
  4. from apps.organizations_ext.models import OrganizationUserRole
  5. from glitchtip.test_utils.test_case import GlitchTipTestCaseMixin
  6. from ..models import ProjectAlert
  7. class AlertAPITestCase(GlitchTipTestCaseMixin, TestCase):
  8. def setUp(self):
  9. self.create_logged_in_user()
  10. def test_project_alerts_list(self):
  11. alert = baker.make(
  12. "alerts.ProjectAlert", project=self.project, timespan_minutes=60
  13. )
  14. # Should not show up
  15. baker.make("alerts.ProjectAlert", timespan_minutes=60)
  16. # Second team could cause duplicates
  17. team2 = baker.make("teams.Team", organization=self.organization)
  18. team2.members.add(self.org_user)
  19. self.project.teams.add(team2)
  20. url = reverse(
  21. "api:list_project_alerts", args=[self.organization.slug, self.project.slug]
  22. )
  23. res = self.client.get(url)
  24. self.assertContains(res, alert.id)
  25. self.assertEqual(len(res.json()), 1)
  26. def test_project_alerts_create(self):
  27. url = reverse(
  28. "api:create_project_alert", args=[self.organization.slug, self.project.slug]
  29. )
  30. data = {
  31. "name": "foo",
  32. "timespanMinutes": 60,
  33. "quantity": 2,
  34. "uptime": True,
  35. "alertRecipients": [{"recipientType": "email", "url": ""}],
  36. }
  37. res = self.client.post(url, data, content_type="application/json")
  38. self.assertEqual(res.status_code, 201)
  39. project_alert = ProjectAlert.objects.filter(name="foo", uptime=True).first()
  40. self.assertEqual(project_alert.timespan_minutes, data["timespanMinutes"])
  41. self.assertEqual(project_alert.project, self.project)
  42. def test_project_alerts_create_permissions(self):
  43. user = baker.make("users.user")
  44. org_user = self.organization.add_user(user, OrganizationUserRole.MEMBER)
  45. self.client.force_login(user)
  46. url = reverse(
  47. "api:create_project_alert", args=[self.organization.slug, self.project.slug]
  48. )
  49. data = {
  50. "name": "foo",
  51. "timespanMinutes": 60,
  52. "quantity": 2,
  53. "uptime": True,
  54. "alertRecipients": [{"recipientType": "email", "url": ""}],
  55. }
  56. res = self.client.post(url, data, content_type="application/json")
  57. # Member without project team membership cannot create alerts
  58. self.assertEqual(res.status_code, 404)
  59. org_user.role = OrganizationUserRole.ADMIN
  60. org_user.save()
  61. # Add second team to ensure we don't get MultipleObjectsReturned
  62. team2 = baker.make("teams.Team", organization=self.organization)
  63. team2.members.add(org_user)
  64. self.project.teams.add(team2)
  65. res = self.client.post(url, data, content_type="application/json")
  66. self.assertEqual(res.status_code, 201)
  67. org_user.role = OrganizationUserRole.MEMBER
  68. org_user.save()
  69. res = self.client.get(url)
  70. # Members can still view alerts
  71. self.assertEqual(len(res.json()), 1)
  72. def test_project_alerts_update(self):
  73. alert = baker.make(
  74. "alerts.ProjectAlert", project=self.project, timespan_minutes=60
  75. )
  76. url = reverse(
  77. "api:update_project_alert",
  78. args=[self.organization.slug, self.project.slug, alert.pk],
  79. )
  80. data = {
  81. "timespanMinutes": 500,
  82. "quantity": 2,
  83. "alertRecipients": [
  84. {"recipientType": "discord", "url": "https://example.com"},
  85. ],
  86. }
  87. res = self.client.put(url, data, content_type="application/json")
  88. self.assertContains(res, data["alertRecipients"][0]["url"])
  89. # Webhooks require url
  90. data = {
  91. "alertRecipients": [
  92. {"recipientType": "discord", "url": ""},
  93. ],
  94. }
  95. res = self.client.put(url, data, content_type="application/json")
  96. self.assertEqual(res.status_code, 422)
  97. def test_project_alerts_update_auth(self):
  98. """Cannot update alert on project that user does not belong to"""
  99. alert = baker.make("alerts.ProjectAlert", timespan_minutes=60)
  100. url = reverse(
  101. "api:update_project_alert",
  102. args=[self.organization.slug, self.project.slug, alert.pk],
  103. )
  104. data = {"timespanMinutes": 500, "quantity": 2}
  105. res = self.client.put(url, data, content_type="application/json")
  106. self.assertEqual(res.status_code, 404)
  107. def test_project_alerts_delete(self):
  108. alert = baker.make(
  109. "alerts.ProjectAlert", project=self.project, timespan_minutes=60
  110. )
  111. url = reverse(
  112. "api:delete_project_alert",
  113. args=[self.organization.slug, self.project.slug, alert.pk],
  114. )
  115. res = self.client.delete(url, content_type="application/json")
  116. self.assertEqual(res.status_code, 204)
  117. self.assertEqual(ProjectAlert.objects.count(), 0)
  118. def test_delete_with_second_team(self):
  119. alert = baker.make(
  120. "alerts.ProjectAlert", project=self.project, timespan_minutes=60
  121. )
  122. url = reverse(
  123. "api:delete_project_alert",
  124. args=[self.organization.slug, self.project.slug, alert.pk],
  125. )
  126. team2 = baker.make("teams.Team", organization=self.organization)
  127. team2.members.add(self.org_user)
  128. self.project.teams.add(team2)
  129. res = self.client.delete(url, content_type="application/json")
  130. self.assertEqual(res.status_code, 204)
  131. self.assertEqual(ProjectAlert.objects.count(), 0)