Skip to content

Commit ee2d877

Browse files
feat(api-idorslug): Updated Subset of Orgmember and Integration Endpoints to use organization_id_or_slug (#70567)
A subset of changes from #70081! --------- Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
1 parent 593978b commit ee2d877

File tree

17 files changed

+128
-96
lines changed

17 files changed

+128
-96
lines changed

pyproject.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,12 @@ ignore_missing_imports = true
120120
module = [
121121
"sentry.api.base",
122122
"sentry.api.bases.external_actor",
123-
"sentry.api.bases.incident",
124123
"sentry.api.bases.integration",
125124
"sentry.api.bases.organization_events",
126125
"sentry.api.bases.organization_request_change",
127126
"sentry.api.bases.organizationmember",
128127
"sentry.api.bases.project",
129128
"sentry.api.bases.project_request_change",
130-
"sentry.api.bases.rule",
131129
"sentry.api.bases.sentryapps",
132130
"sentry.api.bases.team",
133131
"sentry.api.endpoints.accept_organization_invite",
@@ -152,11 +150,8 @@ module = [
152150
"sentry.api.endpoints.integrations.sentry_apps.requests",
153151
"sentry.api.endpoints.integrations.sentry_apps.stats.details",
154152
"sentry.api.endpoints.internal.mail",
155-
"sentry.api.endpoints.notifications.notification_actions_details",
156153
"sentry.api.endpoints.organization_code_mapping_codeowners",
157-
"sentry.api.endpoints.organization_code_mapping_details",
158154
"sentry.api.endpoints.organization_code_mappings",
159-
"sentry.api.endpoints.organization_dashboard_details",
160155
"sentry.api.endpoints.organization_details",
161156
"sentry.api.endpoints.organization_events",
162157
"sentry.api.endpoints.organization_events_facets",

src/sentry/api/bases/organization.py

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -242,30 +242,42 @@ class ControlSiloOrganizationEndpoint(Endpoint):
242242
def convert_args(
243243
self,
244244
request: Request,
245-
organization_slug: str | int | None = None,
246245
*args: Any,
247246
**kwargs: Any,
248247
) -> tuple[tuple[Any, ...], dict[str, Any]]:
248+
organization_id_or_slug: int | str | None = None
249+
if args and args[0] is not None:
250+
organization_id_or_slug = args[0]
251+
# Required so it behaves like the original convert_args, where organization_id_or_slug was another parameter
252+
# TODO: Remove this once we remove the old `organization_slug` parameter from getsentry
253+
args = args[1:]
254+
else:
255+
organization_id_or_slug = kwargs.pop("organization_id_or_slug", None) or kwargs.pop(
256+
"organization_slug", None
257+
)
258+
259+
if not organization_id_or_slug:
260+
raise ResourceDoesNotExist
261+
249262
if not subdomain_is_region(request):
250263
subdomain = getattr(request, "subdomain", None)
251-
if subdomain is not None and subdomain != organization_slug:
264+
if subdomain is not None and subdomain != organization_id_or_slug:
252265
raise ResourceDoesNotExist
253266

254-
if not organization_slug:
255-
raise ResourceDoesNotExist
256-
257267
if (
258-
id_or_slug_path_params_enabled(self.convert_args.__qualname__, str(organization_slug))
259-
and str(organization_slug).isdecimal()
268+
id_or_slug_path_params_enabled(
269+
self.convert_args.__qualname__, str(organization_id_or_slug)
270+
)
271+
and str(organization_id_or_slug).isdecimal()
260272
):
261273
# It is ok that `get_organization_by_id` doesn't check for visibility as we
262274
# don't check the visibility in `get_organization_by_slug` either (only_active=False).
263275
organization_context = organization_service.get_organization_by_id(
264-
id=int(organization_slug), user_id=request.user.id
276+
id=int(organization_id_or_slug), user_id=request.user.id
265277
)
266278
else:
267279
organization_context = organization_service.get_organization_by_slug(
268-
slug=str(organization_slug), only_visible=False, user_id=request.user.id
280+
slug=str(organization_id_or_slug), only_visible=False, user_id=request.user.id
269281
)
270282
if organization_context is None:
271283
raise ResourceDoesNotExist
@@ -536,32 +548,42 @@ def get_filter_params(
536548
def convert_args(
537549
self,
538550
request: Request,
539-
organization_slug: str | int | None = None,
540551
*args: Any,
541552
**kwargs: Any,
542553
) -> tuple[tuple[Any, ...], dict[str, Any]]:
543554
"""
544-
We temporarily allow the organization_slug to be an integer as it actually can be both slug or id
555+
We temporarily allow the organization_id_or_slug to be an integer as it actually can be both slug or id
545556
Eventually, we will rename this method to organization_id_or_slug
546557
"""
558+
organization_id_or_slug: int | str | None = None
559+
if args and args[0] is not None:
560+
organization_id_or_slug = args[0]
561+
# Required so it behaves like the original convert_args, where organization_id_or_slug was another parameter
562+
# TODO: Remove this once we remove the old `organization_slug` parameter from getsentry
563+
args = args[1:]
564+
else:
565+
organization_id_or_slug = kwargs.pop("organization_id_or_slug", None) or kwargs.pop(
566+
"organization_slug", None
567+
)
568+
569+
if not organization_id_or_slug:
570+
raise ResourceDoesNotExist
571+
547572
if not subdomain_is_region(request):
548573
subdomain = getattr(request, "subdomain", None)
549-
if subdomain is not None and subdomain != organization_slug:
574+
if subdomain is not None and subdomain != organization_id_or_slug:
550575
raise ResourceDoesNotExist
551576

552-
if not organization_slug:
553-
raise ResourceDoesNotExist
554-
555577
try:
556578
if (
557579
id_or_slug_path_params_enabled(
558-
self.convert_args.__qualname__, str(organization_slug)
580+
self.convert_args.__qualname__, str(organization_id_or_slug)
559581
)
560-
and str(organization_slug).isdecimal()
582+
and str(organization_id_or_slug).isdecimal()
561583
):
562-
organization = Organization.objects.get_from_cache(id=organization_slug)
584+
organization = Organization.objects.get_from_cache(id=organization_id_or_slug)
563585
else:
564-
organization = Organization.objects.get_from_cache(slug=organization_slug)
586+
organization = Organization.objects.get_from_cache(slug=organization_id_or_slug)
565587
except Organization.DoesNotExist:
566588
raise ResourceDoesNotExist
567589

src/sentry/api/bases/organization_integrations.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ class RegionOrganizationIntegrationBaseEndpoint(RegionIntegrationEndpoint):
7575
def convert_args(
7676
self,
7777
request: Request,
78-
organization_slug: str | int | None = None,
78+
organization_id_or_slug: int | str | None = None,
7979
integration_id: str | None = None,
8080
*args: Any,
8181
**kwargs: Any,
8282
) -> tuple[tuple[Any, ...], dict[str, Any]]:
83-
args, kwargs = super().convert_args(request, organization_slug, *args, **kwargs)
83+
args, kwargs = super().convert_args(request, organization_id_or_slug, *args, **kwargs)
8484

8585
kwargs["integration_id"] = self.validate_integration_id(integration_id or "")
8686
return args, kwargs

src/sentry/api/bases/organizationmember.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ class OrganizationMemberEndpoint(OrganizationEndpoint):
5353
def convert_args(
5454
self,
5555
request: Request,
56-
organization_slug: int | str | None = None,
56+
organization_id_or_slug: str | int | None = None,
5757
member_id: str = "me",
5858
*args: Any,
5959
**kwargs: Any,
6060
) -> tuple[tuple[Any, ...], dict[str, Any]]:
61-
args, kwargs = super().convert_args(request, organization_slug, *args, **kwargs)
61+
args, kwargs = super().convert_args(request, organization_id_or_slug, *args, **kwargs)
6262

6363
serializer = MemberSerializer(data={"id": member_id})
6464
if serializer.is_valid():

src/sentry/api/bases/project.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,19 @@ class ProjectEndpoint(Endpoint):
111111
def convert_args(
112112
self,
113113
request: Request,
114-
organization_slug: str | int,
115114
*args,
116115
**kwargs,
117116
):
117+
if args and args[0] is not None:
118+
organization_id_or_slug: int | str = args[0]
119+
# Required so it behaves like the original convert_args, where organization_id_or_slug was another parameter
120+
# TODO: Remove this once we remove the old `organization_slug` parameter from getsentry
121+
args = args[1:]
122+
else:
123+
organization_id_or_slug = kwargs.pop("organization_id_or_slug", None) or kwargs.pop(
124+
"organization_slug"
125+
)
126+
118127
if args and args[0] is not None:
119128
project_id_or_slug: int | str = args[0]
120129
# Required so it behaves like the original convert_args, where project_id_or_slug was another parameter
@@ -125,11 +134,11 @@ def convert_args(
125134
)
126135
try:
127136
if id_or_slug_path_params_enabled(
128-
self.convert_args.__qualname__, str(organization_slug)
137+
self.convert_args.__qualname__, str(organization_id_or_slug)
129138
):
130139
project = (
131140
Project.objects.filter(
132-
organization__slug__id_or_slug=organization_slug,
141+
organization__slug__id_or_slug=organization_id_or_slug,
133142
slug__id_or_slug=project_id_or_slug,
134143
)
135144
.select_related("organization")
@@ -139,7 +148,7 @@ def convert_args(
139148
else:
140149
project = (
141150
Project.objects.filter(
142-
organization__slug=organization_slug, slug=project_id_or_slug
151+
organization__slug=organization_id_or_slug, slug=project_id_or_slug
143152
)
144153
.select_related("organization")
145154
.prefetch_related("teams")
@@ -151,24 +160,24 @@ def convert_args(
151160
# This will only happen if the passed in project_id_or_slug is a slug and not an id
152161
redirect = ProjectRedirect.objects.select_related("project")
153162
if id_or_slug_path_params_enabled(
154-
self.convert_args.__qualname__, str(organization_slug)
163+
self.convert_args.__qualname__, str(organization_id_or_slug)
155164
):
156165
redirect = redirect.get(
157-
organization__slug__id_or_slug=organization_slug,
166+
organization__slug__id_or_slug=organization_id_or_slug,
158167
redirect_slug=project_id_or_slug,
159168
)
160169
else:
161170
redirect = redirect.get(
162-
organization__slug=organization_slug, redirect_slug=project_id_or_slug
171+
organization__slug=organization_id_or_slug, redirect_slug=project_id_or_slug
163172
)
164173
# Without object permissions don't reveal the rename
165174
self.check_object_permissions(request, redirect.project)
166175

167176
# get full path so that we keep query strings
168177
requested_url = request.get_full_path()
169178
new_url = requested_url.replace(
170-
f"projects/{organization_slug}/{project_id_or_slug}/",
171-
f"projects/{organization_slug}/{redirect.project.slug}/",
179+
f"projects/{organization_id_or_slug}/{project_id_or_slug}/",
180+
f"projects/{organization_id_or_slug}/{redirect.project.slug}/",
172181
)
173182

174183
# Resource was moved/renamed if the requested url is different than the new url

src/sentry/api/endpoints/accept_organization_invite.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def get_invite_state(
8585
if (
8686
id_or_slug_path_params_enabled(
8787
convert_args_class=AcceptOrganizationInvite,
88-
organization_slug=str(organization_id_or_slug),
88+
organization_id_or_slug=str(organization_id_or_slug),
8989
)
9090
and str(organization_id_or_slug).isdecimal()
9191
):
@@ -127,12 +127,12 @@ def get(
127127
request: Request,
128128
member_id: int,
129129
token: str,
130-
organization_slug: int | str | None = None,
130+
organization_id_or_slug: int | str | None = None,
131131
) -> Response:
132132

133133
invite_context = get_invite_state(
134134
member_id=int(member_id),
135-
organization_id_or_slug=organization_slug,
135+
organization_id_or_slug=organization_id_or_slug,
136136
user_id=request.user.id,
137137
request=request,
138138
)
@@ -222,11 +222,15 @@ def get(
222222
return response
223223

224224
def post(
225-
self, request: Request, member_id: int, token: str, organization_slug: str | None = None
225+
self,
226+
request: Request,
227+
member_id: int,
228+
token: str,
229+
organization_id_or_slug: int | str | None = None,
226230
) -> Response:
227231
invite_context = get_invite_state(
228232
member_id=int(member_id),
229-
organization_id_or_slug=organization_slug,
233+
organization_id_or_slug=organization_id_or_slug,
230234
user_id=request.user.id,
231235
request=request,
232236
)

src/sentry/api/endpoints/codeowners/details.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ class ProjectCodeOwnersDetailsEndpoint(ProjectEndpoint, ProjectCodeOwnersMixin):
3535
def convert_args(
3636
self,
3737
request: Request,
38-
organization_slug: str | int,
38+
organization_id_or_slug: int | str,
3939
project_id_or_slug: int | str,
4040
codeowners_id: str,
4141
*args: Any,
4242
**kwargs: Any,
4343
) -> tuple[Any, Any]:
4444
args, kwargs = super().convert_args(
45-
request, organization_slug, project_id_or_slug, *args, **kwargs
45+
request, organization_id_or_slug, project_id_or_slug, *args, **kwargs
4646
)
4747
try:
4848
kwargs["codeowners"] = ProjectCodeOwners.objects.get(

src/sentry/api/endpoints/codeowners/external_actor/user_details.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class ExternalUserDetailsEndpoint(OrganizationEndpoint, ExternalActorEndpointMix
2727
}
2828
owner = ApiOwner.ENTERPRISE
2929

30-
def convert_args( # type: ignore[override]
30+
def convert_args(
3131
self,
3232
request: Request,
3333
organization_slug: str,

src/sentry/api/endpoints/organization_event_details.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,19 @@ class OrganizationEventDetailsEndpoint(OrganizationEventsEndpointBase):
9191
def convert_args(
9292
self,
9393
request: Request,
94-
organization_slug: str | int | None = None,
94+
organization_id_or_slug: int | str | None = None,
9595
*args: Any,
9696
**kwargs: Any,
9797
) -> tuple[tuple[Any, ...], dict[str, Any]]:
98-
args, kwargs = super().convert_args(request, organization_slug, *args, **kwargs)
98+
args, kwargs = super().convert_args(request, organization_id_or_slug, *args, **kwargs)
9999

100100
organization = kwargs["organization"]
101101
project_id_or_slug = kwargs.pop("project_id_or_slug")
102102

103103
try:
104104
if id_or_slug_path_params_enabled(
105105
convert_args_class=self.convert_args.__qualname__,
106-
organization_slug=organization.slug,
106+
organization_id_or_slug=organization.slug,
107107
):
108108
project = Project.objects.get(
109109
slug__id_or_slug=project_id_or_slug,

src/sentry/api/endpoints/organization_member/details.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def _get_member(
113113
@extend_schema(
114114
operation_id="Retrieve an Organization Member",
115115
parameters=[
116-
GlobalParams.ORG_SLUG,
116+
GlobalParams.ORG_ID_OR_SLUG,
117117
GlobalParams.member_id("The ID of the organization member."),
118118
],
119119
responses={
@@ -146,7 +146,7 @@ def get(
146146
@extend_schema(
147147
operation_id="Update an Organization Member's Roles",
148148
parameters=[
149-
GlobalParams.ORG_SLUG,
149+
GlobalParams.ORG_ID_OR_SLUG,
150150
GlobalParams.member_id("The ID of the member to update."),
151151
],
152152
request=inline_serializer(
@@ -357,7 +357,7 @@ def _change_org_role(member: OrganizationMember, role: str) -> None:
357357
@extend_schema(
358358
operation_id="Delete an Organization Member",
359359
parameters=[
360-
GlobalParams.ORG_SLUG,
360+
GlobalParams.ORG_ID_OR_SLUG,
361361
GlobalParams.member_id("The ID of the member to delete."),
362362
],
363363
responses={

0 commit comments

Comments
 (0)