From 9898694a7a4e18dedbf2a2845f9dc38815db05f1 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Tue, 25 Nov 2025 17:22:43 -0500 Subject: [PATCH 01/11] Add silo annotations to email debug views --- src/sentry/web/frontend/debug/debug_auth_views.py | 3 +++ .../debug_codeowners_auto_sync_failure_email.py | 2 ++ .../debug/debug_cron_broken_monitor_email.py | 3 +++ .../debug/debug_cron_muted_monitor_email.py | 3 +++ .../web/frontend/debug/debug_error_embed.py | 2 ++ .../web/frontend/debug/debug_feedback_issue.py | 2 ++ .../web/frontend/debug/debug_generic_issue.py | 2 ++ .../debug/debug_incident_trigger_email.py | 2 ++ .../debug/debug_invalid_identity_email.py | 2 ++ .../web/frontend/debug/debug_mfa_added_email.py | 2 ++ .../web/frontend/debug/debug_mfa_removed_email.py | 2 ++ .../debug/debug_missing_member_nudge_email.py | 2 ++ .../web/frontend/debug/debug_new_release_email.py | 2 ++ .../debug/debug_new_user_feedback_email.py | 2 ++ src/sentry/web/frontend/debug/debug_note_email.py | 2 ++ .../web/frontend/debug/debug_oauth_authorize.py | 2 ++ .../debug/debug_onboarding_continuation_email.py | 2 ++ .../debug_organization_integration_request.py | 2 ++ .../debug/debug_organization_invite_request.py | 2 ++ .../debug/debug_organization_join_request.py | 2 ++ .../debug/debug_password_changed_email.py | 2 ++ .../web/frontend/debug/debug_performance_issue.py | 2 ++ .../debug_recovery_codes_regenerated_email.py | 2 ++ .../web/frontend/debug/debug_regression_email.py | 3 +++ .../web/frontend/debug/debug_resolved_email.py | 2 ++ .../debug/debug_resolved_in_release_email.py | 3 +++ .../web/frontend/debug/debug_setup_2fa_email.py | 2 ++ .../web/frontend/debug/debug_sso_link_email.py | 4 ++++ .../web/frontend/debug/debug_trigger_error.py | 2 ++ .../debug/debug_unable_to_delete_repository.py | 2 ++ .../debug/debug_unable_to_fetch_commits_email.py | 2 ++ .../web/frontend/debug/debug_unassigned_email.py | 2 ++ .../debug_uptime_auto_detected_monitor_email.py | 3 +++ .../web/frontend/debug/debug_weekly_report.py | 2 ++ src/sentry/web/frontend/debug/mail.py | 15 +++++++++++++++ 35 files changed, 91 insertions(+) diff --git a/src/sentry/web/frontend/debug/debug_auth_views.py b/src/sentry/web/frontend/debug/debug_auth_views.py index 5de8010b1afc7f..29d332058f2873 100644 --- a/src/sentry/web/frontend/debug/debug_auth_views.py +++ b/src/sentry/web/frontend/debug/debug_auth_views.py @@ -2,9 +2,11 @@ from django.views.generic import View from sentry.users.models.user import User +from sentry.web.frontend.base import region_silo_view from sentry.web.helpers import render_to_response +@region_silo_view class DebugAuthConfirmIdentity(View): def get(self, request: HttpRequest) -> HttpResponse: auth_identity = {"id": "bar@example.com", "email": "bar@example.com"} @@ -21,6 +23,7 @@ def get(self, request: HttpRequest) -> HttpResponse: ) +@region_silo_view class DebugAuthConfirmLink(View): def get(self, request: HttpRequest) -> HttpResponse: auth_identity = {"id": "bar@example.com", "email": "test1@example.com"} diff --git a/src/sentry/web/frontend/debug/debug_codeowners_auto_sync_failure_email.py b/src/sentry/web/frontend/debug/debug_codeowners_auto_sync_failure_email.py index d7ea9c9000b6f4..3251832b4b32d5 100644 --- a/src/sentry/web/frontend/debug/debug_codeowners_auto_sync_failure_email.py +++ b/src/sentry/web/frontend/debug/debug_codeowners_auto_sync_failure_email.py @@ -6,10 +6,12 @@ from sentry.models.project import Project from sentry.notifications.notifications.codeowners_auto_sync import AutoSyncNotification from sentry.users.models.user import User +from sentry.web.frontend.base import region_silo_view from .mail import render_preview_email_for_notification +@region_silo_view class DebugCodeOwnersAutoSyncFailureView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="petal", name="Petal") diff --git a/src/sentry/web/frontend/debug/debug_cron_broken_monitor_email.py b/src/sentry/web/frontend/debug/debug_cron_broken_monitor_email.py index 284dfdf2ccd525..f71d15e595dafd 100644 --- a/src/sentry/web/frontend/debug/debug_cron_broken_monitor_email.py +++ b/src/sentry/web/frontend/debug/debug_cron_broken_monitor_email.py @@ -3,6 +3,8 @@ from django.http import HttpRequest, HttpResponse from django.views.generic import View +from sentry.web.frontend.base import region_silo_view + from .mail import MailPreview @@ -17,6 +19,7 @@ def get_context(): } +@region_silo_view class DebugCronBrokenMonitorEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context() diff --git a/src/sentry/web/frontend/debug/debug_cron_muted_monitor_email.py b/src/sentry/web/frontend/debug/debug_cron_muted_monitor_email.py index 28a0aa427f5079..a21ed5f4cd4b40 100644 --- a/src/sentry/web/frontend/debug/debug_cron_muted_monitor_email.py +++ b/src/sentry/web/frontend/debug/debug_cron_muted_monitor_email.py @@ -3,6 +3,8 @@ from django.http import HttpRequest, HttpResponse from django.views.generic import View +from sentry.web.frontend.base import region_silo_view + from .mail import MailPreview @@ -17,6 +19,7 @@ def get_context(): } +@region_silo_view class DebugCronMutedMonitorEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context() diff --git a/src/sentry/web/frontend/debug/debug_error_embed.py b/src/sentry/web/frontend/debug/debug_error_embed.py index c292ff96af7317..1968d73f5ef865 100644 --- a/src/sentry/web/frontend/debug/debug_error_embed.py +++ b/src/sentry/web/frontend/debug/debug_error_embed.py @@ -5,9 +5,11 @@ from django.views.generic import View from sentry.models.projectkey import ProjectKey +from sentry.web.frontend.base import region_silo_view from sentry.web.helpers import render_to_response +@region_silo_view class DebugErrorPageEmbedView(View): def _get_project_key(self): return ProjectKey.objects.filter(project=settings.SENTRY_PROJECT)[0] diff --git a/src/sentry/web/frontend/debug/debug_feedback_issue.py b/src/sentry/web/frontend/debug/debug_feedback_issue.py index f3052324165d7d..c7dc89d5f9fb0f 100644 --- a/src/sentry/web/frontend/debug/debug_feedback_issue.py +++ b/src/sentry/web/frontend/debug/debug_feedback_issue.py @@ -8,10 +8,12 @@ from sentry.notifications.utils import get_generic_data from sentry.notifications.utils.links import get_group_settings_link, get_rules from sentry.utils import json +from sentry.web.frontend.base import region_silo_view from .mail import COMMIT_EXAMPLE, MailPreview, make_feedback_issue +@region_silo_view class DebugFeedbackIssueEmailView(View): def get(self, request): org = Organization(id=1, slug="example", name="Example") diff --git a/src/sentry/web/frontend/debug/debug_generic_issue.py b/src/sentry/web/frontend/debug/debug_generic_issue.py index 5df29d9b0475de..8a3a8e4a1852dc 100644 --- a/src/sentry/web/frontend/debug/debug_generic_issue.py +++ b/src/sentry/web/frontend/debug/debug_generic_issue.py @@ -9,10 +9,12 @@ from sentry.notifications.utils import get_generic_data from sentry.notifications.utils.links import get_group_settings_link, get_rules from sentry.utils import json +from sentry.web.frontend.base import region_silo_view from .mail import COMMIT_EXAMPLE, MailPreview, make_generic_event +@region_silo_view class DebugGenericIssueEmailView(View): def get(self, request): org = Organization(id=1, slug="example", name="Example") diff --git a/src/sentry/web/frontend/debug/debug_incident_trigger_email.py b/src/sentry/web/frontend/debug/debug_incident_trigger_email.py index ef536d12211c41..d9d40103f9d131 100644 --- a/src/sentry/web/frontend/debug/debug_incident_trigger_email.py +++ b/src/sentry/web/frontend/debug/debug_incident_trigger_email.py @@ -18,6 +18,7 @@ from sentry.models.project import Project from sentry.snuba.models import SnubaQuery from sentry.users.models.user import User +from sentry.web.frontend.base import region_silo_view from .mail import MailPreviewView @@ -26,6 +27,7 @@ class MockedIncidentTrigger: date_added = timezone.now() +@region_silo_view class DebugIncidentTriggerEmailView(MailPreviewView): @mock.patch( "sentry.incidents.models.incident.IncidentTrigger.objects.get", diff --git a/src/sentry/web/frontend/debug/debug_invalid_identity_email.py b/src/sentry/web/frontend/debug/debug_invalid_identity_email.py index 1f3596e926c77b..2e3035e6a3e2d2 100644 --- a/src/sentry/web/frontend/debug/debug_invalid_identity_email.py +++ b/src/sentry/web/frontend/debug/debug_invalid_identity_email.py @@ -2,11 +2,13 @@ from django.views.generic import View from sentry.tasks.commits import generate_invalid_identity_email +from sentry.web.frontend.base import region_silo_view from social_auth.models import UserSocialAuth from .mail import MailPreview +@region_silo_view class DebugInvalidIdentityEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: assert request.user.is_authenticated diff --git a/src/sentry/web/frontend/debug/debug_mfa_added_email.py b/src/sentry/web/frontend/debug/debug_mfa_added_email.py index 6853396103ca03..aca819f106173b 100644 --- a/src/sentry/web/frontend/debug/debug_mfa_added_email.py +++ b/src/sentry/web/frontend/debug/debug_mfa_added_email.py @@ -6,10 +6,12 @@ from sentry.security.emails import generate_security_email from sentry.users.models.authenticator import Authenticator +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview +@region_silo_view class DebugMfaAddedEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: if isinstance(request.user, AnonymousUser): diff --git a/src/sentry/web/frontend/debug/debug_mfa_removed_email.py b/src/sentry/web/frontend/debug/debug_mfa_removed_email.py index 03cb98317c83cb..44fa2c7c70b6e0 100644 --- a/src/sentry/web/frontend/debug/debug_mfa_removed_email.py +++ b/src/sentry/web/frontend/debug/debug_mfa_removed_email.py @@ -6,10 +6,12 @@ from sentry.security.emails import generate_security_email from sentry.users.models.authenticator import Authenticator +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview +@region_silo_view class DebugMfaRemovedEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: if isinstance(request.user, AnonymousUser): diff --git a/src/sentry/web/frontend/debug/debug_missing_member_nudge_email.py b/src/sentry/web/frontend/debug/debug_missing_member_nudge_email.py index 766416435ee74b..ad7666cf5daf0b 100644 --- a/src/sentry/web/frontend/debug/debug_missing_member_nudge_email.py +++ b/src/sentry/web/frontend/debug/debug_missing_member_nudge_email.py @@ -2,10 +2,12 @@ from django.views.generic import View from sentry.models.organization import Organization +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview +@region_silo_view class DebugMissingMembersNudgeView(View): def get(self, request: HttpRequest) -> HttpResponse: self.organization = Organization(id=1, slug="organization", name="My Company") diff --git a/src/sentry/web/frontend/debug/debug_new_release_email.py b/src/sentry/web/frontend/debug/debug_new_release_email.py index 43d53c7563b3ae..bc1079b1e47c92 100644 --- a/src/sentry/web/frontend/debug/debug_new_release_email.py +++ b/src/sentry/web/frontend/debug/debug_new_release_email.py @@ -14,10 +14,12 @@ from sentry.notifications.types import GroupSubscriptionReason from sentry.users.models.user import User from sentry.utils.http import absolute_uri +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview +@region_silo_view class DebugNewReleaseEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="organization", name="My Company") diff --git a/src/sentry/web/frontend/debug/debug_new_user_feedback_email.py b/src/sentry/web/frontend/debug/debug_new_user_feedback_email.py index 7699b3da3ebd07..90ca5a14006e4c 100644 --- a/src/sentry/web/frontend/debug/debug_new_user_feedback_email.py +++ b/src/sentry/web/frontend/debug/debug_new_user_feedback_email.py @@ -5,10 +5,12 @@ from sentry.models.project import Project from sentry.utils.http import absolute_uri from sentry.utils.samples import create_sample_event +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview +@region_silo_view class DebugNewUserFeedbackEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="organization", name="My Company") diff --git a/src/sentry/web/frontend/debug/debug_note_email.py b/src/sentry/web/frontend/debug/debug_note_email.py index 09e3d39dec359c..2d770b1ca1fb6c 100644 --- a/src/sentry/web/frontend/debug/debug_note_email.py +++ b/src/sentry/web/frontend/debug/debug_note_email.py @@ -1,10 +1,12 @@ from django.http import HttpRequest from sentry.types.activity import ActivityType +from sentry.web.frontend.base import region_silo_view from .mail import ActivityMailDebugView, get_random, make_message +@region_silo_view class DebugNoteEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): random = get_random(request) diff --git a/src/sentry/web/frontend/debug/debug_oauth_authorize.py b/src/sentry/web/frontend/debug/debug_oauth_authorize.py index 0968abee97e90c..833895f069ccbc 100644 --- a/src/sentry/web/frontend/debug/debug_oauth_authorize.py +++ b/src/sentry/web/frontend/debug/debug_oauth_authorize.py @@ -2,9 +2,11 @@ from django.views.generic import View from sentry.models.apiapplication import ApiApplication +from sentry.web.frontend.base import region_silo_view from sentry.web.helpers import render_to_response +@region_silo_view class DebugOAuthAuthorizeView(View): def get(self, request: HttpRequest) -> HttpResponse: application = ApiApplication( diff --git a/src/sentry/web/frontend/debug/debug_onboarding_continuation_email.py b/src/sentry/web/frontend/debug/debug_onboarding_continuation_email.py index f837ba16ccd1e2..7972326ce12960 100644 --- a/src/sentry/web/frontend/debug/debug_onboarding_continuation_email.py +++ b/src/sentry/web/frontend/debug/debug_onboarding_continuation_email.py @@ -4,10 +4,12 @@ from sentry.api.endpoints.organization_onboarding_continuation_email import get_request_builder_args from sentry.models.organization import Organization from sentry.users.models.user import User +from sentry.web.frontend.base import region_silo_view from sentry.web.frontend.debug.mail import MailPreviewAdapter from sentry.web.helpers import render_to_response +@region_silo_view class DebugOrganizationOnboardingContinuationEmail(View): def get(self, request: HttpRequest) -> HttpResponse: platforms = request.GET.getlist("platforms", ["javascript", "python", "flutter"]) diff --git a/src/sentry/web/frontend/debug/debug_organization_integration_request.py b/src/sentry/web/frontend/debug/debug_organization_integration_request.py index 0ccc34143ff058..e5b9b350bdb6ef 100644 --- a/src/sentry/web/frontend/debug/debug_organization_integration_request.py +++ b/src/sentry/web/frontend/debug/debug_organization_integration_request.py @@ -8,10 +8,12 @@ IntegrationRequestNotification, ) from sentry.users.models.user import User +from sentry.web.frontend.base import region_silo_view from .mail import render_preview_email_for_notification +@region_silo_view class DebugOrganizationIntegrationRequestEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="default", name="Default") diff --git a/src/sentry/web/frontend/debug/debug_organization_invite_request.py b/src/sentry/web/frontend/debug/debug_organization_invite_request.py index 41005e2ef2f8a9..643cba8acefe56 100644 --- a/src/sentry/web/frontend/debug/debug_organization_invite_request.py +++ b/src/sentry/web/frontend/debug/debug_organization_invite_request.py @@ -5,10 +5,12 @@ from sentry.models.organizationmember import InviteStatus, OrganizationMember from sentry.notifications.notifications.organization_request import InviteRequestNotification from sentry.users.models.user import User +from sentry.web.frontend.base import region_silo_view from .mail import render_preview_email_for_notification +@region_silo_view class DebugOrganizationInviteRequestEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="default", name="Default") diff --git a/src/sentry/web/frontend/debug/debug_organization_join_request.py b/src/sentry/web/frontend/debug/debug_organization_join_request.py index 6c024130cca598..45ca0c1f55f164 100644 --- a/src/sentry/web/frontend/debug/debug_organization_join_request.py +++ b/src/sentry/web/frontend/debug/debug_organization_join_request.py @@ -5,10 +5,12 @@ from sentry.models.organizationmember import InviteStatus, OrganizationMember from sentry.notifications.notifications.organization_request import JoinRequestNotification from sentry.users.models.user import User +from sentry.web.frontend.base import region_silo_view from .mail import render_preview_email_for_notification +@region_silo_view class DebugOrganizationJoinRequestEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="default", name="Default") diff --git a/src/sentry/web/frontend/debug/debug_password_changed_email.py b/src/sentry/web/frontend/debug/debug_password_changed_email.py index 9649ce7c37ec82..1ddda321a6d5ff 100644 --- a/src/sentry/web/frontend/debug/debug_password_changed_email.py +++ b/src/sentry/web/frontend/debug/debug_password_changed_email.py @@ -5,10 +5,12 @@ from sentry.security.emails import generate_security_email from sentry.utils.auth import AuthenticatedHttpRequest +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview +@region_silo_view class DebugPasswordChangedEmailView(View): def get(self, request: AuthenticatedHttpRequest) -> HttpResponse: email = generate_security_email( diff --git a/src/sentry/web/frontend/debug/debug_performance_issue.py b/src/sentry/web/frontend/debug/debug_performance_issue.py index 65240fdfe7c602..59f47485cef1ad 100644 --- a/src/sentry/web/frontend/debug/debug_performance_issue.py +++ b/src/sentry/web/frontend/debug/debug_performance_issue.py @@ -9,10 +9,12 @@ get_transaction_data, ) from sentry.utils import json +from sentry.web.frontend.base import region_silo_view from .mail import COMMIT_EXAMPLE, MailPreview, get_shared_context, make_performance_event +@region_silo_view class DebugPerformanceIssueEmailView(View): def get(self, request, sample_name="transaction-n-plus-one"): project = Project.objects.get(id=1) diff --git a/src/sentry/web/frontend/debug/debug_recovery_codes_regenerated_email.py b/src/sentry/web/frontend/debug/debug_recovery_codes_regenerated_email.py index 4c21edbb188556..99226b06200a4b 100644 --- a/src/sentry/web/frontend/debug/debug_recovery_codes_regenerated_email.py +++ b/src/sentry/web/frontend/debug/debug_recovery_codes_regenerated_email.py @@ -6,10 +6,12 @@ from sentry.security.emails import generate_security_email from sentry.users.models.authenticator import Authenticator from sentry.utils.auth import AuthenticatedHttpRequest +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview +@region_silo_view class DebugRecoveryCodesRegeneratedEmailView(View): def get(self, request: AuthenticatedHttpRequest) -> HttpResponse: authenticator = Authenticator(id=0, type=3, user_id=request.user.id) # u2f diff --git a/src/sentry/web/frontend/debug/debug_regression_email.py b/src/sentry/web/frontend/debug/debug_regression_email.py index 1a8cef20002629..bb9a2bba70d38d 100644 --- a/src/sentry/web/frontend/debug/debug_regression_email.py +++ b/src/sentry/web/frontend/debug/debug_regression_email.py @@ -1,15 +1,18 @@ from django.http import HttpRequest from sentry.types.activity import ActivityType +from sentry.web.frontend.base import region_silo_view from .mail import ActivityMailDebugView +@region_silo_view class DebugRegressionEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.SET_REGRESSION.value} +@region_silo_view class DebugRegressionReleaseEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.SET_REGRESSION.value, "data": {"version": "abcdef"}} diff --git a/src/sentry/web/frontend/debug/debug_resolved_email.py b/src/sentry/web/frontend/debug/debug_resolved_email.py index 11af58ddbbd035..b2441455038d9b 100644 --- a/src/sentry/web/frontend/debug/debug_resolved_email.py +++ b/src/sentry/web/frontend/debug/debug_resolved_email.py @@ -1,10 +1,12 @@ from django.http import HttpRequest from sentry.types.activity import ActivityType +from sentry.web.frontend.base import region_silo_view from .mail import ActivityMailDebugView +@region_silo_view class DebugResolvedEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.SET_RESOLVED.value} diff --git a/src/sentry/web/frontend/debug/debug_resolved_in_release_email.py b/src/sentry/web/frontend/debug/debug_resolved_in_release_email.py index d592a43b89bb86..6d313f1bee9d57 100644 --- a/src/sentry/web/frontend/debug/debug_resolved_in_release_email.py +++ b/src/sentry/web/frontend/debug/debug_resolved_in_release_email.py @@ -1,15 +1,18 @@ from django.http import HttpRequest from sentry.types.activity import ActivityType +from sentry.web.frontend.base import region_silo_view from .mail import ActivityMailDebugView +@region_silo_view class DebugResolvedInReleaseEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.SET_RESOLVED_IN_RELEASE.value, "data": {"version": "abcdef"}} +@region_silo_view class DebugResolvedInReleaseUpcomingEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.SET_RESOLVED_IN_RELEASE.value, "data": {"version": ""}} diff --git a/src/sentry/web/frontend/debug/debug_setup_2fa_email.py b/src/sentry/web/frontend/debug/debug_setup_2fa_email.py index 5a1e0541bdc528..e87a3d96ea4fad 100644 --- a/src/sentry/web/frontend/debug/debug_setup_2fa_email.py +++ b/src/sentry/web/frontend/debug/debug_setup_2fa_email.py @@ -3,10 +3,12 @@ from sentry.models.organization import Organization from sentry.models.organizationmember import OrganizationMember +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview +@region_silo_view class DebugSetup2faEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="organization", name="sentry corp") diff --git a/src/sentry/web/frontend/debug/debug_sso_link_email.py b/src/sentry/web/frontend/debug/debug_sso_link_email.py index fe3e33578b3bdb..6aa5484034ceb1 100644 --- a/src/sentry/web/frontend/debug/debug_sso_link_email.py +++ b/src/sentry/web/frontend/debug/debug_sso_link_email.py @@ -3,6 +3,7 @@ from sentry.auth.providers.dummy import DummyProvider from sentry.models.organization import Organization +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview @@ -14,6 +15,7 @@ def get_context(request): return {"organization": org, "actor_email": request.user.email, "provider": provider} +@region_silo_view class DebugSsoLinkedEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context(request) @@ -25,6 +27,7 @@ def get(self, request: HttpRequest) -> HttpResponse: ).render(request) +@region_silo_view class DebugSsoUnlinkedEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context(request) @@ -37,6 +40,7 @@ def get(self, request: HttpRequest) -> HttpResponse: ).render(request) +@region_silo_view class DebugSsoUnlinkedNoPasswordEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context(request) diff --git a/src/sentry/web/frontend/debug/debug_trigger_error.py b/src/sentry/web/frontend/debug/debug_trigger_error.py index b757c6c06694d1..5bc5d685c75706 100644 --- a/src/sentry/web/frontend/debug/debug_trigger_error.py +++ b/src/sentry/web/frontend/debug/debug_trigger_error.py @@ -3,9 +3,11 @@ from django.views.generic import View from sentry.utils.sdk import capture_exception +from sentry.web.frontend.base import region_silo_view from sentry.web.frontend.error_500 import Error500View +@region_silo_view class DebugTriggerErrorView(View): def get(self, request: HttpRequest) -> HttpResponseBase: try: diff --git a/src/sentry/web/frontend/debug/debug_unable_to_delete_repository.py b/src/sentry/web/frontend/debug/debug_unable_to_delete_repository.py index f397c12f8a708b..cb82a353bbe718 100644 --- a/src/sentry/web/frontend/debug/debug_unable_to_delete_repository.py +++ b/src/sentry/web/frontend/debug/debug_unable_to_delete_repository.py @@ -3,10 +3,12 @@ from sentry.models.repository import Repository from sentry.plugins.providers.dummy import DummyRepositoryProvider +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview +@region_silo_view class DebugUnableToDeleteRepository(View): def get(self, request: HttpRequest) -> HttpResponse: repo = Repository(name="getsentry/sentry", provider="dummy") diff --git a/src/sentry/web/frontend/debug/debug_unable_to_fetch_commits_email.py b/src/sentry/web/frontend/debug/debug_unable_to_fetch_commits_email.py index 7271678e2aa5a0..6846df5a1d0b59 100644 --- a/src/sentry/web/frontend/debug/debug_unable_to_fetch_commits_email.py +++ b/src/sentry/web/frontend/debug/debug_unable_to_fetch_commits_email.py @@ -5,10 +5,12 @@ from sentry.models.release import Release from sentry.models.repository import Repository from sentry.tasks.commits import generate_fetch_commits_error_email +from sentry.web.frontend.base import region_silo_view from .mail import MailPreview +@region_silo_view class DebugUnableToFetchCommitsEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(slug="myorg") diff --git a/src/sentry/web/frontend/debug/debug_unassigned_email.py b/src/sentry/web/frontend/debug/debug_unassigned_email.py index b2414ba53466b8..8cf59cdd38915e 100644 --- a/src/sentry/web/frontend/debug/debug_unassigned_email.py +++ b/src/sentry/web/frontend/debug/debug_unassigned_email.py @@ -1,10 +1,12 @@ from django.http import HttpRequest from sentry.types.activity import ActivityType +from sentry.web.frontend.base import region_silo_view from .mail import ActivityMailDebugView +@region_silo_view class DebugUnassignedEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.UNASSIGNED.value, "user_id": request.user.id} diff --git a/src/sentry/web/frontend/debug/debug_uptime_auto_detected_monitor_email.py b/src/sentry/web/frontend/debug/debug_uptime_auto_detected_monitor_email.py index b0dcf2e190fd71..29faec6560ffec 100644 --- a/src/sentry/web/frontend/debug/debug_uptime_auto_detected_monitor_email.py +++ b/src/sentry/web/frontend/debug/debug_uptime_auto_detected_monitor_email.py @@ -3,6 +3,8 @@ from django.http import HttpRequest, HttpResponse from django.views.generic import View +from sentry.web.frontend.base import region_silo_view + from .mail import MailPreview @@ -17,6 +19,7 @@ def get_context(): } +@region_silo_view class DebugUptimeAutoDetectedMonitorEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context() diff --git a/src/sentry/web/frontend/debug/debug_weekly_report.py b/src/sentry/web/frontend/debug/debug_weekly_report.py index de4ca6b517c898..1d9f22e55f3389 100644 --- a/src/sentry/web/frontend/debug/debug_weekly_report.py +++ b/src/sentry/web/frontend/debug/debug_weekly_report.py @@ -11,6 +11,7 @@ from sentry.tasks.summaries.weekly_reports import render_template_context from sentry.utils import loremipsum from sentry.utils.dates import floor_to_utc_day, to_datetime +from sentry.web.frontend.base import region_silo_view from .mail import MailPreviewView @@ -20,6 +21,7 @@ def get_random(request): return Random(seed) +@region_silo_view class DebugWeeklyReportView(MailPreviewView): def get_context(self, request): organization = Organization(id=1, slug="myorg", name="MyOrg") diff --git a/src/sentry/web/frontend/debug/mail.py b/src/sentry/web/frontend/debug/mail.py index 8aaa2b6bcfa943..d29f2e95c3fdae 100644 --- a/src/sentry/web/frontend/debug/mail.py +++ b/src/sentry/web/frontend/debug/mail.py @@ -67,6 +67,7 @@ from sentry.utils.http import absolute_uri from sentry.utils.samples import load_data from sentry.web.decorators import login_required +from sentry.web.frontend.base import control_silo_view, region_silo_view from sentry.web.helpers import render_to_response, render_to_string logger = logging.getLogger(__name__) @@ -410,6 +411,7 @@ def html_body(self): raise +@region_silo_view class ActivityMailDebugView(View): def get_activity(self, request: AuthenticatedHttpRequest, event): raise NotImplementedError @@ -446,6 +448,7 @@ def get(self, request: AuthenticatedHttpRequest) -> HttpResponse: ) +@region_silo_view @login_required def alert(request): random = get_random(request) @@ -489,6 +492,7 @@ def alert(request): ).render(request) +@region_silo_view @login_required def digest(request): random = get_random(request) @@ -611,6 +615,7 @@ def digest(request): ).render(request) +@region_silo_view @login_required def request_access(request): org = Organization(id=1, slug="sentry", name="Sentry org") @@ -631,6 +636,7 @@ def request_access(request): ).render(request) +@region_silo_view @login_required def request_access_for_another_member(request): org = Organization(id=1, slug="sentry", name="Sentry org") @@ -652,6 +658,7 @@ def request_access_for_another_member(request): ).render(request) +@region_silo_view @login_required def invitation(request): org = Organization(id=1, slug="example", name="Example") @@ -673,6 +680,7 @@ def invitation(request): ).render(request) +@region_silo_view @login_required def access_approved(request): org = Organization(id=1, slug="example", name="Example") @@ -690,6 +698,7 @@ def access_approved(request): ).render(request) +@region_silo_view @login_required def confirm_email(request): email = request.user.emails.first() @@ -711,6 +720,7 @@ def confirm_email(request): ).render(request) +@region_silo_view @login_required def recover_account(request): return MailPreview( @@ -731,6 +741,7 @@ def recover_account(request): ).render(request) +@control_silo_view @login_required def relocate_account(request): password_hash, __ = LostPasswordHash.objects.get_or_create(user_id=request.user.id) @@ -753,6 +764,7 @@ def relocate_account(request): ).render(request) +@region_silo_view @login_required def relocation_failed(request): return MailPreview( @@ -767,6 +779,7 @@ def relocation_failed(request): ).render(request) +@region_silo_view @login_required def relocation_started(request): return MailPreview( @@ -781,6 +794,7 @@ def relocation_started(request): ).render(request) +@region_silo_view @login_required def relocation_succeeded(request): return MailPreview( @@ -795,6 +809,7 @@ def relocation_succeeded(request): ).render(request) +@region_silo_view @login_required def org_delete_confirm(request): from sentry.models.auditlogentry import AuditLogEntry From 5ce044ecc50bb53e8546b84b95697548f6103f79 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Tue, 25 Nov 2025 18:42:46 -0500 Subject: [PATCH 02/11] Add internal_region_silo view decorator We need to mark debug email views as internal. They won't be reachable via cell routing. --- src/sentry/web/frontend/base.py | 24 ++++++++++++++++++++---- tests/sentry/web/frontend/test_base.py | 24 ++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/sentry/web/frontend/base.py b/src/sentry/web/frontend/base.py index 2e4a7c35f950d4..586b3aa4c78900 100644 --- a/src/sentry/web/frontend/base.py +++ b/src/sentry/web/frontend/base.py @@ -57,6 +57,12 @@ class ViewSiloLimit(SiloLimit): + def __init__(self, modes: SiloMode | Iterable[SiloMode], internal: bool = False) -> None: + if isinstance(modes, SiloMode): + modes = [modes] + self.modes = frozenset(modes) + self.internal = internal + def modify_endpoint_class(self, decorated_class: type[View]) -> type: dispatch_override = self.create_override(decorated_class.dispatch) new_class = type( @@ -71,7 +77,10 @@ def modify_endpoint_class(self, decorated_class: type[View]) -> type: return new_class def modify_endpoint_method(self, decorated_method: Callable[..., Any]) -> Callable[..., Any]: - return self.create_override(decorated_method) + decorated = self.create_override(decorated_method) + setattr(decorated, "silo_limit", self) + + return decorated def handle_when_unavailable( self, @@ -115,25 +124,32 @@ def __call__(self, decorated_obj: Any) -> Any: raise TypeError("`@ViewSiloLimit` must decorate a class or method") -control_silo_view = ViewSiloLimit(SiloMode.CONTROL) +control_silo_view = ViewSiloLimit([SiloMode.CONTROL]) """ Apply to frontend views that exist in CONTROL Silo If a request is received and the application is not in CONTROL/MONOLITH mode a 404 will be returned. """ -region_silo_view = ViewSiloLimit(SiloMode.REGION) +region_silo_view = ViewSiloLimit([SiloMode.REGION]) """ Apply to frontend views that exist in REGION Silo If a request is received and the application is not in REGION/MONOLITH mode a 404 will be returned. """ -all_silo_view = ViewSiloLimit(SiloMode.REGION, SiloMode.CONTROL, SiloMode.MONOLITH) +all_silo_view = ViewSiloLimit([SiloMode.REGION, SiloMode.CONTROL, SiloMode.MONOLITH]) """ Apply to frontend views that respond in both CONTROL and REGION mode. """ +internal_region_silo_view = ViewSiloLimit([SiloMode.REGION], internal=True) +""" +Apply to frontend views that exist in REGION Silo +and are not accessible via cell routing. +This is generally for debug/development views. +""" + class _HasRespond(Protocol): active_organization: RpcUserOrganizationContext | None diff --git a/tests/sentry/web/frontend/test_base.py b/tests/sentry/web/frontend/test_base.py index 0e7e8dcd904bdb..96e638e014cd3e 100644 --- a/tests/sentry/web/frontend/test_base.py +++ b/tests/sentry/web/frontend/test_base.py @@ -9,11 +9,11 @@ class ViewSiloLimitTest(APITestCase): def _test_active_on(self, endpoint_mode, active_mode, expect_to_be_active): - @ViewSiloLimit(endpoint_mode) + @ViewSiloLimit([endpoint_mode]) def view_func(request): pass - @ViewSiloLimit(endpoint_mode) + @ViewSiloLimit([endpoint_mode]) class DummyView(BaseView): def get(self, request): return Response("dummy-view", 200) @@ -43,3 +43,23 @@ def test_with_inactive_mode(self) -> None: def test_with_monolith_mode(self) -> None: self._test_active_on(SiloMode.REGION, SiloMode.MONOLITH, True) self._test_active_on(SiloMode.CONTROL, SiloMode.MONOLITH, True) + + def test_sets_silo_limit_on_function(self) -> None: + @ViewSiloLimit([SiloMode.CONTROL]) + def view_func(request): + pass + + assert view_func.silo_limit, "Should have silo_limit set" + assert view_func.silo_limit.modes, "Should have silo_limit.modes set" + assert not view_func.silo_limit.internal, "Not internal by default" + + def test_internal_attribute(self) -> None: + @ViewSiloLimit([SiloMode.REGION], internal=True) + def view_func(request): + pass + + assert view_func.silo_limit, "Should have silo_limit set" + assert view_func.silo_limit.modes, "Should have silo_limit.modes set" + assert len(view_func.silo_limit.modes) == 1 + assert SiloMode.REGION in view_func.silo_limit.modes + assert view_func.silo_limit.internal, "Should be marked as internal" From 1447dddb24e3b298a71fea33a38f72659d8502ba Mon Sep 17 00:00:00 2001 From: Mark Story Date: Tue, 25 Nov 2025 18:45:51 -0500 Subject: [PATCH 03/11] Use internal_region_silo_view on debug email views --- .../web/frontend/debug/debug_auth_views.py | 6 ++-- ...ebug_codeowners_auto_sync_failure_email.py | 4 +-- .../debug/debug_cron_broken_monitor_email.py | 4 +-- .../debug/debug_cron_muted_monitor_email.py | 4 +-- .../web/frontend/debug/debug_error_embed.py | 4 +-- .../frontend/debug/debug_feedback_issue.py | 4 +-- .../web/frontend/debug/debug_generic_issue.py | 4 +-- .../debug/debug_incident_trigger_email.py | 4 +-- .../debug/debug_invalid_identity_email.py | 4 +-- .../frontend/debug/debug_mfa_added_email.py | 4 +-- .../frontend/debug/debug_mfa_removed_email.py | 4 +-- .../debug/debug_missing_member_nudge_email.py | 4 +-- .../frontend/debug/debug_new_release_email.py | 4 +-- .../debug/debug_new_user_feedback_email.py | 4 +-- .../web/frontend/debug/debug_note_email.py | 4 +-- .../frontend/debug/debug_oauth_authorize.py | 4 +-- .../debug_onboarding_continuation_email.py | 4 +-- .../debug_organization_integration_request.py | 4 +-- .../debug_organization_invite_request.py | 4 +-- .../debug/debug_organization_join_request.py | 4 +-- .../debug/debug_password_changed_email.py | 4 +-- .../frontend/debug/debug_performance_issue.py | 4 +-- .../debug_recovery_codes_regenerated_email.py | 4 +-- .../frontend/debug/debug_regression_email.py | 6 ++-- .../frontend/debug/debug_resolved_email.py | 4 +-- .../debug/debug_resolved_in_release_email.py | 6 ++-- .../frontend/debug/debug_setup_2fa_email.py | 4 +-- .../frontend/debug/debug_sso_link_email.py | 8 +++--- .../web/frontend/debug/debug_trigger_error.py | 4 +-- .../debug_unable_to_delete_repository.py | 4 +-- .../debug_unable_to_fetch_commits_email.py | 4 +-- .../frontend/debug/debug_unassigned_email.py | 4 +-- ...ebug_uptime_auto_detected_monitor_email.py | 4 +-- .../web/frontend/debug/debug_weekly_report.py | 4 +-- src/sentry/web/frontend/debug/mail.py | 28 +++++++++---------- 35 files changed, 87 insertions(+), 87 deletions(-) diff --git a/src/sentry/web/frontend/debug/debug_auth_views.py b/src/sentry/web/frontend/debug/debug_auth_views.py index 29d332058f2873..c0393652000402 100644 --- a/src/sentry/web/frontend/debug/debug_auth_views.py +++ b/src/sentry/web/frontend/debug/debug_auth_views.py @@ -2,11 +2,11 @@ from django.views.generic import View from sentry.users.models.user import User -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from sentry.web.helpers import render_to_response -@region_silo_view +@internal_region_silo_view class DebugAuthConfirmIdentity(View): def get(self, request: HttpRequest) -> HttpResponse: auth_identity = {"id": "bar@example.com", "email": "bar@example.com"} @@ -23,7 +23,7 @@ def get(self, request: HttpRequest) -> HttpResponse: ) -@region_silo_view +@internal_region_silo_view class DebugAuthConfirmLink(View): def get(self, request: HttpRequest) -> HttpResponse: auth_identity = {"id": "bar@example.com", "email": "test1@example.com"} diff --git a/src/sentry/web/frontend/debug/debug_codeowners_auto_sync_failure_email.py b/src/sentry/web/frontend/debug/debug_codeowners_auto_sync_failure_email.py index 3251832b4b32d5..87329705b1c273 100644 --- a/src/sentry/web/frontend/debug/debug_codeowners_auto_sync_failure_email.py +++ b/src/sentry/web/frontend/debug/debug_codeowners_auto_sync_failure_email.py @@ -6,12 +6,12 @@ from sentry.models.project import Project from sentry.notifications.notifications.codeowners_auto_sync import AutoSyncNotification from sentry.users.models.user import User -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import render_preview_email_for_notification -@region_silo_view +@internal_region_silo_view class DebugCodeOwnersAutoSyncFailureView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="petal", name="Petal") diff --git a/src/sentry/web/frontend/debug/debug_cron_broken_monitor_email.py b/src/sentry/web/frontend/debug/debug_cron_broken_monitor_email.py index f71d15e595dafd..2108995d4520f9 100644 --- a/src/sentry/web/frontend/debug/debug_cron_broken_monitor_email.py +++ b/src/sentry/web/frontend/debug/debug_cron_broken_monitor_email.py @@ -3,7 +3,7 @@ from django.http import HttpRequest, HttpResponse from django.views.generic import View -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview @@ -19,7 +19,7 @@ def get_context(): } -@region_silo_view +@internal_region_silo_view class DebugCronBrokenMonitorEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context() diff --git a/src/sentry/web/frontend/debug/debug_cron_muted_monitor_email.py b/src/sentry/web/frontend/debug/debug_cron_muted_monitor_email.py index a21ed5f4cd4b40..ddb3aa68a4a0c4 100644 --- a/src/sentry/web/frontend/debug/debug_cron_muted_monitor_email.py +++ b/src/sentry/web/frontend/debug/debug_cron_muted_monitor_email.py @@ -3,7 +3,7 @@ from django.http import HttpRequest, HttpResponse from django.views.generic import View -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview @@ -19,7 +19,7 @@ def get_context(): } -@region_silo_view +@internal_region_silo_view class DebugCronMutedMonitorEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context() diff --git a/src/sentry/web/frontend/debug/debug_error_embed.py b/src/sentry/web/frontend/debug/debug_error_embed.py index 1968d73f5ef865..c082378e33f852 100644 --- a/src/sentry/web/frontend/debug/debug_error_embed.py +++ b/src/sentry/web/frontend/debug/debug_error_embed.py @@ -5,11 +5,11 @@ from django.views.generic import View from sentry.models.projectkey import ProjectKey -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from sentry.web.helpers import render_to_response -@region_silo_view +@internal_region_silo_view class DebugErrorPageEmbedView(View): def _get_project_key(self): return ProjectKey.objects.filter(project=settings.SENTRY_PROJECT)[0] diff --git a/src/sentry/web/frontend/debug/debug_feedback_issue.py b/src/sentry/web/frontend/debug/debug_feedback_issue.py index c7dc89d5f9fb0f..46a195f578d973 100644 --- a/src/sentry/web/frontend/debug/debug_feedback_issue.py +++ b/src/sentry/web/frontend/debug/debug_feedback_issue.py @@ -8,12 +8,12 @@ from sentry.notifications.utils import get_generic_data from sentry.notifications.utils.links import get_group_settings_link, get_rules from sentry.utils import json -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import COMMIT_EXAMPLE, MailPreview, make_feedback_issue -@region_silo_view +@internal_region_silo_view class DebugFeedbackIssueEmailView(View): def get(self, request): org = Organization(id=1, slug="example", name="Example") diff --git a/src/sentry/web/frontend/debug/debug_generic_issue.py b/src/sentry/web/frontend/debug/debug_generic_issue.py index 8a3a8e4a1852dc..80ebb5075f5175 100644 --- a/src/sentry/web/frontend/debug/debug_generic_issue.py +++ b/src/sentry/web/frontend/debug/debug_generic_issue.py @@ -9,12 +9,12 @@ from sentry.notifications.utils import get_generic_data from sentry.notifications.utils.links import get_group_settings_link, get_rules from sentry.utils import json -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import COMMIT_EXAMPLE, MailPreview, make_generic_event -@region_silo_view +@internal_region_silo_view class DebugGenericIssueEmailView(View): def get(self, request): org = Organization(id=1, slug="example", name="Example") diff --git a/src/sentry/web/frontend/debug/debug_incident_trigger_email.py b/src/sentry/web/frontend/debug/debug_incident_trigger_email.py index d9d40103f9d131..2b60e2eff75262 100644 --- a/src/sentry/web/frontend/debug/debug_incident_trigger_email.py +++ b/src/sentry/web/frontend/debug/debug_incident_trigger_email.py @@ -18,7 +18,7 @@ from sentry.models.project import Project from sentry.snuba.models import SnubaQuery from sentry.users.models.user import User -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreviewView @@ -27,7 +27,7 @@ class MockedIncidentTrigger: date_added = timezone.now() -@region_silo_view +@internal_region_silo_view class DebugIncidentTriggerEmailView(MailPreviewView): @mock.patch( "sentry.incidents.models.incident.IncidentTrigger.objects.get", diff --git a/src/sentry/web/frontend/debug/debug_invalid_identity_email.py b/src/sentry/web/frontend/debug/debug_invalid_identity_email.py index 2e3035e6a3e2d2..fb9d354dc83192 100644 --- a/src/sentry/web/frontend/debug/debug_invalid_identity_email.py +++ b/src/sentry/web/frontend/debug/debug_invalid_identity_email.py @@ -2,13 +2,13 @@ from django.views.generic import View from sentry.tasks.commits import generate_invalid_identity_email -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from social_auth.models import UserSocialAuth from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugInvalidIdentityEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: assert request.user.is_authenticated diff --git a/src/sentry/web/frontend/debug/debug_mfa_added_email.py b/src/sentry/web/frontend/debug/debug_mfa_added_email.py index aca819f106173b..9fb12c941a1d11 100644 --- a/src/sentry/web/frontend/debug/debug_mfa_added_email.py +++ b/src/sentry/web/frontend/debug/debug_mfa_added_email.py @@ -6,12 +6,12 @@ from sentry.security.emails import generate_security_email from sentry.users.models.authenticator import Authenticator -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugMfaAddedEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: if isinstance(request.user, AnonymousUser): diff --git a/src/sentry/web/frontend/debug/debug_mfa_removed_email.py b/src/sentry/web/frontend/debug/debug_mfa_removed_email.py index 44fa2c7c70b6e0..b9dca7d0032b08 100644 --- a/src/sentry/web/frontend/debug/debug_mfa_removed_email.py +++ b/src/sentry/web/frontend/debug/debug_mfa_removed_email.py @@ -6,12 +6,12 @@ from sentry.security.emails import generate_security_email from sentry.users.models.authenticator import Authenticator -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugMfaRemovedEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: if isinstance(request.user, AnonymousUser): diff --git a/src/sentry/web/frontend/debug/debug_missing_member_nudge_email.py b/src/sentry/web/frontend/debug/debug_missing_member_nudge_email.py index ad7666cf5daf0b..19e8bbeee8aa0a 100644 --- a/src/sentry/web/frontend/debug/debug_missing_member_nudge_email.py +++ b/src/sentry/web/frontend/debug/debug_missing_member_nudge_email.py @@ -2,12 +2,12 @@ from django.views.generic import View from sentry.models.organization import Organization -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugMissingMembersNudgeView(View): def get(self, request: HttpRequest) -> HttpResponse: self.organization = Organization(id=1, slug="organization", name="My Company") diff --git a/src/sentry/web/frontend/debug/debug_new_release_email.py b/src/sentry/web/frontend/debug/debug_new_release_email.py index bc1079b1e47c92..d89047b7e92d85 100644 --- a/src/sentry/web/frontend/debug/debug_new_release_email.py +++ b/src/sentry/web/frontend/debug/debug_new_release_email.py @@ -14,12 +14,12 @@ from sentry.notifications.types import GroupSubscriptionReason from sentry.users.models.user import User from sentry.utils.http import absolute_uri -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugNewReleaseEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="organization", name="My Company") diff --git a/src/sentry/web/frontend/debug/debug_new_user_feedback_email.py b/src/sentry/web/frontend/debug/debug_new_user_feedback_email.py index 90ca5a14006e4c..6e8e6e535cab25 100644 --- a/src/sentry/web/frontend/debug/debug_new_user_feedback_email.py +++ b/src/sentry/web/frontend/debug/debug_new_user_feedback_email.py @@ -5,12 +5,12 @@ from sentry.models.project import Project from sentry.utils.http import absolute_uri from sentry.utils.samples import create_sample_event -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugNewUserFeedbackEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="organization", name="My Company") diff --git a/src/sentry/web/frontend/debug/debug_note_email.py b/src/sentry/web/frontend/debug/debug_note_email.py index 2d770b1ca1fb6c..fc507c7d02e3c9 100644 --- a/src/sentry/web/frontend/debug/debug_note_email.py +++ b/src/sentry/web/frontend/debug/debug_note_email.py @@ -1,12 +1,12 @@ from django.http import HttpRequest from sentry.types.activity import ActivityType -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import ActivityMailDebugView, get_random, make_message -@region_silo_view +@internal_region_silo_view class DebugNoteEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): random = get_random(request) diff --git a/src/sentry/web/frontend/debug/debug_oauth_authorize.py b/src/sentry/web/frontend/debug/debug_oauth_authorize.py index 833895f069ccbc..7c7d3e01e5c468 100644 --- a/src/sentry/web/frontend/debug/debug_oauth_authorize.py +++ b/src/sentry/web/frontend/debug/debug_oauth_authorize.py @@ -2,11 +2,11 @@ from django.views.generic import View from sentry.models.apiapplication import ApiApplication -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from sentry.web.helpers import render_to_response -@region_silo_view +@internal_region_silo_view class DebugOAuthAuthorizeView(View): def get(self, request: HttpRequest) -> HttpResponse: application = ApiApplication( diff --git a/src/sentry/web/frontend/debug/debug_onboarding_continuation_email.py b/src/sentry/web/frontend/debug/debug_onboarding_continuation_email.py index 7972326ce12960..67e4b9efb1467a 100644 --- a/src/sentry/web/frontend/debug/debug_onboarding_continuation_email.py +++ b/src/sentry/web/frontend/debug/debug_onboarding_continuation_email.py @@ -4,12 +4,12 @@ from sentry.api.endpoints.organization_onboarding_continuation_email import get_request_builder_args from sentry.models.organization import Organization from sentry.users.models.user import User -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from sentry.web.frontend.debug.mail import MailPreviewAdapter from sentry.web.helpers import render_to_response -@region_silo_view +@internal_region_silo_view class DebugOrganizationOnboardingContinuationEmail(View): def get(self, request: HttpRequest) -> HttpResponse: platforms = request.GET.getlist("platforms", ["javascript", "python", "flutter"]) diff --git a/src/sentry/web/frontend/debug/debug_organization_integration_request.py b/src/sentry/web/frontend/debug/debug_organization_integration_request.py index e5b9b350bdb6ef..c01c645798c449 100644 --- a/src/sentry/web/frontend/debug/debug_organization_integration_request.py +++ b/src/sentry/web/frontend/debug/debug_organization_integration_request.py @@ -8,12 +8,12 @@ IntegrationRequestNotification, ) from sentry.users.models.user import User -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import render_preview_email_for_notification -@region_silo_view +@internal_region_silo_view class DebugOrganizationIntegrationRequestEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="default", name="Default") diff --git a/src/sentry/web/frontend/debug/debug_organization_invite_request.py b/src/sentry/web/frontend/debug/debug_organization_invite_request.py index 643cba8acefe56..190ceda92f302f 100644 --- a/src/sentry/web/frontend/debug/debug_organization_invite_request.py +++ b/src/sentry/web/frontend/debug/debug_organization_invite_request.py @@ -5,12 +5,12 @@ from sentry.models.organizationmember import InviteStatus, OrganizationMember from sentry.notifications.notifications.organization_request import InviteRequestNotification from sentry.users.models.user import User -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import render_preview_email_for_notification -@region_silo_view +@internal_region_silo_view class DebugOrganizationInviteRequestEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="default", name="Default") diff --git a/src/sentry/web/frontend/debug/debug_organization_join_request.py b/src/sentry/web/frontend/debug/debug_organization_join_request.py index 45ca0c1f55f164..9986512f259715 100644 --- a/src/sentry/web/frontend/debug/debug_organization_join_request.py +++ b/src/sentry/web/frontend/debug/debug_organization_join_request.py @@ -5,12 +5,12 @@ from sentry.models.organizationmember import InviteStatus, OrganizationMember from sentry.notifications.notifications.organization_request import JoinRequestNotification from sentry.users.models.user import User -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import render_preview_email_for_notification -@region_silo_view +@internal_region_silo_view class DebugOrganizationJoinRequestEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="default", name="Default") diff --git a/src/sentry/web/frontend/debug/debug_password_changed_email.py b/src/sentry/web/frontend/debug/debug_password_changed_email.py index 1ddda321a6d5ff..ccae49c5cc252a 100644 --- a/src/sentry/web/frontend/debug/debug_password_changed_email.py +++ b/src/sentry/web/frontend/debug/debug_password_changed_email.py @@ -5,12 +5,12 @@ from sentry.security.emails import generate_security_email from sentry.utils.auth import AuthenticatedHttpRequest -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugPasswordChangedEmailView(View): def get(self, request: AuthenticatedHttpRequest) -> HttpResponse: email = generate_security_email( diff --git a/src/sentry/web/frontend/debug/debug_performance_issue.py b/src/sentry/web/frontend/debug/debug_performance_issue.py index 59f47485cef1ad..b100ee9d9f72f5 100644 --- a/src/sentry/web/frontend/debug/debug_performance_issue.py +++ b/src/sentry/web/frontend/debug/debug_performance_issue.py @@ -9,12 +9,12 @@ get_transaction_data, ) from sentry.utils import json -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import COMMIT_EXAMPLE, MailPreview, get_shared_context, make_performance_event -@region_silo_view +@internal_region_silo_view class DebugPerformanceIssueEmailView(View): def get(self, request, sample_name="transaction-n-plus-one"): project = Project.objects.get(id=1) diff --git a/src/sentry/web/frontend/debug/debug_recovery_codes_regenerated_email.py b/src/sentry/web/frontend/debug/debug_recovery_codes_regenerated_email.py index 99226b06200a4b..6f8cfa32759761 100644 --- a/src/sentry/web/frontend/debug/debug_recovery_codes_regenerated_email.py +++ b/src/sentry/web/frontend/debug/debug_recovery_codes_regenerated_email.py @@ -6,12 +6,12 @@ from sentry.security.emails import generate_security_email from sentry.users.models.authenticator import Authenticator from sentry.utils.auth import AuthenticatedHttpRequest -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugRecoveryCodesRegeneratedEmailView(View): def get(self, request: AuthenticatedHttpRequest) -> HttpResponse: authenticator = Authenticator(id=0, type=3, user_id=request.user.id) # u2f diff --git a/src/sentry/web/frontend/debug/debug_regression_email.py b/src/sentry/web/frontend/debug/debug_regression_email.py index bb9a2bba70d38d..9395f4d51df271 100644 --- a/src/sentry/web/frontend/debug/debug_regression_email.py +++ b/src/sentry/web/frontend/debug/debug_regression_email.py @@ -1,18 +1,18 @@ from django.http import HttpRequest from sentry.types.activity import ActivityType -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import ActivityMailDebugView -@region_silo_view +@internal_region_silo_view class DebugRegressionEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.SET_REGRESSION.value} -@region_silo_view +@internal_region_silo_view class DebugRegressionReleaseEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.SET_REGRESSION.value, "data": {"version": "abcdef"}} diff --git a/src/sentry/web/frontend/debug/debug_resolved_email.py b/src/sentry/web/frontend/debug/debug_resolved_email.py index b2441455038d9b..59d7652ecac3fe 100644 --- a/src/sentry/web/frontend/debug/debug_resolved_email.py +++ b/src/sentry/web/frontend/debug/debug_resolved_email.py @@ -1,12 +1,12 @@ from django.http import HttpRequest from sentry.types.activity import ActivityType -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import ActivityMailDebugView -@region_silo_view +@internal_region_silo_view class DebugResolvedEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.SET_RESOLVED.value} diff --git a/src/sentry/web/frontend/debug/debug_resolved_in_release_email.py b/src/sentry/web/frontend/debug/debug_resolved_in_release_email.py index 6d313f1bee9d57..6f908f2d4ba799 100644 --- a/src/sentry/web/frontend/debug/debug_resolved_in_release_email.py +++ b/src/sentry/web/frontend/debug/debug_resolved_in_release_email.py @@ -1,18 +1,18 @@ from django.http import HttpRequest from sentry.types.activity import ActivityType -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import ActivityMailDebugView -@region_silo_view +@internal_region_silo_view class DebugResolvedInReleaseEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.SET_RESOLVED_IN_RELEASE.value, "data": {"version": "abcdef"}} -@region_silo_view +@internal_region_silo_view class DebugResolvedInReleaseUpcomingEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.SET_RESOLVED_IN_RELEASE.value, "data": {"version": ""}} diff --git a/src/sentry/web/frontend/debug/debug_setup_2fa_email.py b/src/sentry/web/frontend/debug/debug_setup_2fa_email.py index e87a3d96ea4fad..8d965e885aa620 100644 --- a/src/sentry/web/frontend/debug/debug_setup_2fa_email.py +++ b/src/sentry/web/frontend/debug/debug_setup_2fa_email.py @@ -3,12 +3,12 @@ from sentry.models.organization import Organization from sentry.models.organizationmember import OrganizationMember -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugSetup2faEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(id=1, slug="organization", name="sentry corp") diff --git a/src/sentry/web/frontend/debug/debug_sso_link_email.py b/src/sentry/web/frontend/debug/debug_sso_link_email.py index 6aa5484034ceb1..339539049d9304 100644 --- a/src/sentry/web/frontend/debug/debug_sso_link_email.py +++ b/src/sentry/web/frontend/debug/debug_sso_link_email.py @@ -3,7 +3,7 @@ from sentry.auth.providers.dummy import DummyProvider from sentry.models.organization import Organization -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview @@ -15,7 +15,7 @@ def get_context(request): return {"organization": org, "actor_email": request.user.email, "provider": provider} -@region_silo_view +@internal_region_silo_view class DebugSsoLinkedEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context(request) @@ -27,7 +27,7 @@ def get(self, request: HttpRequest) -> HttpResponse: ).render(request) -@region_silo_view +@internal_region_silo_view class DebugSsoUnlinkedEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context(request) @@ -40,7 +40,7 @@ def get(self, request: HttpRequest) -> HttpResponse: ).render(request) -@region_silo_view +@internal_region_silo_view class DebugSsoUnlinkedNoPasswordEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context(request) diff --git a/src/sentry/web/frontend/debug/debug_trigger_error.py b/src/sentry/web/frontend/debug/debug_trigger_error.py index 5bc5d685c75706..d14bc06f707f17 100644 --- a/src/sentry/web/frontend/debug/debug_trigger_error.py +++ b/src/sentry/web/frontend/debug/debug_trigger_error.py @@ -3,11 +3,11 @@ from django.views.generic import View from sentry.utils.sdk import capture_exception -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from sentry.web.frontend.error_500 import Error500View -@region_silo_view +@internal_region_silo_view class DebugTriggerErrorView(View): def get(self, request: HttpRequest) -> HttpResponseBase: try: diff --git a/src/sentry/web/frontend/debug/debug_unable_to_delete_repository.py b/src/sentry/web/frontend/debug/debug_unable_to_delete_repository.py index cb82a353bbe718..ce35b7657fdb5c 100644 --- a/src/sentry/web/frontend/debug/debug_unable_to_delete_repository.py +++ b/src/sentry/web/frontend/debug/debug_unable_to_delete_repository.py @@ -3,12 +3,12 @@ from sentry.models.repository import Repository from sentry.plugins.providers.dummy import DummyRepositoryProvider -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugUnableToDeleteRepository(View): def get(self, request: HttpRequest) -> HttpResponse: repo = Repository(name="getsentry/sentry", provider="dummy") diff --git a/src/sentry/web/frontend/debug/debug_unable_to_fetch_commits_email.py b/src/sentry/web/frontend/debug/debug_unable_to_fetch_commits_email.py index 6846df5a1d0b59..fb7e17eb21359d 100644 --- a/src/sentry/web/frontend/debug/debug_unable_to_fetch_commits_email.py +++ b/src/sentry/web/frontend/debug/debug_unable_to_fetch_commits_email.py @@ -5,12 +5,12 @@ from sentry.models.release import Release from sentry.models.repository import Repository from sentry.tasks.commits import generate_fetch_commits_error_email -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview -@region_silo_view +@internal_region_silo_view class DebugUnableToFetchCommitsEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: org = Organization(slug="myorg") diff --git a/src/sentry/web/frontend/debug/debug_unassigned_email.py b/src/sentry/web/frontend/debug/debug_unassigned_email.py index 8cf59cdd38915e..c8eebfa6016921 100644 --- a/src/sentry/web/frontend/debug/debug_unassigned_email.py +++ b/src/sentry/web/frontend/debug/debug_unassigned_email.py @@ -1,12 +1,12 @@ from django.http import HttpRequest from sentry.types.activity import ActivityType -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import ActivityMailDebugView -@region_silo_view +@internal_region_silo_view class DebugUnassignedEmailView(ActivityMailDebugView): def get_activity(self, request: HttpRequest, event): return {"type": ActivityType.UNASSIGNED.value, "user_id": request.user.id} diff --git a/src/sentry/web/frontend/debug/debug_uptime_auto_detected_monitor_email.py b/src/sentry/web/frontend/debug/debug_uptime_auto_detected_monitor_email.py index 29faec6560ffec..cb183f54382f44 100644 --- a/src/sentry/web/frontend/debug/debug_uptime_auto_detected_monitor_email.py +++ b/src/sentry/web/frontend/debug/debug_uptime_auto_detected_monitor_email.py @@ -3,7 +3,7 @@ from django.http import HttpRequest, HttpResponse from django.views.generic import View -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreview @@ -19,7 +19,7 @@ def get_context(): } -@region_silo_view +@internal_region_silo_view class DebugUptimeAutoDetectedMonitorEmailView(View): def get(self, request: HttpRequest) -> HttpResponse: context = get_context() diff --git a/src/sentry/web/frontend/debug/debug_weekly_report.py b/src/sentry/web/frontend/debug/debug_weekly_report.py index 1d9f22e55f3389..7f813d3c1578bc 100644 --- a/src/sentry/web/frontend/debug/debug_weekly_report.py +++ b/src/sentry/web/frontend/debug/debug_weekly_report.py @@ -11,7 +11,7 @@ from sentry.tasks.summaries.weekly_reports import render_template_context from sentry.utils import loremipsum from sentry.utils.dates import floor_to_utc_day, to_datetime -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import internal_region_silo_view from .mail import MailPreviewView @@ -21,7 +21,7 @@ def get_random(request): return Random(seed) -@region_silo_view +@internal_region_silo_view class DebugWeeklyReportView(MailPreviewView): def get_context(self, request): organization = Organization(id=1, slug="myorg", name="MyOrg") diff --git a/src/sentry/web/frontend/debug/mail.py b/src/sentry/web/frontend/debug/mail.py index d29f2e95c3fdae..19c98944c9dd59 100644 --- a/src/sentry/web/frontend/debug/mail.py +++ b/src/sentry/web/frontend/debug/mail.py @@ -67,7 +67,7 @@ from sentry.utils.http import absolute_uri from sentry.utils.samples import load_data from sentry.web.decorators import login_required -from sentry.web.frontend.base import control_silo_view, region_silo_view +from sentry.web.frontend.base import control_silo_view, internal_region_silo_view from sentry.web.helpers import render_to_response, render_to_string logger = logging.getLogger(__name__) @@ -411,7 +411,7 @@ def html_body(self): raise -@region_silo_view +@internal_region_silo_view class ActivityMailDebugView(View): def get_activity(self, request: AuthenticatedHttpRequest, event): raise NotImplementedError @@ -448,7 +448,7 @@ def get(self, request: AuthenticatedHttpRequest) -> HttpResponse: ) -@region_silo_view +@internal_region_silo_view @login_required def alert(request): random = get_random(request) @@ -492,7 +492,7 @@ def alert(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def digest(request): random = get_random(request) @@ -615,7 +615,7 @@ def digest(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def request_access(request): org = Organization(id=1, slug="sentry", name="Sentry org") @@ -636,7 +636,7 @@ def request_access(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def request_access_for_another_member(request): org = Organization(id=1, slug="sentry", name="Sentry org") @@ -658,7 +658,7 @@ def request_access_for_another_member(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def invitation(request): org = Organization(id=1, slug="example", name="Example") @@ -680,7 +680,7 @@ def invitation(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def access_approved(request): org = Organization(id=1, slug="example", name="Example") @@ -698,7 +698,7 @@ def access_approved(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def confirm_email(request): email = request.user.emails.first() @@ -720,7 +720,7 @@ def confirm_email(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def recover_account(request): return MailPreview( @@ -764,7 +764,7 @@ def relocate_account(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def relocation_failed(request): return MailPreview( @@ -779,7 +779,7 @@ def relocation_failed(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def relocation_started(request): return MailPreview( @@ -794,7 +794,7 @@ def relocation_started(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def relocation_succeeded(request): return MailPreview( @@ -809,7 +809,7 @@ def relocation_succeeded(request): ).render(request) -@region_silo_view +@internal_region_silo_view @login_required def org_delete_confirm(request): from sentry.models.auditlogentry import AuditLogEntry From 355adbb39e6c8f736d2ae73f719849a15cad6651 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 26 Nov 2025 10:43:56 -0500 Subject: [PATCH 04/11] Update controlsilo URL list --- static/app/data/controlsiloUrlPatterns.ts | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/static/app/data/controlsiloUrlPatterns.ts b/static/app/data/controlsiloUrlPatterns.ts index 844dfa5a4fa04c..236c8146cfc59d 100644 --- a/static/app/data/controlsiloUrlPatterns.ts +++ b/static/app/data/controlsiloUrlPatterns.ts @@ -2,6 +2,7 @@ // To update it run `getsentry django generate_controlsilo_urls --format=js --output=/path/to/thisfile.ts` const patterns: RegExp[] = [ new RegExp('^remote/heroku/resources(?:/[^/]+)?$'), + new RegExp('^remote/heroku/sso-login/?$'), new RegExp('^remote/beacon/$'), new RegExp('^remote/newsletter/unsubscribe/$'), new RegExp('^remote/github-copilot/oauth/$'), @@ -16,8 +17,13 @@ const patterns: RegExp[] = [ new RegExp('^remote/vercel/v1/installations/[^/]+/resources$'), new RegExp('^remote/vercel/v1/installations/[^/]+/resources/[^/]+$'), new RegExp('^remote/vercel/oauth$'), + new RegExp('^$'), + new RegExp('^support/$'), + new RegExp('^identity/login/[^/]+/$'), new RegExp('^orgredirect/try-business/$'), new RegExp('^orgredirect/'), + new RegExp('^associate/complete/[^/]+/$'), + new RegExp('^associate/[^/]+/$'), new RegExp('^api/0/staff-auth/$'), new RegExp('^api/0/signup/$'), new RegExp('^api/0/audit-logs/$'), @@ -50,6 +56,7 @@ const patterns: RegExp[] = [ new RegExp('^api/0/sponsored_account_request/$'), new RegExp('^api/0/migrate_to_hosted/$'), new RegExp('^api/0/sponsored_education_account/$'), + new RegExp('^organizations/[^/]+/documents/[^/]+/?$'), new RegExp('^api/0/organizations/[^/]+/broadcasts/$'), new RegExp('^api/0/billing-config/$'), new RegExp('^api/0/auth-details/$'), @@ -58,8 +65,15 @@ const patterns: RegExp[] = [ new RegExp('^_admin/'), new RegExp('^500/'), new RegExp('^404/'), + new RegExp('^403-csrf-failure/'), + new RegExp('^debug/mail/relocate-account/$'), new RegExp('^_warmup/$'), new RegExp('^api/client-config/?$'), + new RegExp('^api/relay/.*$'), + new RegExp('^_static/dist/[^/]+/[^/]+$'), + new RegExp('^_static/(?:[^/]+/)?[^/]+/[^/]+$'), + new RegExp('^get-cli/$'), + new RegExp('^get-cli/[^/]+/[^/]+/?$'), new RegExp('^api/0/organizations/[^/]+/api-keys/$'), new RegExp('^api/0/organizations/[^/]+/api-keys/[^/]+/$'), new RegExp('^api/0/organizations/[^/]+/audit-logs/$'), @@ -172,15 +186,28 @@ const patterns: RegExp[] = [ new RegExp('^auth/channel/[^/]+/[^/]+/$'), new RegExp('^auth/link/[^/]+/$'), new RegExp('^auth/2fa/$'), + new RegExp('^auth/2fa/u2fappid\\.json$'), new RegExp('^auth/sso/$'), new RegExp('^auth/logout/$'), new RegExp('^auth/reactivate/$'), new RegExp('^auth/register/$'), new RegExp('^auth/close/$'), + new RegExp('^login-redirect/$'), new RegExp('^account/sudo/$'), + new RegExp('^account/confirm-email/$'), + new RegExp('^account/confirm-email/[^/]+/[^/]+/$'), + new RegExp('^account/confirm-signed-email/[^/]+/$'), new RegExp('^account/user-confirm/[^/]+/$'), + new RegExp('^account/recover/$'), + new RegExp('^account/recover/confirm/[^/]+/[^/]+/$'), + new RegExp('^account/relocation/reclaim/[^/]+/$'), + new RegExp('^account/password/confirm/[^/]+/[^/]+/$'), + new RegExp('^account/relocation/confirm/[^/]+/[^/]+/$'), new RegExp('^account/settings/identities/associate/[^/]+/[^/]+/[^/]+/$'), new RegExp('^account/settings/wizard/[^/]+/$'), + new RegExp('^account/settings/social/associate/complete/[^/]+/$'), + new RegExp('^account/settings/social/associate/[^/]+/$'), + new RegExp('^auth/sso/account/settings/social/associate/complete/[^/]+/$'), new RegExp('^out/$'), new RegExp('^settings/organization/auth/configure/$'), new RegExp('^disabled-member/'), @@ -190,6 +217,9 @@ const patterns: RegExp[] = [ new RegExp('^avatar/[^/]+/$'), new RegExp('^sentry-app-avatar/[^/]+/$'), new RegExp('^doc-integration-avatar/[^/]+/$'), + new RegExp('^robots\\.txt$'), + new RegExp('^\\.well-known/security\\.txt$'), + new RegExp('^\\.well-known/mcp\\.json$'), new RegExp('^extensions/[^/]+/setup/$'), new RegExp('^extensions/jira/ui-hook/$'), new RegExp('^extensions/jira/descriptor/$'), From ade9b54a9872af40bdc6eff32cd115d55e56ca74 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 26 Nov 2025 10:49:50 -0500 Subject: [PATCH 05/11] Fix duplicate monolith mode in error messages --- src/sentry/silo/base.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sentry/silo/base.py b/src/sentry/silo/base.py index d7e20653ce80ac..ac41024a4283d7 100644 --- a/src/sentry/silo/base.py +++ b/src/sentry/silo/base.py @@ -158,10 +158,11 @@ def override(*args: P.args, **kwargs: P.kwargs) -> R: if is_available: return original_method(*args, **kwargs) else: + modes = self.modes + if SiloMode.MONOLITH not in modes: + modes = itertools.chain([SiloMode.MONOLITH], modes) handler = self.handle_when_unavailable( - original_method, - SiloMode.get_current_mode(), - itertools.chain([SiloMode.MONOLITH], self.modes), + original_method, SiloMode.get_current_mode(), modes ) return handler(*args, **kwargs) From e550643426e935eff6a30da28a012596e2b32242 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 26 Nov 2025 11:35:02 -0500 Subject: [PATCH 06/11] Add more silo annotations to plugin and debug views. --- src/sentry/charts/endpoints.py | 2 ++ src/sentry/web/frontend/debug/charts/debug_chart_renderer.py | 2 ++ src/sentry/web/frontend/debug/charts/metric_alert_charts.py | 2 ++ src/sentry/web/frontend/debug/debug_oauth_authorize.py | 1 + src/sentry_plugins/bitbucket/endpoints/webhook.py | 2 ++ src/sentry_plugins/github/webhooks/integration.py | 2 ++ src/sentry_plugins/github/webhooks/non_integration.py | 2 ++ 7 files changed, 13 insertions(+) diff --git a/src/sentry/charts/endpoints.py b/src/sentry/charts/endpoints.py index cfa8c1b5a68506..cd3531da0a6965 100644 --- a/src/sentry/charts/endpoints.py +++ b/src/sentry/charts/endpoints.py @@ -5,12 +5,14 @@ from django.views import static import sentry +from sentry.web.frontend.base import all_silo_view CONFIG_DIR = os.path.abspath( os.path.join(os.path.dirname(sentry.__file__), "..", "..", "config", "chartcuterie") ) +@all_silo_view def serve_chartcuterie_config( request: HttpRequest, ) -> HttpResponseBase: diff --git a/src/sentry/web/frontend/debug/charts/debug_chart_renderer.py b/src/sentry/web/frontend/debug/charts/debug_chart_renderer.py index e57b0b648e38c5..db7978d39889f2 100644 --- a/src/sentry/web/frontend/debug/charts/debug_chart_renderer.py +++ b/src/sentry/web/frontend/debug/charts/debug_chart_renderer.py @@ -3,6 +3,7 @@ from sentry.charts import backend as charts from sentry.charts.types import ChartType +from sentry.web.frontend.base import internal_region_silo_view from sentry.web.frontend.debug.mail import MailPreview discover_total_period = { @@ -279,6 +280,7 @@ } +@internal_region_silo_view class DebugChartRendererView(View): def get(self, request: HttpRequest) -> HttpResponse: ret = [] diff --git a/src/sentry/web/frontend/debug/charts/metric_alert_charts.py b/src/sentry/web/frontend/debug/charts/metric_alert_charts.py index 9612ebde06dc39..edb876ecb86d8f 100644 --- a/src/sentry/web/frontend/debug/charts/metric_alert_charts.py +++ b/src/sentry/web/frontend/debug/charts/metric_alert_charts.py @@ -4,6 +4,7 @@ from sentry.charts import backend as charts from sentry.charts.types import ChartType from sentry.seer.anomaly_detection.types import AnomalyType +from sentry.web.frontend.base import internal_region_silo_view from sentry.web.frontend.debug.mail import MailPreview incident = { @@ -510,6 +511,7 @@ } +@internal_region_silo_view class DebugMetricAlertChartRendererView(View): def get(self, request: HttpRequest) -> HttpResponse: ret = [] diff --git a/src/sentry/web/frontend/debug/debug_oauth_authorize.py b/src/sentry/web/frontend/debug/debug_oauth_authorize.py index 7c7d3e01e5c468..b271bee00ac5ad 100644 --- a/src/sentry/web/frontend/debug/debug_oauth_authorize.py +++ b/src/sentry/web/frontend/debug/debug_oauth_authorize.py @@ -30,6 +30,7 @@ def get(self, request: HttpRequest) -> HttpResponse: ) +@internal_region_silo_view class DebugOAuthAuthorizeErrorView(View): def get(self, request: HttpRequest) -> HttpResponse: return render_to_response( diff --git a/src/sentry_plugins/bitbucket/endpoints/webhook.py b/src/sentry_plugins/bitbucket/endpoints/webhook.py index 0f118be67c2178..01707797910cbc 100644 --- a/src/sentry_plugins/bitbucket/endpoints/webhook.py +++ b/src/sentry_plugins/bitbucket/endpoints/webhook.py @@ -19,6 +19,7 @@ from sentry.plugins.providers import RepositoryProvider from sentry.utils import json from sentry.utils.email import parse_email +from sentry.web.frontend.base import region_silo_view logger = logging.getLogger("sentry.webhooks") @@ -79,6 +80,7 @@ def __call__(self, organization_id: int, event): pass +@region_silo_view class BitbucketPluginWebhookEndpoint(View): _handlers = {"repo:push": PushEventWebhook} diff --git a/src/sentry_plugins/github/webhooks/integration.py b/src/sentry_plugins/github/webhooks/integration.py index a16ce37dee6acb..e4766c39e8e8ec 100644 --- a/src/sentry_plugins/github/webhooks/integration.py +++ b/src/sentry_plugins/github/webhooks/integration.py @@ -10,6 +10,7 @@ from sentry import options from sentry.models.organization import Organization +from sentry.web.frontend.base import region_silo_view from .base import GithubWebhookBase from .events import InstallationEventWebhook, InstallationRepositoryEventWebhook, PushEventWebhook @@ -17,6 +18,7 @@ logger = logging.getLogger(__name__) +@region_silo_view class GithubPluginIntegrationsWebhookEndpoint(GithubWebhookBase): _handlers = { "push": PushEventWebhook, diff --git a/src/sentry_plugins/github/webhooks/non_integration.py b/src/sentry_plugins/github/webhooks/non_integration.py index f44a2cdf026ea5..b8ad11fd1819a3 100644 --- a/src/sentry_plugins/github/webhooks/non_integration.py +++ b/src/sentry_plugins/github/webhooks/non_integration.py @@ -7,12 +7,14 @@ from sentry.models.options.organization_option import OrganizationOption from sentry.models.organization import Organization +from sentry.web.frontend.base import region_silo_view from .base import GithubWebhookBase logger = logging.getLogger("sentry.webhooks") +@region_silo_view class GithubPluginWebhookEndpoint(GithubWebhookBase): def get_logging_data(self, organization): return {"organization_id": organization.id} From c13a3a9411b9ba5c5c8271bbd1ccdd19378df79a Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 26 Nov 2025 12:42:29 -0500 Subject: [PATCH 07/11] Regenerate control silo URL list again --- static/app/data/controlsiloUrlPatterns.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/static/app/data/controlsiloUrlPatterns.ts b/static/app/data/controlsiloUrlPatterns.ts index 236c8146cfc59d..7003073a933d2a 100644 --- a/static/app/data/controlsiloUrlPatterns.ts +++ b/static/app/data/controlsiloUrlPatterns.ts @@ -217,6 +217,7 @@ const patterns: RegExp[] = [ new RegExp('^avatar/[^/]+/$'), new RegExp('^sentry-app-avatar/[^/]+/$'), new RegExp('^doc-integration-avatar/[^/]+/$'), + new RegExp('^_chartcuterie-config\\.js$'), new RegExp('^robots\\.txt$'), new RegExp('^\\.well-known/security\\.txt$'), new RegExp('^\\.well-known/mcp\\.json$'), From 48890b25b343f9d9af7e9cb1123c8c27205f422d Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 26 Nov 2025 12:44:21 -0500 Subject: [PATCH 08/11] Align types --- src/sentry/silo/base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sentry/silo/base.py b/src/sentry/silo/base.py index ac41024a4283d7..19f1955d260ddc 100644 --- a/src/sentry/silo/base.py +++ b/src/sentry/silo/base.py @@ -158,9 +158,9 @@ def override(*args: P.args, **kwargs: P.kwargs) -> R: if is_available: return original_method(*args, **kwargs) else: - modes = self.modes - if SiloMode.MONOLITH not in modes: - modes = itertools.chain([SiloMode.MONOLITH], modes) + modes = itertools.chain(self.modes) + if SiloMode.MONOLITH not in self.modes: + modes = itertools.chain([SiloMode.MONOLITH], self.modes) handler = self.handle_when_unavailable( original_method, SiloMode.get_current_mode(), modes ) From 17e58f38e2160026eb4ee54105849bde37c00935 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 26 Nov 2025 13:35:58 -0500 Subject: [PATCH 09/11] Relax silo mode of github plugin --- src/sentry_plugins/github/webhooks/integration.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sentry_plugins/github/webhooks/integration.py b/src/sentry_plugins/github/webhooks/integration.py index e4766c39e8e8ec..012537974ab341 100644 --- a/src/sentry_plugins/github/webhooks/integration.py +++ b/src/sentry_plugins/github/webhooks/integration.py @@ -10,7 +10,7 @@ from sentry import options from sentry.models.organization import Organization -from sentry.web.frontend.base import region_silo_view +from sentry.web.frontend.base import all_silo_view from .base import GithubWebhookBase from .events import InstallationEventWebhook, InstallationRepositoryEventWebhook, PushEventWebhook @@ -18,7 +18,7 @@ logger = logging.getLogger(__name__) -@region_silo_view +@all_silo_view class GithubPluginIntegrationsWebhookEndpoint(GithubWebhookBase): _handlers = { "push": PushEventWebhook, From 0be6d2d2b25d773a4ba11cd51d0d72378c030975 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 26 Nov 2025 13:36:24 -0500 Subject: [PATCH 10/11] regen control silo mappings --- static/app/data/controlsiloUrlPatterns.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/static/app/data/controlsiloUrlPatterns.ts b/static/app/data/controlsiloUrlPatterns.ts index 7003073a933d2a..9deaac0e1cb832 100644 --- a/static/app/data/controlsiloUrlPatterns.ts +++ b/static/app/data/controlsiloUrlPatterns.ts @@ -254,6 +254,7 @@ const patterns: RegExp[] = [ new RegExp('^extensions/discord/configure/$'), new RegExp('^extensions/discord/link-identity/[^/]+/$'), new RegExp('^extensions/discord/unlink-identity/[^/]+/$'), + new RegExp('^plugins/github/installations/webhook/$'), new RegExp('^share/(?:group|issue)/[^/]+/$'), ]; From d53c080c5521eee080671c8f0f358225821c277f Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 26 Nov 2025 14:13:10 -0500 Subject: [PATCH 11/11] Remove itertools --- src/sentry/silo/base.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sentry/silo/base.py b/src/sentry/silo/base.py index 19f1955d260ddc..5850a204ecaddd 100644 --- a/src/sentry/silo/base.py +++ b/src/sentry/silo/base.py @@ -3,7 +3,6 @@ import abc import contextlib import functools -import itertools import threading import typing from collections.abc import Callable, Generator, Iterable @@ -158,9 +157,9 @@ def override(*args: P.args, **kwargs: P.kwargs) -> R: if is_available: return original_method(*args, **kwargs) else: - modes = itertools.chain(self.modes) + modes = list(self.modes) if SiloMode.MONOLITH not in self.modes: - modes = itertools.chain([SiloMode.MONOLITH], self.modes) + modes = modes + [SiloMode.MONOLITH] handler = self.handle_when_unavailable( original_method, SiloMode.get_current_mode(), modes )