Skip to content

Commit

Permalink
fix(issues): inherit ShortIdLookupEndpoint from GroupEndpoint (#83502)
Browse files Browse the repository at this point in the history
  • Loading branch information
oioki authored Jan 15, 2025
1 parent 8857e10 commit 1353939
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 36 deletions.
2 changes: 1 addition & 1 deletion api-docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
"/api/0/organizations/{organization_id_or_slug}/repos/{repo_id}/commits/": {
"$ref": "paths/organizations/repo-commits.json"
},
"/api/0/organizations/{organization_id_or_slug}/shortids/{short_id}/": {
"/api/0/organizations/{organization_id_or_slug}/shortids/{issue_id}/": {
"$ref": "paths/organizations/shortid.json"
},
"/api/0/projects/": {
Expand Down
6 changes: 3 additions & 3 deletions api-docs/paths/organizations/shortid.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"get": {
"tags": ["Organizations"],
"description": "This resolves a short ID to the project slug and internal issue ID.",
"description": "This resolves a short ID or internal issue ID to the project slug and group details.",
"operationId": "Resolve a Short ID",
"parameters": [
{
Expand All @@ -14,9 +14,9 @@
}
},
{
"name": "short_id",
"name": "issue_id",
"in": "path",
"description": "The short ID to look up.",
"description": "The short ID or issue ID to look up.",
"required": true,
"schema": {
"type": "string"
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,7 @@ def create_group_urls(name_prefix: str) -> list[URLPattern | URLResolver]:
name="sentry-api-0-organization-dashboard-favorite",
),
re_path(
r"^(?P<organization_id_or_slug>[^\/]+)/shortids/(?P<short_id>[^\/]+)/$",
r"^(?P<organization_id_or_slug>[^\/]+)/shortids/(?P<issue_id>[^\/]+)/$",
ShortIdLookupEndpoint.as_view(),
name="sentry-api-0-short-id-lookup",
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,6 @@
"PUT",
},
"/api/0/organizations/{organization_id_or_slug}/dashboards/{dashboard_id}/visit/": {"POST"},
"/api/0/organizations/{organization_id_or_slug}/shortids/{short_id}/": {"GET"},
"/api/0/organizations/{organization_id_or_slug}/eventids/{event_id}/": {"GET"},
"/api/0/organizations/{organization_id_or_slug}/data-scrubbing-selector-suggestions/": {"GET"},
"/api/0/organizations/{organization_id_or_slug}/access-requests/": {"GET", "PUT"},
Expand Down
23 changes: 7 additions & 16 deletions src/sentry/issues/endpoints/organization_shortid.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,31 @@
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import region_silo_endpoint
from sentry.api.bases.organization import OrganizationEndpoint
from sentry.api.exceptions import ResourceDoesNotExist
from sentry.api.bases import GroupEndpoint
from sentry.api.serializers import serialize
from sentry.models.group import Group
from sentry.models.organization import Organization


@region_silo_endpoint
class ShortIdLookupEndpoint(OrganizationEndpoint):
class ShortIdLookupEndpoint(GroupEndpoint):
owner = ApiOwner.ISSUES
publish_status = {
"GET": ApiPublishStatus.UNKNOWN,
"GET": ApiPublishStatus.PRIVATE,
}

def get(self, request: Request, organization: Organization, short_id: str) -> Response:
def get(self, request: Request, group: Group) -> Response:
"""
Resolve a Short ID
``````````````````
This resolves a short ID to the project slug and internal issue ID.
This resolves a short ID or internal issue ID to the project slug and group details.
:pparam string organization_id_or_slug: the id or slug of the organization the
short ID should be looked up in.
:pparam string short_id: the short ID to look up.
:pparam string issue_id: the short ID or issue ID to look up.
:auth: required
"""
try:
group = Group.objects.by_qualified_short_id(organization.id, short_id)
except Group.DoesNotExist:
raise ResourceDoesNotExist()

return Response(
{
"organizationSlug": organization.slug,
"organizationSlug": group.project.organization.slug,
"projectSlug": group.project.slug,
"groupId": str(group.id),
"group": serialize(group, request.user),
Expand Down
2 changes: 1 addition & 1 deletion tests/apidocs/endpoints/organizations/test_shortid.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def setUp(self):
"sentry-api-0-short-id-lookup",
kwargs={
"organization_id_or_slug": self.organization.slug,
"short_id": group.qualified_short_id,
"issue_id": group.qualified_short_id,
},
)

Expand Down
44 changes: 31 additions & 13 deletions tests/sentry/issues/endpoints/test_organization_shortid.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,38 @@


class ShortIdLookupEndpointTest(APITestCase):
def test_simple(self) -> None:
org = self.create_organization(owner=self.user)
project = self.create_project(organization=org)
group = self.create_group(project=project, short_id=project.next_short_id())

self.login_as(user=self.user)
url = reverse(
def setUp(self) -> None:
self.group = self.create_group(project=self.project, short_id=self.project.next_short_id())
self.url = reverse(
"sentry-api-0-short-id-lookup",
kwargs={"organization_id_or_slug": org.slug, "short_id": group.qualified_short_id},
kwargs={
"organization_id_or_slug": self.organization.slug,
"issue_id": self.group.qualified_short_id,
},
)
response = self.client.get(url, format="json")

def test_simple(self) -> None:
self.login_as(user=self.user)
response = self.client.get(self.url, format="json")

assert response.status_code == 200, response.content
assert response.data["organizationSlug"] == org.slug
assert response.data["projectSlug"] == project.slug
assert response.data["groupId"] == str(group.id)
assert response.data["group"]["id"] == str(group.id)
assert response.data["organizationSlug"] == self.organization.slug
assert response.data["projectSlug"] == self.project.slug
assert response.data["groupId"] == str(self.group.id)
assert response.data["group"]["id"] == str(self.group.id)

def test_access_non_member_project(self) -> None:
# disable Open Membership
self.organization.flags.allow_joinleave = False
self.organization.save()

# user has no access to the first project
user_no_team = self.create_user(is_superuser=False)
self.create_member(
user=user_no_team, organization=self.organization, role="member", teams=[]
)
self.login_as(user_no_team)

response = self.client.get(self.url, format="json")
assert response.status_code == 403, response.content
assert response.data["detail"] == "You do not have permission to perform this action."

0 comments on commit 1353939

Please sign in to comment.