diff --git a/src/sentry/sentry_apps/services/app/impl.py b/src/sentry/sentry_apps/services/app/impl.py index f7f2e14d6e2334..009f627cbe9ec5 100644 --- a/src/sentry/sentry_apps/services/app/impl.py +++ b/src/sentry/sentry_apps/services/app/impl.py @@ -33,6 +33,7 @@ RpcSentryAppService, SentryAppInstallationFilterArgs, ) +from sentry.sentry_apps.services.app.model import SentryAppUpdateArgs from sentry.sentry_apps.services.app.serial import ( serialize_sentry_app, serialize_sentry_app_component, @@ -333,6 +334,33 @@ def get_published_sentry_apps_for_organization( ) return [serialize_sentry_app(app) for app in published_apps] + def get_sentry_apps_for_organization(self, *, organization_id: int) -> list[RpcSentryApp]: + """ + Get active Sentry Apps for a given organization + """ + sentry_apps = SentryApp.objects.filter( + owner_id=organization_id, application__isnull=False + ).exclude(status=SentryAppStatus.DELETION_IN_PROGRESS) + return [serialize_sentry_app(app) for app in sentry_apps] + + def update_sentry_app( + self, + *, + id: int, + attrs: SentryAppUpdateArgs, + ) -> RpcSentryApp | None: + try: + sentry_app = SentryApp.objects.get(id=id) + except SentryApp.DoesNotExist: + return None + + if len(attrs): + for k, v in attrs.items(): + setattr(sentry_app, k, v) + sentry_app.save() + + return serialize_sentry_app(sentry_app) + def get_internal_integrations( self, *, organization_id: int, integration_name: str ) -> list[RpcSentryApp]: diff --git a/src/sentry/sentry_apps/services/app/model.py b/src/sentry/sentry_apps/services/app/model.py index a4952bf4b895a0..f3e3f796ab82ac 100644 --- a/src/sentry/sentry_apps/services/app/model.py +++ b/src/sentry/sentry_apps/services/app/model.py @@ -196,3 +196,9 @@ class SentryAppInstallationFilterArgs(TypedDict, total=False): status: int api_token_id: int api_installation_token_id: str + + +class SentryAppUpdateArgs(TypedDict, total=False): + events: list[str] + name: str + # TODO add whatever else as needed diff --git a/src/sentry/sentry_apps/services/app/service.py b/src/sentry/sentry_apps/services/app/service.py index 03e8b8e6fcfb76..c0c494b3d57541 100644 --- a/src/sentry/sentry_apps/services/app/service.py +++ b/src/sentry/sentry_apps/services/app/service.py @@ -20,7 +20,7 @@ RpcSentryAppService, SentryAppInstallationFilterArgs, ) -from sentry.sentry_apps.services.app.model import RpcSentryAppComponentContext +from sentry.sentry_apps.services.app.model import RpcSentryAppComponentContext, SentryAppUpdateArgs from sentry.silo.base import SiloMode from sentry.users.services.user import RpcUser @@ -192,6 +192,16 @@ def get_published_sentry_apps_for_organization( ) -> list[RpcSentryApp]: pass + @rpc_method + @abc.abstractmethod + def get_sentry_apps_for_organization(self, *, organization_id: int) -> list[RpcSentryApp]: + pass + + @rpc_method + @abc.abstractmethod + def update_sentry_app(self, *, id: int, attrs: SentryAppUpdateArgs) -> RpcSentryApp | None: + pass + @rpc_method @abc.abstractmethod def get_internal_integrations( diff --git a/tests/sentry/sentry_apps/services/test_app.py b/tests/sentry/sentry_apps/services/test_app.py index 77b84b3d2996f2..a9c295d72cbcf6 100644 --- a/tests/sentry/sentry_apps/services/test_app.py +++ b/tests/sentry/sentry_apps/services/test_app.py @@ -238,6 +238,47 @@ def test_get_installation_org_id_by_token_id() -> None: assert result is None +@django_db_all(transaction=True) +@all_silo_test +def test_get_sentry_apps_for_organization() -> None: + org = Factories.create_organization() + other_org = Factories.create_organization() + + # Create internal integrations + Factories.create_internal_integration( + name="Test Integration", + organization_id=org.id, + ) + Factories.create_internal_integration( + name="Test Integration", + organization_id=other_org.id, + ) + result = app_service.get_sentry_apps_for_organization(organization_id=org.id) + assert len(result) == 1 + assert result[0].owner_id == org.id + + +@django_db_all(transaction=True) +@all_silo_test +def test_update_sentry_app() -> None: + org = Factories.create_organization() + + sentry_app = Factories.create_internal_integration( + name="Test Integration", + organization_id=org.id, + events=[ + "issue.resolved", + "issue.unresolved", + "issue.ignored", + "issue.assigned", + "error.created", + ], + ) + result = app_service.update_sentry_app(id=sentry_app.id, attrs=dict(events=["error.created"])) + assert result + assert result.events == ["error.created"] + + @django_db_all(transaction=True) @all_silo_test def test_get_internal_integrations() -> None: