Skip to content

Commit 993bddb

Browse files
ref: fix types for group_integration_details (#92026)
<!-- Describe your PR here. -->
1 parent 0a1dadf commit 993bddb

File tree

2 files changed

+38
-15
lines changed

2 files changed

+38
-15
lines changed

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ ignore_missing_imports = true
112112
# - python3 -m tools.mypy_helpers.find_easiest_modules
113113
[[tool.mypy.overrides]]
114114
module = [
115-
"sentry.api.endpoints.group_integration_details",
116115
"sentry.api.endpoints.organization_events_meta",
117116
"sentry.api.endpoints.organization_events_spans_performance",
118117
"sentry.api.endpoints.organization_releases",

src/sentry/api/endpoints/group_integration_details.py

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
from __future__ import annotations
2+
13
from collections.abc import Mapping, MutableMapping
24
from typing import Any
35

6+
from django.contrib.auth.models import AnonymousUser
47
from django.db import IntegrityError, router, transaction
58
from rest_framework.request import Request
69
from rest_framework.response import Response
@@ -12,8 +15,10 @@
1215
from sentry.api.bases import GroupEndpoint
1316
from sentry.api.serializers import serialize
1417
from sentry.integrations.api.serializers.models.integration import IntegrationSerializer
15-
from sentry.integrations.base import IntegrationFeatures, IntegrationInstallation
18+
from sentry.integrations.base import IntegrationFeatures
19+
from sentry.integrations.mixins.issues import IssueBasicIntegration
1620
from sentry.integrations.models.external_issue import ExternalIssue
21+
from sentry.integrations.models.integration import Integration
1722
from sentry.integrations.project_management.metrics import (
1823
ProjectManagementActionType,
1924
ProjectManagementEvent,
@@ -30,6 +35,7 @@
3035
from sentry.signals import integration_issue_created, integration_issue_linked
3136
from sentry.types.activity import ActivityType
3237
from sentry.users.models.user import User
38+
from sentry.users.services.user.model import RpcUser
3339

3440
MISSING_FEATURE_MESSAGE = "Your organization does not have access to this feature."
3541

@@ -46,7 +52,11 @@ def __init__(
4652
self.config = config
4753

4854
def serialize(
49-
self, obj: RpcIntegration, attrs: Mapping[str, Any], user: User, **kwargs: Any
55+
self,
56+
obj: Integration | RpcIntegration,
57+
attrs: Mapping[str, Any],
58+
user: User | RpcUser | AnonymousUser,
59+
**kwargs: Any,
5060
) -> MutableMapping[str, Any]:
5161
data = super().serialize(obj, attrs, user)
5262

@@ -68,7 +78,7 @@ class GroupIntegrationDetailsEndpoint(GroupEndpoint):
6878
"POST": ApiPublishStatus.UNKNOWN,
6979
}
7080

71-
def _has_issue_feature(self, organization, user):
81+
def _has_issue_feature(self, organization, user) -> bool:
7282
has_issue_basic = features.has(
7383
"organizations:integrations-issue-basic", organization, actor=user
7484
)
@@ -79,16 +89,24 @@ def _has_issue_feature(self, organization, user):
7989

8090
return has_issue_sync or has_issue_basic
8191

82-
def _has_issue_feature_on_integration(self, integration: RpcIntegration):
92+
def _has_issue_feature_on_integration(self, integration: RpcIntegration) -> bool:
8393
return integration.has_feature(
8494
feature=IntegrationFeatures.ISSUE_BASIC
8595
) or integration.has_feature(feature=IntegrationFeatures.ISSUE_SYNC)
8696

97+
def _get_installation(
98+
self, integration: RpcIntegration, organization_id: int
99+
) -> IssueBasicIntegration:
100+
installation = integration.get_installation(organization_id=organization_id)
101+
if not isinstance(installation, IssueBasicIntegration):
102+
raise ValueError(installation)
103+
return installation
104+
87105
def create_issue_activity(
88106
self,
89107
request: Request,
90108
group: Group,
91-
installation: IntegrationInstallation,
109+
installation: IssueBasicIntegration,
92110
external_issue: ExternalIssue,
93111
new: bool,
94112
):
@@ -108,7 +126,9 @@ def create_issue_activity(
108126
)
109127

110128
def get(self, request: Request, group, integration_id) -> Response:
111-
if not self._has_issue_feature(group.organization, request.user):
129+
if not request.user.is_authenticated:
130+
return Response(status=400)
131+
elif not self._has_issue_feature(group.organization, request.user):
112132
return Response({"detail": MISSING_FEATURE_MESSAGE}, status=400)
113133

114134
# Keep link/create separate since create will likely require
@@ -132,16 +152,16 @@ def get(self, request: Request, group, integration_id) -> Response:
132152
{"detail": "This feature is not supported for this integration."}, status=400
133153
)
134154

135-
installation = integration.get_installation(organization_id=organization_id)
136-
config = None
155+
installation = self._get_installation(integration, organization_id)
137156
try:
138157
if action == "link":
139158
config = installation.get_link_issue_config(group, params=request.GET)
140-
141-
if action == "create":
159+
elif action == "create":
142160
config = installation.get_create_issue_config(
143161
group, request.user, params=request.GET
144162
)
163+
else:
164+
raise AssertionError("unreachable")
145165
except IntegrationError as e:
146166
return Response({"detail": str(e)}, status=400)
147167

@@ -156,7 +176,9 @@ def get(self, request: Request, group, integration_id) -> Response:
156176

157177
# was thinking put for link an existing issue, post for create new issue?
158178
def put(self, request: Request, group, integration_id) -> Response:
159-
if not self._has_issue_feature(group.organization, request.user):
179+
if not request.user.is_authenticated:
180+
return Response(status=400)
181+
elif not self._has_issue_feature(group.organization, request.user):
160182
return Response({"detail": MISSING_FEATURE_MESSAGE}, status=400)
161183

162184
external_issue_id = request.data.get("externalIssue")
@@ -181,7 +203,7 @@ def put(self, request: Request, group, integration_id) -> Response:
181203
{"detail": "This feature is not supported for this integration."}, status=400
182204
)
183205

184-
installation = integration.get_installation(organization_id=organization_id)
206+
installation = self._get_installation(integration, organization_id)
185207

186208
try:
187209
data = installation.get_issue(external_issue_id, data=request.data)
@@ -254,7 +276,9 @@ def put(self, request: Request, group, integration_id) -> Response:
254276
return Response(context, status=201)
255277

256278
def post(self, request: Request, group, integration_id) -> Response:
257-
if not self._has_issue_feature(group.organization, request.user):
279+
if not request.user.is_authenticated:
280+
return Response(status=400)
281+
elif not self._has_issue_feature(group.organization, request.user):
258282
return Response({"detail": MISSING_FEATURE_MESSAGE}, status=400)
259283

260284
organization_id = group.project.organization_id
@@ -271,7 +295,7 @@ def post(self, request: Request, group, integration_id) -> Response:
271295
{"detail": "This feature is not supported for this integration."}, status=400
272296
)
273297

274-
installation = integration.get_installation(organization_id=organization_id)
298+
installation = self._get_installation(integration, organization_id)
275299

276300
with ProjectManagementEvent(
277301
action_type=ProjectManagementActionType.CREATE_EXTERNAL_ISSUE_VIA_ISSUE_DETAIL,

0 commit comments

Comments
 (0)