Skip to content

Commit 1353939

Browse files
authored
fix(issues): inherit ShortIdLookupEndpoint from GroupEndpoint (#83502)
1 parent 8857e10 commit 1353939

File tree

7 files changed

+44
-36
lines changed

7 files changed

+44
-36
lines changed

api-docs/openapi.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
"/api/0/organizations/{organization_id_or_slug}/repos/{repo_id}/commits/": {
107107
"$ref": "paths/organizations/repo-commits.json"
108108
},
109-
"/api/0/organizations/{organization_id_or_slug}/shortids/{short_id}/": {
109+
"/api/0/organizations/{organization_id_or_slug}/shortids/{issue_id}/": {
110110
"$ref": "paths/organizations/shortid.json"
111111
},
112112
"/api/0/projects/": {

api-docs/paths/organizations/shortid.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"get": {
33
"tags": ["Organizations"],
4-
"description": "This resolves a short ID to the project slug and internal issue ID.",
4+
"description": "This resolves a short ID or internal issue ID to the project slug and group details.",
55
"operationId": "Resolve a Short ID",
66
"parameters": [
77
{
@@ -14,9 +14,9 @@
1414
}
1515
},
1616
{
17-
"name": "short_id",
17+
"name": "issue_id",
1818
"in": "path",
19-
"description": "The short ID to look up.",
19+
"description": "The short ID or issue ID to look up.",
2020
"required": true,
2121
"schema": {
2222
"type": "string"

src/sentry/api/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1286,7 +1286,7 @@ def create_group_urls(name_prefix: str) -> list[URLPattern | URLResolver]:
12861286
name="sentry-api-0-organization-dashboard-favorite",
12871287
),
12881288
re_path(
1289-
r"^(?P<organization_id_or_slug>[^\/]+)/shortids/(?P<short_id>[^\/]+)/$",
1289+
r"^(?P<organization_id_or_slug>[^\/]+)/shortids/(?P<issue_id>[^\/]+)/$",
12901290
ShortIdLookupEndpoint.as_view(),
12911291
name="sentry-api-0-short-id-lookup",
12921292
),

src/sentry/apidocs/api_publish_status_allowlist_dont_modify.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,6 @@
303303
"PUT",
304304
},
305305
"/api/0/organizations/{organization_id_or_slug}/dashboards/{dashboard_id}/visit/": {"POST"},
306-
"/api/0/organizations/{organization_id_or_slug}/shortids/{short_id}/": {"GET"},
307306
"/api/0/organizations/{organization_id_or_slug}/eventids/{event_id}/": {"GET"},
308307
"/api/0/organizations/{organization_id_or_slug}/data-scrubbing-selector-suggestions/": {"GET"},
309308
"/api/0/organizations/{organization_id_or_slug}/access-requests/": {"GET", "PUT"},

src/sentry/issues/endpoints/organization_shortid.py

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,31 @@
44
from sentry.api.api_owners import ApiOwner
55
from sentry.api.api_publish_status import ApiPublishStatus
66
from sentry.api.base import region_silo_endpoint
7-
from sentry.api.bases.organization import OrganizationEndpoint
8-
from sentry.api.exceptions import ResourceDoesNotExist
7+
from sentry.api.bases import GroupEndpoint
98
from sentry.api.serializers import serialize
109
from sentry.models.group import Group
11-
from sentry.models.organization import Organization
1210

1311

1412
@region_silo_endpoint
15-
class ShortIdLookupEndpoint(OrganizationEndpoint):
13+
class ShortIdLookupEndpoint(GroupEndpoint):
1614
owner = ApiOwner.ISSUES
1715
publish_status = {
18-
"GET": ApiPublishStatus.UNKNOWN,
16+
"GET": ApiPublishStatus.PRIVATE,
1917
}
2018

21-
def get(self, request: Request, organization: Organization, short_id: str) -> Response:
19+
def get(self, request: Request, group: Group) -> Response:
2220
"""
2321
Resolve a Short ID
2422
``````````````````
2523
26-
This resolves a short ID to the project slug and internal issue ID.
24+
This resolves a short ID or internal issue ID to the project slug and group details.
2725
28-
:pparam string organization_id_or_slug: the id or slug of the organization the
29-
short ID should be looked up in.
30-
:pparam string short_id: the short ID to look up.
26+
:pparam string issue_id: the short ID or issue ID to look up.
3127
:auth: required
3228
"""
33-
try:
34-
group = Group.objects.by_qualified_short_id(organization.id, short_id)
35-
except Group.DoesNotExist:
36-
raise ResourceDoesNotExist()
37-
3829
return Response(
3930
{
40-
"organizationSlug": organization.slug,
31+
"organizationSlug": group.project.organization.slug,
4132
"projectSlug": group.project.slug,
4233
"groupId": str(group.id),
4334
"group": serialize(group, request.user),

tests/apidocs/endpoints/organizations/test_shortid.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def setUp(self):
1212
"sentry-api-0-short-id-lookup",
1313
kwargs={
1414
"organization_id_or_slug": self.organization.slug,
15-
"short_id": group.qualified_short_id,
15+
"issue_id": group.qualified_short_id,
1616
},
1717
)
1818

tests/sentry/issues/endpoints/test_organization_shortid.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,38 @@
77

88

99
class ShortIdLookupEndpointTest(APITestCase):
10-
def test_simple(self) -> None:
11-
org = self.create_organization(owner=self.user)
12-
project = self.create_project(organization=org)
13-
group = self.create_group(project=project, short_id=project.next_short_id())
14-
15-
self.login_as(user=self.user)
16-
url = reverse(
10+
def setUp(self) -> None:
11+
self.group = self.create_group(project=self.project, short_id=self.project.next_short_id())
12+
self.url = reverse(
1713
"sentry-api-0-short-id-lookup",
18-
kwargs={"organization_id_or_slug": org.slug, "short_id": group.qualified_short_id},
14+
kwargs={
15+
"organization_id_or_slug": self.organization.slug,
16+
"issue_id": self.group.qualified_short_id,
17+
},
1918
)
20-
response = self.client.get(url, format="json")
19+
20+
def test_simple(self) -> None:
21+
self.login_as(user=self.user)
22+
response = self.client.get(self.url, format="json")
2123

2224
assert response.status_code == 200, response.content
23-
assert response.data["organizationSlug"] == org.slug
24-
assert response.data["projectSlug"] == project.slug
25-
assert response.data["groupId"] == str(group.id)
26-
assert response.data["group"]["id"] == str(group.id)
25+
assert response.data["organizationSlug"] == self.organization.slug
26+
assert response.data["projectSlug"] == self.project.slug
27+
assert response.data["groupId"] == str(self.group.id)
28+
assert response.data["group"]["id"] == str(self.group.id)
29+
30+
def test_access_non_member_project(self) -> None:
31+
# disable Open Membership
32+
self.organization.flags.allow_joinleave = False
33+
self.organization.save()
34+
35+
# user has no access to the first project
36+
user_no_team = self.create_user(is_superuser=False)
37+
self.create_member(
38+
user=user_no_team, organization=self.organization, role="member", teams=[]
39+
)
40+
self.login_as(user_no_team)
41+
42+
response = self.client.get(self.url, format="json")
43+
assert response.status_code == 403, response.content
44+
assert response.data["detail"] == "You do not have permission to perform this action."

0 commit comments

Comments
 (0)