Skip to content
Open
2 changes: 2 additions & 0 deletions src/sentry/charts/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
7 changes: 4 additions & 3 deletions src/sentry/silo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,11 @@ def override(*args: P.args, **kwargs: P.kwargs) -> R:
if is_available:
return original_method(*args, **kwargs)
else:
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(),
itertools.chain([SiloMode.MONOLITH], self.modes),
original_method, SiloMode.get_current_mode(), modes
)
return handler(*args, **kwargs)

Expand Down
24 changes: 20 additions & 4 deletions src/sentry/web/frontend/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/charts/debug_chart_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -279,6 +280,7 @@
}


@internal_region_silo_view
class DebugChartRendererView(View):
def get(self, request: HttpRequest) -> HttpResponse:
ret = []
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/charts/metric_alert_charts.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -510,6 +511,7 @@
}


@internal_region_silo_view
class DebugMetricAlertChartRendererView(View):
def get(self, request: HttpRequest) -> HttpResponse:
ret = []
Expand Down
3 changes: 3 additions & 0 deletions src/sentry/web/frontend/debug/debug_auth_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
from django.views.generic import View

from sentry.users.models.user import User
from sentry.web.frontend.base import internal_region_silo_view
from sentry.web.helpers import render_to_response


@internal_region_silo_view
class DebugAuthConfirmIdentity(View):
def get(self, request: HttpRequest) -> HttpResponse:
auth_identity = {"id": "[email protected]", "email": "[email protected]"}
Expand All @@ -21,6 +23,7 @@ def get(self, request: HttpRequest) -> HttpResponse:
)


@internal_region_silo_view
class DebugAuthConfirmLink(View):
def get(self, request: HttpRequest) -> HttpResponse:
auth_identity = {"id": "[email protected]", "email": "[email protected]"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view

from .mail import render_preview_email_for_notification


@internal_region_silo_view
class DebugCodeOwnersAutoSyncFailureView(View):
def get(self, request: HttpRequest) -> HttpResponse:
org = Organization(id=1, slug="petal", name="Petal")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from django.http import HttpRequest, HttpResponse
from django.views.generic import View

from sentry.web.frontend.base import internal_region_silo_view

from .mail import MailPreview


Expand All @@ -17,6 +19,7 @@ def get_context():
}


@internal_region_silo_view
class DebugCronBrokenMonitorEmailView(View):
def get(self, request: HttpRequest) -> HttpResponse:
context = get_context()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from django.http import HttpRequest, HttpResponse
from django.views.generic import View

from sentry.web.frontend.base import internal_region_silo_view

from .mail import MailPreview


Expand All @@ -17,6 +19,7 @@ def get_context():
}


@internal_region_silo_view
class DebugCronMutedMonitorEmailView(View):
def get(self, request: HttpRequest) -> HttpResponse:
context = get_context()
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/debug_error_embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
from django.views.generic import View

from sentry.models.projectkey import ProjectKey
from sentry.web.frontend.base import internal_region_silo_view
from sentry.web.helpers import render_to_response


@internal_region_silo_view
class DebugErrorPageEmbedView(View):
def _get_project_key(self):
return ProjectKey.objects.filter(project=settings.SENTRY_PROJECT)[0]
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/debug_feedback_issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view

from .mail import COMMIT_EXAMPLE, MailPreview, make_feedback_issue


@internal_region_silo_view
class DebugFeedbackIssueEmailView(View):
def get(self, request):
org = Organization(id=1, slug="example", name="Example")
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/debug_generic_issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view

from .mail import COMMIT_EXAMPLE, MailPreview, make_generic_event


@internal_region_silo_view
class DebugGenericIssueEmailView(View):
def get(self, request):
org = Organization(id=1, slug="example", name="Example")
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/debug_incident_trigger_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view

from .mail import MailPreviewView

Expand All @@ -26,6 +27,7 @@ class MockedIncidentTrigger:
date_added = timezone.now()


@internal_region_silo_view
class DebugIncidentTriggerEmailView(MailPreviewView):
@mock.patch(
"sentry.incidents.models.incident.IncidentTrigger.objects.get",
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/debug_invalid_identity_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view
from social_auth.models import UserSocialAuth

from .mail import MailPreview


@internal_region_silo_view
class DebugInvalidIdentityEmailView(View):
def get(self, request: HttpRequest) -> HttpResponse:
assert request.user.is_authenticated
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/debug_mfa_added_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view

from .mail import MailPreview


@internal_region_silo_view
class DebugMfaAddedEmailView(View):
def get(self, request: HttpRequest) -> HttpResponse:
if isinstance(request.user, AnonymousUser):
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/debug_mfa_removed_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view

from .mail import MailPreview


@internal_region_silo_view
class DebugMfaRemovedEmailView(View):
def get(self, request: HttpRequest) -> HttpResponse:
if isinstance(request.user, AnonymousUser):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
from django.views.generic import View

from sentry.models.organization import Organization
from sentry.web.frontend.base import internal_region_silo_view

from .mail import MailPreview


@internal_region_silo_view
class DebugMissingMembersNudgeView(View):
def get(self, request: HttpRequest) -> HttpResponse:
self.organization = Organization(id=1, slug="organization", name="My Company")
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/debug_new_release_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view

from .mail import MailPreview


@internal_region_silo_view
class DebugNewReleaseEmailView(View):
def get(self, request: HttpRequest) -> HttpResponse:
org = Organization(id=1, slug="organization", name="My Company")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view

from .mail import MailPreview


@internal_region_silo_view
class DebugNewUserFeedbackEmailView(View):
def get(self, request: HttpRequest) -> HttpResponse:
org = Organization(id=1, slug="organization", name="My Company")
Expand Down
2 changes: 2 additions & 0 deletions src/sentry/web/frontend/debug/debug_note_email.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from django.http import HttpRequest

from sentry.types.activity import ActivityType
from sentry.web.frontend.base import internal_region_silo_view

from .mail import ActivityMailDebugView, get_random, make_message


@internal_region_silo_view
class DebugNoteEmailView(ActivityMailDebugView):
def get_activity(self, request: HttpRequest, event):
random = get_random(request)
Expand Down
3 changes: 3 additions & 0 deletions src/sentry/web/frontend/debug/debug_oauth_authorize.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
from django.views.generic import View

from sentry.models.apiapplication import ApiApplication
from sentry.web.frontend.base import internal_region_silo_view
from sentry.web.helpers import render_to_response


@internal_region_silo_view
class DebugOAuthAuthorizeView(View):
def get(self, request: HttpRequest) -> HttpResponse:
application = ApiApplication(
Expand All @@ -28,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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view
from sentry.web.frontend.debug.mail import MailPreviewAdapter
from sentry.web.helpers import render_to_response


@internal_region_silo_view
class DebugOrganizationOnboardingContinuationEmail(View):
def get(self, request: HttpRequest) -> HttpResponse:
platforms = request.GET.getlist("platforms", ["javascript", "python", "flutter"])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
IntegrationRequestNotification,
)
from sentry.users.models.user import User
from sentry.web.frontend.base import internal_region_silo_view

from .mail import render_preview_email_for_notification


@internal_region_silo_view
class DebugOrganizationIntegrationRequestEmailView(View):
def get(self, request: HttpRequest) -> HttpResponse:
org = Organization(id=1, slug="default", name="Default")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 internal_region_silo_view

from .mail import render_preview_email_for_notification


@internal_region_silo_view
class DebugOrganizationInviteRequestEmailView(View):
def get(self, request: HttpRequest) -> HttpResponse:
org = Organization(id=1, slug="default", name="Default")
Expand Down
Loading
Loading