diff --git a/src/sentry/models/authprovider.py b/src/sentry/models/authprovider.py index 1454ee71d30ad3..be3b0f7085ec13 100644 --- a/src/sentry/models/authprovider.py +++ b/src/sentry/models/authprovider.py @@ -11,8 +11,10 @@ from sentry.backup.dependencies import NormalizedModelName, get_model_name from sentry.backup.sanitize import SanitizableField, Sanitizer from sentry.backup.scopes import RelocationScope +from sentry.constants import SentryAppStatus from sentry.db.models import BoundedPositiveIntegerField, control_silo_model, sane_repr from sentry.db.models.fields.hybrid_cloud_foreign_key import HybridCloudForeignKey +from sentry.deletions.models.scheduleddeletion import ScheduledDeletion from sentry.hybridcloud.models.outbox import ControlOutbox from sentry.hybridcloud.outbox.base import ReplicatedControlModel from sentry.hybridcloud.outbox.category import OutboxCategory, OutboxScope @@ -164,7 +166,6 @@ def outboxes_for_reset_idp_flags(self) -> list[ControlOutbox]: ] def disable_scim(self): - from sentry import deletions from sentry.sentry_apps.models.sentry_app_installation_for_provider import ( SentryAppInstallationForProvider, ) @@ -185,7 +186,8 @@ def disable_scim(self): assert ( sentry_app.is_internal ), "scim sentry apps should always be internal, thus deleting them without triggering InstallationNotifier is correct." - deletions.exec_sync(sentry_app) + sentry_app.update(status=SentryAppStatus.DELETION_IN_PROGRESS) + ScheduledDeletion.schedule(sentry_app, days=0) except SentryAppInstallationForProvider.DoesNotExist: pass self.flags.scim_enabled = False diff --git a/src/sentry/sentry_apps/api/endpoints/sentry_app_details.py b/src/sentry/sentry_apps/api/endpoints/sentry_app_details.py index 1f32d6f6db7157..022fd980192fed 100644 --- a/src/sentry/sentry_apps/api/endpoints/sentry_app_details.py +++ b/src/sentry/sentry_apps/api/endpoints/sentry_app_details.py @@ -23,6 +23,7 @@ from sentry.apidocs.utils import inline_sentry_response_serializer from sentry.auth.staff import is_active_staff from sentry.constants import SentryAppStatus +from sentry.deletions.models.scheduleddeletion import ScheduledDeletion from sentry.organizations.services.organization import organization_service from sentry.sentry_apps.api.bases.sentryapps import ( SentryAppAndStaffPermission, @@ -234,13 +235,15 @@ def delete(self, request: Request, sentry_app) -> Response: sentry_sdk.capture_exception(exc) with transaction.atomic(using=router.db_for_write(SentryApp)): - deletions.exec_sync(sentry_app) + sentry_app.update(status=SentryAppStatus.DELETION_IN_PROGRESS) + scheduled = ScheduledDeletion.schedule(sentry_app, days=0, actor=request.user) create_audit_entry( request=request, organization_id=sentry_app.owner_id, target_object=sentry_app.owner_id, event=audit_log.get_event_id("SENTRY_APP_REMOVE"), data={"sentry_app": sentry_app.name}, + transaction_id=scheduled.id, ) if request.user.is_authenticated: analytics.record( diff --git a/tests/sentry/sentry_apps/api/endpoints/test_sentry_app_details.py b/tests/sentry/sentry_apps/api/endpoints/test_sentry_app_details.py index 3114898be75f66..d48d712634236f 100644 --- a/tests/sentry/sentry_apps/api/endpoints/test_sentry_app_details.py +++ b/tests/sentry/sentry_apps/api/endpoints/test_sentry_app_details.py @@ -9,6 +9,7 @@ SentryAppSchemaValidationError, ) from sentry.constants import SentryAppStatus +from sentry.deletions.tasks.scheduled import run_scheduled_deletions_control from sentry.models.auditlogentry import AuditLogEntry from sentry.models.organizationmember import OrganizationMember from sentry.sentry_apps.api.endpoints.sentry_app_details import PARTNERSHIP_RESTRICTED_ERROR_MESSAGE @@ -791,6 +792,8 @@ def test_superuser_delete_unpublished_app(self, record: MagicMock) -> None: self.unpublished_app.slug, status_code=204, ) + with self.tasks(): + run_scheduled_deletions_control() assert AuditLogEntry.objects.filter( event=audit_log.get_event_id("SENTRY_APP_REMOVE") @@ -815,6 +818,8 @@ def test_superuser_delete_unpublished_app_with_installs(self) -> None: self.unpublished_app.slug, status_code=204, ) + with self.tasks(): + run_scheduled_deletions_control() assert AuditLogEntry.objects.filter( event=audit_log.get_event_id("SENTRY_APP_REMOVE") diff --git a/tests/sentry/web/frontend/test_organization_auth_settings.py b/tests/sentry/web/frontend/test_organization_auth_settings.py index 625c10043af112..94df506a16a37c 100644 --- a/tests/sentry/web/frontend/test_organization_auth_settings.py +++ b/tests/sentry/web/frontend/test_organization_auth_settings.py @@ -15,6 +15,7 @@ ) from sentry.auth.providers.saml2.generic.provider import GenericSAML2Provider from sentry.auth.providers.saml2.provider import Attributes +from sentry.deletions.tasks.scheduled import run_scheduled_deletions_control from sentry.models.auditlogentry import AuditLogEntry from sentry.models.authidentity import AuthIdentity from sentry.models.authprovider import AuthProvider @@ -604,6 +605,9 @@ def test_edit_sso_settings__scim(self) -> None: }, ) + with self.tasks(): + run_scheduled_deletions_control() + assert resp.status_code == 200 auth_provider = AuthProvider.objects.get(organization_id=organization.id)