Skip to content

Commit b4d0f64

Browse files
authored
feat(app-platform): integration feature models, serializer, endpoints (#13377)
* integration feature models, serializer, endpoints
1 parent 2226337 commit b4d0f64

File tree

10 files changed

+1598
-0
lines changed

10 files changed

+1598
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from __future__ import absolute_import
2+
3+
from sentry.api.bases.sentryapps import SentryAppBaseEndpoint
4+
from sentry.api.serializers import serialize
5+
from sentry.api.paginator import OffsetPaginator
6+
from sentry.models import IntegrationFeature
7+
8+
9+
class SentryAppFeaturesEndpoint(SentryAppBaseEndpoint):
10+
def get(self, request, sentry_app):
11+
features = IntegrationFeature.objects.filter(
12+
sentry_app_id=sentry_app.id,
13+
)
14+
15+
return self.paginate(
16+
request=request,
17+
queryset=features,
18+
paginator_cls=OffsetPaginator,
19+
on_results=lambda x: serialize(x, request.user),
20+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from __future__ import absolute_import
2+
3+
from sentry.api.serializers import Serializer, register
4+
from sentry.models import IntegrationFeature
5+
6+
7+
@register(IntegrationFeature)
8+
class IntegrationFeatureSerializer(Serializer):
9+
def serialize(self, obj, attrs, user):
10+
return {
11+
'description': obj.description.strip(),
12+
# feature gating work done in getsentry expects the format 'featureGate'
13+
'featureGate': obj.feature_str(),
14+
}

src/sentry/api/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@
189189
from .endpoints.debug_files import DebugFilesEndpoint, DifAssembleEndpoint, \
190190
UnknownDebugFilesEndpoint, AssociateDSymFilesEndpoint
191191
from .endpoints.sentry_apps import SentryAppsEndpoint
192+
from .endpoints.sentry_app_features import SentryAppFeaturesEndpoint
192193
from .endpoints.sentry_apps_stats import SentryAppsStatsEndpoint
193194
from .endpoints.sentry_app_components import SentryAppComponentsEndpoint, \
194195
OrganizationSentryAppComponentsEndpoint
@@ -1328,6 +1329,11 @@
13281329
SentryAppDetailsEndpoint.as_view(),
13291330
name='sentry-api-0-sentry-app-details'
13301331
),
1332+
url(
1333+
r'^sentry-apps/(?P<sentry_app_slug>[^\/]+)/features/$',
1334+
SentryAppFeaturesEndpoint.as_view(),
1335+
name='sentry-api-0-sentry-app-features'
1336+
),
13311337
url(
13321338
r'^sentry-apps/(?P<sentry_app_slug>[^\/]+)/components/$',
13331339
SentryAppComponentsEndpoint.as_view(),

src/sentry/features/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
default_manager.add('organizations:incidents', OrganizationFeature) # NOQA
6666
default_manager.add('organizations:integrations-issue-basic', OrganizationFeature) # NOQA
6767
default_manager.add('organizations:integrations-issue-sync', OrganizationFeature) # NOQA
68+
default_manager.add('organizations:integrations-event-hooks', OrganizationFeature) # NOQA
6869
default_manager.add('organizations:internal-catchall', OrganizationFeature) # NOQA
6970
default_manager.add('organizations:incidents', OrganizationFeature) # NOQA
7071
default_manager.add('organizations:sentry-apps', OrganizationFeature) # NOQA
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
from __future__ import absolute_import
2+
3+
from django.db import models
4+
from django.utils import timezone
5+
6+
from sentry.db.models import BoundedPositiveIntegerField, FlexibleForeignKey, Model
7+
8+
9+
class Feature(object):
10+
API = 0
11+
ISSUE_LINK = 1
12+
STACKTRACE_LINK = 2
13+
EVENT_HOOKS = 3
14+
15+
@classmethod
16+
def as_choices(cls):
17+
return (
18+
(cls.API, 'integrations-api'),
19+
(cls.ISSUE_LINK, 'integrations-issue-link'),
20+
(cls.STACKTRACE_LINK, 'integrations-stacktrace-link'),
21+
(cls.EVENT_HOOKS, 'integrations-event-hooks'),
22+
)
23+
24+
@classmethod
25+
def as_str(cls, feature):
26+
if feature == cls.API:
27+
return 'integrations-api'
28+
elif feature == cls.ISSUE_LINK:
29+
return 'integrations-issue-link'
30+
elif feature == cls.STACKTRACE_LINK:
31+
return 'integrations-stacktrace-link'
32+
elif feature == cls.EVENT_HOOKS:
33+
return 'integrations-event-hooks'
34+
35+
@classmethod
36+
def description(cls, feature):
37+
if feature == cls.API:
38+
return "This integration can utilize the Sentry API (with the permissions granted) to pull data or update resources in Sentry!"
39+
elif feature == cls.ISSUE_LINK:
40+
return "This integration can allow your organization to create or link Sentry issues to another service!"
41+
elif feature == cls.STACKTRACE_LINK:
42+
return "This integration allows your organization to open a line in Sentry's stack trace in another service!"
43+
elif feature == cls.EVENT_HOOKS:
44+
return "This integration allows your organization to forward events to another service!"
45+
46+
47+
class IntegrationFeature(Model):
48+
__core__ = False
49+
50+
sentry_app = FlexibleForeignKey('sentry.SentryApp')
51+
user_description = models.TextField(null=True)
52+
feature = BoundedPositiveIntegerField(
53+
default=0,
54+
choices=Feature.as_choices(),
55+
)
56+
date_added = models.DateTimeField(default=timezone.now)
57+
58+
class Meta:
59+
app_label = 'sentry'
60+
db_table = 'sentry_integrationfeature'
61+
62+
def feature_str(self):
63+
return Feature.as_str(self.feature)
64+
65+
@property
66+
def description(self):
67+
if self.user_description:
68+
return self.user_description
69+
else:
70+
return Feature.description(self.feature)

0 commit comments

Comments
 (0)