Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/sentry/uptime/endpoints/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,16 +469,27 @@ class UptimeDomainCheckFailureValidator(BaseDetectorTypeValidator):
def validate_config(self, config: dict[str, Any]) -> dict[str, Any]:
"""
Validate that only superusers can change mode to non-MANUAL values.

When a non-superuser updates a monitor that is not in MANUAL mode,
automatically switch to MANUAL.
"""
if "mode" not in config:
return config

mode = config["mode"]

# For updates, only validate if mode is being changed
# For updates, if current mode is not MANUAL and user is not a superuser,
# automatically switch to MANUAL mode
if self.instance:
current_mode = self.instance.config.get("mode")
# If mode hasn't changed, no validation needed

if current_mode != UptimeMonitorMode.MANUAL:
request = self.context["request"]
if not is_active_superuser(request):
config["mode"] = UptimeMonitorMode.MANUAL
return config

# If mode hasn't changed, no further validation needed
if current_mode == mode:
return config

Expand Down
41 changes: 41 additions & 0 deletions tests/sentry/uptime/endpoints/test_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,47 @@ def test_update(self) -> None:
)
assert updated_sub.timeout_ms == 15000

def test_update_auto_detected_switches_to_manual(self) -> None:
"""Test that when a user modifies an AUTO_DETECTED detector, it automatically switches to MANUAL mode."""
# Create an AUTO_DETECTED detector
auto_detector = self.create_uptime_detector(
project=self.project,
env=self.environment,
uptime_subscription=self.uptime_subscription,
name="Auto Detected Monitor",
mode=UptimeMonitorMode.AUTO_DETECTED_ACTIVE,
)

assert auto_detector.workflow_condition_group is not None
# User modifies the detector (e.g., changes name)
# They pass the current config including the AUTO_DETECTED mode
valid_data = {
"id": auto_detector.id,
"projectId": self.project.id,
"name": "User Modified Monitor",
"type": UptimeDomainCheckFailure.slug,
"dateCreated": auto_detector.date_added,
"dateUpdated": timezone.now(),
"conditionGroup": {
"id": auto_detector.workflow_condition_group.id,
"organizationId": self.organization.id,
},
"config": auto_detector.config, # Passing existing config with AUTO_DETECTED mode
}

self.get_success_response(
self.organization.slug,
auto_detector.id,
**valid_data,
status_code=status.HTTP_200_OK,
method="PUT",
)

# Verify that mode was automatically switched to MANUAL
auto_detector.refresh_from_db()
assert auto_detector.name == "User Modified Monitor"
assert auto_detector.config["mode"] == UptimeMonitorMode.MANUAL.value

def test_update_invalid(self) -> None:
assert self.detector.workflow_condition_group is not None
valid_data = {
Expand Down
Loading