Browse Source

fix(alerts): Fix org events anomalies endpoint permissions (#79154)

Members currently can't load the alert preview chart for dynamic alerts
because they lack the correct permissions - this PR changes the
`OrganizationEventsAnomaliesEndpoint` to match those of creating and
editing alerts.

Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
Colleen O'Rourke 4 months ago
parent
commit
dc29f5bf7a

+ 2 - 0
src/sentry/api/endpoints/organization_events_anomalies.py

@@ -6,6 +6,7 @@ from sentry import features
 from sentry.api.api_owners import ApiOwner
 from sentry.api.api_publish_status import ApiPublishStatus
 from sentry.api.base import region_silo_endpoint
+from sentry.api.bases.organization import OrganizationAlertRulePermission
 from sentry.api.bases.organization_events import OrganizationEventsV2EndpointBase
 from sentry.api.exceptions import ResourceDoesNotExist
 from sentry.api.paginator import OffsetPaginator
@@ -32,6 +33,7 @@ class OrganizationEventsAnomaliesEndpoint(OrganizationEventsV2EndpointBase):
     publish_status = {
         "POST": ApiPublishStatus.EXPERIMENTAL,
     }
+    permission_classes = (OrganizationAlertRulePermission,)
 
     @extend_schema(
         operation_id="Identify anomalies in historical data",

+ 41 - 0
tests/sentry/api/endpoints/test_organization_events_anomalies.py

@@ -116,6 +116,47 @@ class OrganizationEventsAnomaliesEndpointTest(APITestCase):
         assert mock_seer_request.call_count == 1
         assert resp.data == seer_return_value["timeseries"]
 
+    @with_feature("organizations:anomaly-detection-alerts")
+    @with_feature("organizations:anomaly-detection-rollout")
+    @with_feature("organizations:incidents")
+    @patch(
+        "sentry.seer.anomaly_detection.get_historical_anomalies.seer_anomaly_detection_connection_pool.urlopen"
+    )
+    def test_member_permission(self, mock_seer_request):
+        """Test that even a member (lowest permissions) can access this endpoint"""
+        user = self.create_user(is_superuser=False)
+        member = self.create_member(
+            user=user, organization=self.organization, role="member", teams=[]
+        )
+        self.create_team(organization=self.organization, members=[member])
+        self.login_as(member)
+
+        seer_return_value = DetectAnomaliesResponse(
+            success=True,
+            message="",
+            timeseries=[
+                TimeSeriesPoint(
+                    timestamp=self.current_timestamp_1,
+                    value=2,
+                    anomaly=Anomaly(anomaly_score=-0.1, anomaly_type="none"),
+                ),
+                TimeSeriesPoint(
+                    timestamp=self.current_timestamp_2,
+                    value=3,
+                    anomaly=Anomaly(anomaly_score=-0.2, anomaly_type="none"),
+                ),
+            ],
+        )
+        mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200)
+
+        with outbox_runner():
+            resp = self.get_success_response(
+                self.organization.slug, status_code=200, raw_data=orjson.dumps(self.data)
+            )
+
+        assert mock_seer_request.call_count == 1
+        assert resp.data == seer_return_value["timeseries"]
+
     @with_feature("organizations:anomaly-detection-alerts")
     @with_feature("organizations:anomaly-detection-rollout")
     @with_feature("organizations:incidents")