test_event_attachment_details.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. from io import BytesIO
  2. from sentry.models import EventAttachment, File
  3. from sentry.testutils import APITestCase, PermissionTestCase
  4. from sentry.testutils.helpers.datetime import before_now, iso_format
  5. from sentry.testutils.helpers.response import close_streaming_response
  6. from sentry.testutils.silo import region_silo_test
  7. class CreateAttachmentMixin:
  8. def create_attachment(self):
  9. self.project = self.create_project()
  10. self.release = self.create_release(self.project, self.user)
  11. min_ago = iso_format(before_now(minutes=1))
  12. self.event = self.store_event(
  13. data={
  14. "fingerprint": ["group1"],
  15. "timestamp": min_ago,
  16. "tags": {"sentry:release": self.release.version},
  17. },
  18. project_id=self.project.id,
  19. )
  20. self.file = File.objects.create(name="hello.png", type="image/png; foo=bar")
  21. self.file.putfile(BytesIO(b"File contents here"))
  22. self.attachment = EventAttachment.objects.create(
  23. event_id=self.event.event_id,
  24. project_id=self.event.project_id,
  25. file_id=self.file.id,
  26. type=self.file.type,
  27. name="hello.png",
  28. )
  29. assert self.attachment.mimetype == "image/png"
  30. return self.attachment
  31. @region_silo_test(stable=True)
  32. class EventAttachmentDetailsTest(APITestCase, CreateAttachmentMixin):
  33. def test_simple(self):
  34. self.login_as(user=self.user)
  35. self.create_attachment()
  36. path = f"/api/0/projects/{self.organization.slug}/{self.project.slug}/events/{self.event.event_id}/attachments/{self.attachment.id}/"
  37. with self.feature("organizations:event-attachments"):
  38. response = self.client.get(path)
  39. assert response.status_code == 200, response.content
  40. assert response.data["id"] == str(self.attachment.id)
  41. assert response.data["mimetype"] == self.attachment.mimetype
  42. assert response.data["event_id"] == self.event.event_id
  43. def test_download(self):
  44. self.login_as(user=self.user)
  45. self.create_attachment()
  46. path = f"/api/0/projects/{self.organization.slug}/{self.project.slug}/events/{self.event.event_id}/attachments/{self.attachment.id}/?download"
  47. with self.feature("organizations:event-attachments"):
  48. response = self.client.get(path)
  49. assert response.status_code == 200, response.content
  50. assert response.get("Content-Disposition") == 'attachment; filename="hello.png"'
  51. assert response.get("Content-Length") == str(self.file.size)
  52. assert response.get("Content-Type") == "application/octet-stream"
  53. assert b"File contents here" == b"".join(response.streaming_content)
  54. def test_delete(self):
  55. self.login_as(user=self.user)
  56. self.create_attachment()
  57. path = f"/api/0/projects/{self.organization.slug}/{self.project.slug}/events/{self.event.event_id}/attachments/{self.attachment.id}/"
  58. with self.feature("organizations:event-attachments"):
  59. response = self.client.delete(path)
  60. assert response.status_code == 204, response.content
  61. assert EventAttachment.objects.count() == 0
  62. @region_silo_test
  63. class EventAttachmentDetailsPermissionTest(PermissionTestCase, CreateAttachmentMixin):
  64. def setUp(self):
  65. super().setUp()
  66. self.create_attachment()
  67. self.path = f"/api/0/projects/{self.organization.slug}/{self.project.slug}/events/{self.event.event_id}/attachments/{self.attachment.id}/?download"
  68. def test_member_can_access_by_default(self):
  69. with self.feature("organizations:event-attachments"):
  70. close_streaming_response(self.assert_member_can_access(self.path))
  71. close_streaming_response(self.assert_can_access(self.owner, self.path))
  72. def test_member_cannot_access_for_owner_role(self):
  73. self.organization.update_option("sentry:attachments_role", "owner")
  74. with self.feature("organizations:event-attachments"):
  75. self.assert_member_cannot_access(self.path)
  76. close_streaming_response(self.assert_can_access(self.owner, self.path))
  77. def test_member_on_owner_team_can_access_for_owner_role(self):
  78. self.organization.update_option("sentry:attachments_role", "owner")
  79. owner_team = self.create_team(organization=self.organization, org_role="owner")
  80. user = self.create_user()
  81. self.create_member(organization=self.organization, user=user, teams=[owner_team, self.team])
  82. with self.feature("organizations:event-attachments"):
  83. close_streaming_response(self.assert_can_access(user, self.path))
  84. def test_random_user_cannot_access(self):
  85. self.organization.update_option("sentry:attachments_role", "owner")
  86. user = self.create_user()
  87. with self.feature("organizations:event-attachments"):
  88. self.assert_cannot_access(user, self.path)
  89. def test_superuser_can_access(self):
  90. self.organization.update_option("sentry:attachments_role", "owner")
  91. superuser = self.create_user(is_superuser=True)
  92. with self.feature("organizations:event-attachments"):
  93. close_streaming_response(self.assert_can_access(superuser, self.path))