|
@@ -23,7 +23,17 @@ org.slf4j.helpers.Util$ClassContextSecurityManager -> org.a.b.g$a:
|
|
|
"""
|
|
|
|
|
|
|
|
|
-class DebugFilesUploadTest(APITestCase):
|
|
|
+class DebugFilesTestCases(APITestCase):
|
|
|
+ def setUp(self):
|
|
|
+ self.url = reverse(
|
|
|
+ "sentry-api-0-dsym-files",
|
|
|
+ kwargs={
|
|
|
+ "organization_id_or_slug": self.organization.slug,
|
|
|
+ "project_id_or_slug": self.project.slug,
|
|
|
+ },
|
|
|
+ )
|
|
|
+ self.login_as(user=self.user)
|
|
|
+
|
|
|
def _upload_proguard(self, url, uuid):
|
|
|
out = BytesIO()
|
|
|
f = zipfile.ZipFile(out, "w")
|
|
@@ -40,45 +50,10 @@ class DebugFilesUploadTest(APITestCase):
|
|
|
format="multipart",
|
|
|
)
|
|
|
|
|
|
- def test_simple_proguard_upload(self):
|
|
|
- project = self.create_project(name="foo")
|
|
|
-
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
-
|
|
|
- self.login_as(user=self.user)
|
|
|
-
|
|
|
- response = self._upload_proguard(url, PROGUARD_UUID)
|
|
|
-
|
|
|
- assert response.status_code == 201, response.content
|
|
|
- assert len(response.data) == 1
|
|
|
- assert response.data[0]["headers"] == {"Content-Type": "text/x-proguard+plain"}
|
|
|
- assert response.data[0]["sha1"] == "e6d3c5185dac63eddfdc1a5edfffa32d46103b44"
|
|
|
- assert response.data[0]["uuid"] == PROGUARD_UUID
|
|
|
- assert response.data[0]["objectName"] == "proguard-mapping"
|
|
|
- assert response.data[0]["cpuName"] == "any"
|
|
|
- assert response.data[0]["symbolType"] == "proguard"
|
|
|
-
|
|
|
- def test_associate_proguard_dsym(self):
|
|
|
- project = self.create_project(name="foo")
|
|
|
-
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
-
|
|
|
- self.login_as(user=self.user)
|
|
|
-
|
|
|
- response = self._upload_proguard(url, PROGUARD_UUID)
|
|
|
|
|
|
+class DebugFilesTest(DebugFilesTestCases):
|
|
|
+ def test_simple_proguard_upload(self):
|
|
|
+ response = self._upload_proguard(self.url, PROGUARD_UUID)
|
|
|
assert response.status_code == 201, response.content
|
|
|
assert len(response.data) == 1
|
|
|
assert response.data[0]["headers"] == {"Content-Type": "text/x-proguard+plain"}
|
|
@@ -88,132 +63,68 @@ class DebugFilesUploadTest(APITestCase):
|
|
|
assert response.data[0]["cpuName"] == "any"
|
|
|
assert response.data[0]["symbolType"] == "proguard"
|
|
|
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-associate-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
-
|
|
|
- response = self.client.post(
|
|
|
- url,
|
|
|
- {
|
|
|
- "checksums": ["e6d3c5185dac63eddfdc1a5edfffa32d46103b44"],
|
|
|
- "platform": "android",
|
|
|
- "name": "MyApp",
|
|
|
- "appId": "com.example.myapp",
|
|
|
- "version": "1.0",
|
|
|
- "build": "1",
|
|
|
- },
|
|
|
- format="json",
|
|
|
- )
|
|
|
+ def test_dsyms_search(self):
|
|
|
+ for i in range(25):
|
|
|
+ last_uuid = str(uuid4())
|
|
|
+ self._upload_proguard(self.url, last_uuid)
|
|
|
|
|
|
+ # Test max 20 per page
|
|
|
+ response = self.client.get(self.url)
|
|
|
assert response.status_code == 200, response.content
|
|
|
- assert "associatedDsymFiles" in response.data
|
|
|
- assert response.data["associatedDsymFiles"] == []
|
|
|
-
|
|
|
- def test_associate_proguard_dsym_no_build(self):
|
|
|
- project = self.create_project(name="foo")
|
|
|
-
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
+ dsyms = response.data
|
|
|
+ assert len(dsyms) == 20
|
|
|
|
|
|
- self.login_as(user=self.user)
|
|
|
+ # Test should return last
|
|
|
+ response = self.client.get(self.url + "?query=" + last_uuid)
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
+ dsyms = response.data
|
|
|
+ assert len(dsyms) == 1
|
|
|
|
|
|
- response = self._upload_proguard(url, PROGUARD_UUID)
|
|
|
+ response = self.client.get(self.url + "?query=proguard")
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
+ dsyms = response.data
|
|
|
+ assert len(dsyms) == 20
|
|
|
|
|
|
+ def test_access_control(self):
|
|
|
+ # create a debug files such as proguard:
|
|
|
+ response = self._upload_proguard(self.url, PROGUARD_UUID)
|
|
|
assert response.status_code == 201, response.content
|
|
|
assert len(response.data) == 1
|
|
|
- assert response.data[0]["headers"] == {"Content-Type": "text/x-proguard+plain"}
|
|
|
- assert response.data[0]["sha1"] == "e6d3c5185dac63eddfdc1a5edfffa32d46103b44"
|
|
|
- assert response.data[0]["uuid"] == PROGUARD_UUID
|
|
|
- assert response.data[0]["objectName"] == "proguard-mapping"
|
|
|
- assert response.data[0]["cpuName"] == "any"
|
|
|
- assert response.data[0]["symbolType"] == "proguard"
|
|
|
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-associate-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
+ response = self.client.get(self.url)
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
|
|
|
- response = self.client.post(
|
|
|
- url,
|
|
|
- {
|
|
|
- "checksums": ["e6d3c5185dac63eddfdc1a5edfffa32d46103b44"],
|
|
|
- "platform": "android",
|
|
|
- "name": "MyApp",
|
|
|
- "appId": "com.example.myapp",
|
|
|
- "version": "1.0",
|
|
|
- },
|
|
|
- format="json",
|
|
|
- )
|
|
|
+ (dsym,) = response.data
|
|
|
+ download_id = dsym["id"]
|
|
|
|
|
|
+ # `self.user` has access to these files
|
|
|
+ response = self.client.get(f"{self.url}?id={download_id}")
|
|
|
assert response.status_code == 200, response.content
|
|
|
- assert "associatedDsymFiles" in response.data
|
|
|
- assert response.data["associatedDsymFiles"] == []
|
|
|
-
|
|
|
- def test_dsyms_requests(self):
|
|
|
- project = self.create_project(name="foo")
|
|
|
+ assert PROGUARD_SOURCE == b"".join(response.streaming_content)
|
|
|
|
|
|
+ # with another user on a different org
|
|
|
+ other_user = self.create_user()
|
|
|
+ other_org = self.create_organization(name="other-org", owner=other_user)
|
|
|
+ other_project = self.create_project(organization=other_org)
|
|
|
url = reverse(
|
|
|
"sentry-api-0-dsym-files",
|
|
|
kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
+ "organization_id_or_slug": other_org.slug,
|
|
|
+ "project_id_or_slug": other_project.slug,
|
|
|
},
|
|
|
)
|
|
|
+ self.login_as(user=other_user)
|
|
|
|
|
|
- self.login_as(user=self.user)
|
|
|
-
|
|
|
- response = self._upload_proguard(url, PROGUARD_UUID)
|
|
|
+ # accessing foreign files should not work
|
|
|
+ response = self.client.get(f"{url}?id={download_id}")
|
|
|
+ assert response.status_code == 404
|
|
|
|
|
|
+ def test_dsyms_requests(self):
|
|
|
+ response = self._upload_proguard(self.url, PROGUARD_UUID)
|
|
|
assert response.status_code == 201, response.content
|
|
|
assert len(response.data) == 1
|
|
|
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-associate-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
-
|
|
|
- response = self.client.post(
|
|
|
- url,
|
|
|
- {
|
|
|
- "checksums": ["e6d3c5185dac63eddfdc1a5edfffa32d46103b44"],
|
|
|
- "platform": "android",
|
|
|
- "name": "MyApp",
|
|
|
- "appId": "com.example.myapp",
|
|
|
- "version": "1.0",
|
|
|
- "build": "1",
|
|
|
- },
|
|
|
- format="json",
|
|
|
- )
|
|
|
-
|
|
|
- assert response.status_code == 200, response.content
|
|
|
- assert "associatedDsymFiles" in response.data
|
|
|
- assert response.data["associatedDsymFiles"] == []
|
|
|
-
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
-
|
|
|
- response = self.client.get(url)
|
|
|
-
|
|
|
+ response = self.client.get(self.url)
|
|
|
assert response.status_code == 200, response.content
|
|
|
|
|
|
(dsym,) = response.data
|
|
@@ -227,10 +138,7 @@ class DebugFilesUploadTest(APITestCase):
|
|
|
|
|
|
# Download as a user with sufficient role
|
|
|
self.organization.update_option("sentry:debug_files_role", "admin")
|
|
|
- user = self.create_user("baz@localhost")
|
|
|
- self.create_member(user=user, organization=project.organization, role="owner")
|
|
|
- self.login_as(user=user)
|
|
|
- response = self.client.get(url + "?id=" + download_id)
|
|
|
+ response = self.client.get(self.url + "?id=" + download_id)
|
|
|
assert response.status_code == 200, response.content
|
|
|
assert (
|
|
|
response.get("Content-Disposition")
|
|
@@ -241,101 +149,48 @@ class DebugFilesUploadTest(APITestCase):
|
|
|
assert PROGUARD_SOURCE == b"".join(response.streaming_content)
|
|
|
|
|
|
# Download as a superuser
|
|
|
- self.login_as(user=self.user)
|
|
|
- response = self.client.get(url + "?id=" + download_id)
|
|
|
+ superuser = self.create_user(is_superuser=True)
|
|
|
+ self.login_as(user=superuser, superuser=True)
|
|
|
+ response = self.client.get(self.url + "?id=" + download_id)
|
|
|
assert response.get("Content-Type") == "application/octet-stream"
|
|
|
close_streaming_response(response)
|
|
|
|
|
|
# Download as a user without sufficient role
|
|
|
self.organization.update_option("sentry:debug_files_role", "owner")
|
|
|
- user = self.create_user("bar@localhost")
|
|
|
- self.create_member(user=user, organization=project.organization, role="member")
|
|
|
- self.login_as(user=user)
|
|
|
- response = self.client.get(url + "?id=" + download_id)
|
|
|
+ member_user = self.create_user("bar@localhost")
|
|
|
+ self.create_member(user=member_user, organization=self.organization, role="member")
|
|
|
+ self.login_as(user=member_user)
|
|
|
+ response = self.client.get(self.url + "?id=" + download_id)
|
|
|
assert response.status_code == 403, response.content
|
|
|
|
|
|
# Download as a user with no permissions
|
|
|
user_no_permission = self.create_user("baz@localhost", username="baz")
|
|
|
self.login_as(user=user_no_permission)
|
|
|
- response = self.client.get(url + "?id=" + download_id)
|
|
|
+ response = self.client.get(self.url + "?id=" + download_id)
|
|
|
assert response.status_code == 403, response.content
|
|
|
|
|
|
# Try to delete with no permissions
|
|
|
- response = self.client.delete(url + "?id=" + download_id)
|
|
|
+ response = self.client.delete(self.url + "?id=" + download_id)
|
|
|
assert response.status_code == 403, response.content
|
|
|
|
|
|
# Login again with permissions
|
|
|
self.login_as(user=self.user)
|
|
|
|
|
|
- response = self.client.delete(url + "?id=888")
|
|
|
+ response = self.client.delete(self.url + "?id=888")
|
|
|
assert response.status_code == 404, response.content
|
|
|
-
|
|
|
assert ProjectDebugFile.objects.count() == 1
|
|
|
|
|
|
- response = self.client.delete(url + "?id=" + download_id)
|
|
|
+ response = self.client.delete(self.url + "?id=" + download_id)
|
|
|
assert response.status_code == 204, response.content
|
|
|
-
|
|
|
assert ProjectDebugFile.objects.count() == 0
|
|
|
|
|
|
- def test_dsyms_search(self):
|
|
|
- project = self.create_project(name="foo")
|
|
|
-
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
-
|
|
|
- self.login_as(user=self.user)
|
|
|
-
|
|
|
- for i in range(25):
|
|
|
- last_uuid = str(uuid4())
|
|
|
- self._upload_proguard(url, last_uuid)
|
|
|
-
|
|
|
- # Test max 20 per page
|
|
|
- response = self.client.get(url)
|
|
|
- assert response.status_code == 200, response.content
|
|
|
- dsyms = response.data
|
|
|
- assert len(dsyms) == 20
|
|
|
-
|
|
|
- # Test should return last
|
|
|
- response = self.client.get(url + "?query=" + last_uuid)
|
|
|
- assert response.status_code == 200, response.content
|
|
|
- dsyms = response.data
|
|
|
- assert len(dsyms) == 1
|
|
|
-
|
|
|
- response = self.client.get(url + "?query=proguard")
|
|
|
- assert response.status_code == 200, response.content
|
|
|
- dsyms = response.data
|
|
|
- assert len(dsyms) == 20
|
|
|
-
|
|
|
- def test_dsyms_delete_as_team_admin(self):
|
|
|
- project = self.create_project(name="foo")
|
|
|
- self.login_as(user=self.user)
|
|
|
-
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
- response = self._upload_proguard(url, PROGUARD_UUID)
|
|
|
-
|
|
|
+ def test_dsyms_as_team_admin(self):
|
|
|
+ response = self._upload_proguard(self.url, PROGUARD_UUID)
|
|
|
assert response.status_code == 201
|
|
|
assert len(response.data) == 1
|
|
|
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-associate-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
response = self.client.post(
|
|
|
- url,
|
|
|
+ self.url,
|
|
|
{
|
|
|
"checksums": ["e6d3c5185dac63eddfdc1a5edfffa32d46103b44"],
|
|
|
"platform": "android",
|
|
@@ -347,14 +202,7 @@ class DebugFilesUploadTest(APITestCase):
|
|
|
format="json",
|
|
|
)
|
|
|
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
- response = self.client.get(url)
|
|
|
+ response = self.client.get(self.url)
|
|
|
download_id = response.data[0]["id"]
|
|
|
|
|
|
assert response.status_code == 200
|
|
@@ -364,12 +212,12 @@ class DebugFilesUploadTest(APITestCase):
|
|
|
|
|
|
self.create_member(
|
|
|
user=team_admin,
|
|
|
- organization=project.organization,
|
|
|
+ organization=self.organization,
|
|
|
role="member",
|
|
|
)
|
|
|
self.create_member(
|
|
|
user=team_admin_without_access,
|
|
|
- organization=project.organization,
|
|
|
+ organization=self.organization,
|
|
|
role="member",
|
|
|
)
|
|
|
self.create_team_membership(user=team_admin, team=self.team, role="admin")
|
|
@@ -377,61 +225,136 @@ class DebugFilesUploadTest(APITestCase):
|
|
|
user=team_admin_without_access, team=self.create_team(), role="admin"
|
|
|
)
|
|
|
|
|
|
- # Team admin without project access can't delete
|
|
|
self.login_as(team_admin_without_access)
|
|
|
- response = self.client.delete(url + "?id=" + download_id)
|
|
|
+ # Team admin without project access can't download
|
|
|
+ response = self.client.get(self.url + "?id=" + download_id)
|
|
|
+ assert response.status_code == 403, response.content
|
|
|
|
|
|
+ # Team admin without project access can't delete
|
|
|
+ response = self.client.delete(self.url + "?id=" + download_id)
|
|
|
assert response.status_code == 404, response.content
|
|
|
assert ProjectDebugFile.objects.count() == 1
|
|
|
|
|
|
- # Team admin with project access can delete
|
|
|
self.login_as(team_admin)
|
|
|
- response = self.client.delete(url + "?id=" + download_id)
|
|
|
+ # Team admin with project access can download
|
|
|
+ response = self.client.get(self.url + "?id=" + download_id)
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
+ assert response.get("Content-Type") == "application/octet-stream"
|
|
|
+ close_streaming_response(response)
|
|
|
|
|
|
+ # Team admin with project access can delete
|
|
|
+ response = self.client.delete(self.url + "?id=" + download_id)
|
|
|
assert response.status_code == 204, response.content
|
|
|
assert ProjectDebugFile.objects.count() == 0
|
|
|
|
|
|
- def test_source_maps(self):
|
|
|
- project = self.create_project(name="foo")
|
|
|
|
|
|
- release = Release.objects.create(organization_id=project.organization_id, version="1")
|
|
|
- release2 = Release.objects.create(organization_id=project.organization_id, version="2")
|
|
|
- release3 = Release.objects.create(organization_id=project.organization_id, version="3")
|
|
|
- release.add_project(project)
|
|
|
- release2.add_project(project)
|
|
|
- release3.add_project(project)
|
|
|
+class AssociateDebugFilesTest(DebugFilesTestCases):
|
|
|
+ def setUp(self):
|
|
|
+ super().setUp()
|
|
|
+ self.associate_url = reverse(
|
|
|
+ "sentry-api-0-associate-dsym-files",
|
|
|
+ kwargs={
|
|
|
+ "organization_id_or_slug": self.organization.slug,
|
|
|
+ "project_id_or_slug": self.project.slug,
|
|
|
+ },
|
|
|
+ )
|
|
|
+
|
|
|
+ def test_associate_proguard_dsym(self):
|
|
|
+ response = self._upload_proguard(self.url, PROGUARD_UUID)
|
|
|
+ assert response.status_code == 201, response.content
|
|
|
+ assert len(response.data) == 1
|
|
|
+ assert response.data[0]["headers"] == {"Content-Type": "text/x-proguard+plain"}
|
|
|
+ assert response.data[0]["sha1"] == "e6d3c5185dac63eddfdc1a5edfffa32d46103b44"
|
|
|
+ assert response.data[0]["uuid"] == PROGUARD_UUID
|
|
|
+ assert response.data[0]["objectName"] == "proguard-mapping"
|
|
|
+ assert response.data[0]["cpuName"] == "any"
|
|
|
+ assert response.data[0]["symbolType"] == "proguard"
|
|
|
+
|
|
|
+ response = self.client.post(
|
|
|
+ self.associate_url,
|
|
|
+ {
|
|
|
+ "checksums": ["e6d3c5185dac63eddfdc1a5edfffa32d46103b44"],
|
|
|
+ "platform": "android",
|
|
|
+ "name": "MyApp",
|
|
|
+ "appId": "com.example.myapp",
|
|
|
+ "version": "1.0",
|
|
|
+ "build": "1",
|
|
|
+ },
|
|
|
+ format="json",
|
|
|
+ )
|
|
|
+
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
+ assert "associatedDsymFiles" in response.data
|
|
|
+ assert response.data["associatedDsymFiles"] == []
|
|
|
+
|
|
|
+ def test_associate_proguard_dsym_no_build(self):
|
|
|
+ response = self._upload_proguard(self.url, PROGUARD_UUID)
|
|
|
+ assert response.status_code == 201, response.content
|
|
|
+ assert len(response.data) == 1
|
|
|
+ assert response.data[0]["headers"] == {"Content-Type": "text/x-proguard+plain"}
|
|
|
+ assert response.data[0]["sha1"] == "e6d3c5185dac63eddfdc1a5edfffa32d46103b44"
|
|
|
+ assert response.data[0]["uuid"] == PROGUARD_UUID
|
|
|
+ assert response.data[0]["objectName"] == "proguard-mapping"
|
|
|
+ assert response.data[0]["cpuName"] == "any"
|
|
|
+ assert response.data[0]["symbolType"] == "proguard"
|
|
|
+
|
|
|
+ response = self.client.post(
|
|
|
+ self.associate_url,
|
|
|
+ {
|
|
|
+ "checksums": ["e6d3c5185dac63eddfdc1a5edfffa32d46103b44"],
|
|
|
+ "platform": "android",
|
|
|
+ "name": "MyApp",
|
|
|
+ "appId": "com.example.myapp",
|
|
|
+ "version": "1.0",
|
|
|
+ },
|
|
|
+ format="json",
|
|
|
+ )
|
|
|
+
|
|
|
+ assert response.status_code == 200, response.content
|
|
|
+ assert "associatedDsymFiles" in response.data
|
|
|
+ assert response.data["associatedDsymFiles"] == []
|
|
|
+
|
|
|
+
|
|
|
+class SourceMapsEndpointTest(APITestCase):
|
|
|
+ def setUp(self):
|
|
|
+ self.url = reverse(
|
|
|
+ "sentry-api-0-source-maps",
|
|
|
+ kwargs={
|
|
|
+ "organization_id_or_slug": self.organization.slug,
|
|
|
+ "project_id_or_slug": self.project.slug,
|
|
|
+ },
|
|
|
+ )
|
|
|
+ self.login_as(user=self.user)
|
|
|
+
|
|
|
+ def test_source_maps(self):
|
|
|
+ release = Release.objects.create(organization_id=self.project.organization_id, version="1")
|
|
|
+ release2 = Release.objects.create(organization_id=self.project.organization_id, version="2")
|
|
|
+ release3 = Release.objects.create(organization_id=self.project.organization_id, version="3")
|
|
|
+ release.add_project(self.project)
|
|
|
+ release2.add_project(self.project)
|
|
|
+ release3.add_project(self.project)
|
|
|
|
|
|
ReleaseFile.objects.create(
|
|
|
- organization_id=project.organization_id,
|
|
|
+ organization_id=self.project.organization_id,
|
|
|
release_id=release.id,
|
|
|
file=File.objects.create(name="application.js", type="release.file"),
|
|
|
name="http://example.com/application.js",
|
|
|
)
|
|
|
ReleaseFile.objects.create(
|
|
|
- organization_id=project.organization_id,
|
|
|
+ organization_id=self.project.organization_id,
|
|
|
release_id=release.id,
|
|
|
file=File.objects.create(name="application2.js", type="release.file"),
|
|
|
name="http://example.com/application2.js",
|
|
|
)
|
|
|
ReleaseFile.objects.create(
|
|
|
- organization_id=project.organization_id,
|
|
|
+ organization_id=self.project.organization_id,
|
|
|
release_id=release2.id,
|
|
|
file=File.objects.create(name="application3.js", type="release.file"),
|
|
|
name="http://example.com/application2.js",
|
|
|
artifact_count=0,
|
|
|
)
|
|
|
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-source-maps",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
-
|
|
|
- self.login_as(user=self.user)
|
|
|
-
|
|
|
- response = self.client.get(url)
|
|
|
+ response = self.client.get(self.url)
|
|
|
|
|
|
assert response.status_code == 200, response.content
|
|
|
assert len(response.data) == 3
|
|
@@ -446,141 +369,64 @@ class DebugFilesUploadTest(APITestCase):
|
|
|
assert response.data[2]["fileCount"] == 2
|
|
|
|
|
|
def test_source_maps_sorting(self):
|
|
|
- project = self.create_project(name="foo")
|
|
|
-
|
|
|
- release = Release.objects.create(organization_id=project.organization_id, version="1")
|
|
|
- release2 = Release.objects.create(organization_id=project.organization_id, version="2")
|
|
|
- release.add_project(project)
|
|
|
- release2.add_project(project)
|
|
|
+ release = Release.objects.create(organization_id=self.project.organization_id, version="1")
|
|
|
+ release2 = Release.objects.create(organization_id=self.project.organization_id, version="2")
|
|
|
+ release.add_project(self.project)
|
|
|
+ release2.add_project(self.project)
|
|
|
|
|
|
ReleaseFile.objects.create(
|
|
|
- organization_id=project.organization_id,
|
|
|
+ organization_id=self.project.organization_id,
|
|
|
release_id=release.id,
|
|
|
file=File.objects.create(name="application.js", type="release.file"),
|
|
|
name="http://example.com/application.js",
|
|
|
)
|
|
|
ReleaseFile.objects.create(
|
|
|
- organization_id=project.organization_id,
|
|
|
+ organization_id=self.project.organization_id,
|
|
|
release_id=release.id,
|
|
|
file=File.objects.create(name="application2.js", type="release.file"),
|
|
|
name="http://example.com/application2.js",
|
|
|
)
|
|
|
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-source-maps",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
-
|
|
|
release_ids = [release.id, release2.id]
|
|
|
|
|
|
- self.login_as(user=self.user)
|
|
|
- response = self.client.get(url + "?sortBy=date_added")
|
|
|
+ response = self.client.get(self.url + "?sortBy=date_added")
|
|
|
assert response.status_code == 200, response.content
|
|
|
assert list(map(lambda value: value["id"], response.data)) == release_ids
|
|
|
|
|
|
- response = self.client.get(url + "?sortBy=-date_added")
|
|
|
+ response = self.client.get(self.url + "?sortBy=-date_added")
|
|
|
assert response.status_code == 200, response.content
|
|
|
assert list(map(lambda value: value["id"], response.data)) == release_ids[::-1]
|
|
|
|
|
|
- response = self.client.get(url + "?sortBy=invalid")
|
|
|
+ response = self.client.get(self.url + "?sortBy=invalid")
|
|
|
assert response.status_code == 400
|
|
|
assert response.data["error"] == "You can either sort via 'date_added' or '-date_added'"
|
|
|
|
|
|
def test_source_maps_delete_archive(self):
|
|
|
- project = self.create_project(name="foo")
|
|
|
-
|
|
|
- release = Release.objects.create(organization_id=project.organization_id, version="1", id=1)
|
|
|
- release.add_project(project)
|
|
|
+ release = Release.objects.create(
|
|
|
+ organization_id=self.project.organization_id, version="1", id=1
|
|
|
+ )
|
|
|
+ release.add_project(self.project)
|
|
|
|
|
|
ReleaseFile.objects.create(
|
|
|
- organization_id=project.organization_id,
|
|
|
+ organization_id=self.project.organization_id,
|
|
|
release_id=release.id,
|
|
|
file=File.objects.create(name="application.js", type="release.file"),
|
|
|
name="http://example.com/application.js",
|
|
|
)
|
|
|
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-source-maps",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
-
|
|
|
- self.login_as(user=self.user)
|
|
|
-
|
|
|
- response = self.client.delete(url + "?name=1")
|
|
|
+ response = self.client.delete(self.url + "?name=1")
|
|
|
assert response.status_code == 204
|
|
|
assert not ReleaseFile.objects.filter(release_id=release.id).exists()
|
|
|
|
|
|
def test_source_maps_release_archive(self):
|
|
|
- project = self.create_project(name="foo")
|
|
|
-
|
|
|
- release = Release.objects.create(organization_id=project.organization_id, version="1")
|
|
|
- release.add_project(project)
|
|
|
+ release = Release.objects.create(organization_id=self.project.organization_id, version="1")
|
|
|
+ release.add_project(self.project)
|
|
|
|
|
|
self.create_release_archive(release=release.version)
|
|
|
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-source-maps",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": project.organization.slug,
|
|
|
- "project_id_or_slug": project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
-
|
|
|
- self.login_as(user=self.user)
|
|
|
-
|
|
|
- response = self.client.get(url)
|
|
|
+ response = self.client.get(self.url)
|
|
|
|
|
|
assert response.status_code == 200, response.content
|
|
|
assert len(response.data) == 1
|
|
|
assert response.data[0]["name"] == str(release.version)
|
|
|
assert response.data[0]["fileCount"] == 2
|
|
|
-
|
|
|
- def test_access_control(self):
|
|
|
- # create a debug files such as proguard:
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": self.project.organization.slug,
|
|
|
- "project_id_or_slug": self.project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
- self.login_as(user=self.user)
|
|
|
-
|
|
|
- response = self._upload_proguard(url, PROGUARD_UUID)
|
|
|
-
|
|
|
- assert response.status_code == 201, response.content
|
|
|
- assert len(response.data) == 1
|
|
|
-
|
|
|
- response = self.client.get(url)
|
|
|
- assert response.status_code == 200, response.content
|
|
|
-
|
|
|
- (dsym,) = response.data
|
|
|
- download_id = dsym["id"]
|
|
|
-
|
|
|
- # `self.user` has access to these files
|
|
|
- response = self.client.get(f"{url}?id={download_id}")
|
|
|
- assert response.status_code == 200, response.content
|
|
|
- assert PROGUARD_SOURCE == b"".join(response.streaming_content)
|
|
|
-
|
|
|
- # with another user on a different org
|
|
|
- other_user = self.create_user()
|
|
|
- other_org = self.create_organization(name="other-org", owner=other_user)
|
|
|
- other_project = self.create_project(organization=other_org)
|
|
|
- url = reverse(
|
|
|
- "sentry-api-0-dsym-files",
|
|
|
- kwargs={
|
|
|
- "organization_id_or_slug": other_org.slug,
|
|
|
- "project_id_or_slug": other_project.slug,
|
|
|
- },
|
|
|
- )
|
|
|
- self.login_as(user=other_user)
|
|
|
-
|
|
|
- # accessing foreign files should not work
|
|
|
- response = self.client.get(f"{url}?id={download_id}")
|
|
|
- assert response.status_code == 404
|