diff --git a/src/sentry/discover/endpoints/bases.py b/src/sentry/discover/endpoints/bases.py index 9eccf57ba9c99c..9d067e9e0ee8dd 100644 --- a/src/sentry/discover/endpoints/bases.py +++ b/src/sentry/discover/endpoints/bases.py @@ -17,8 +17,23 @@ def has_object_permission(self, request, view, obj): return super().has_object_permission(request, view, obj) if isinstance(obj, DiscoverSavedQuery): - for project in obj.projects.all(): - if not request.access.has_project_access(project): - return False + # 1. Saved Query contains certain projects + if obj.projects.exists(): + return request.access.has_projects_access(obj.projects.all()) + # 2. Saved Query covers all projects or all my projects + + # allow when Open Membership + if obj.organization.flags.allow_joinleave: + return True + + # allow for Managers and Owners + if request.access.has_scope("org:write"): + return True + + # allow for creator + if request.user.id == obj.created_by_id: + return True + + return False return True diff --git a/tests/snuba/api/endpoints/test_discover_saved_query_detail.py b/tests/snuba/api/endpoints/test_discover_saved_query_detail.py index 154dc182842566..711679ab0573af 100644 --- a/tests/snuba/api/endpoints/test_discover_saved_query_detail.py +++ b/tests/snuba/api/endpoints/test_discover_saved_query_detail.py @@ -450,6 +450,29 @@ def test_delete_disallow_when_no_project_access(self): assert response.status_code == 403, response.data assert response.data == {"detail": "You do not have permission to perform this action."} + def test_disallow_delete_all_projects_savedquery_when_no_open_membership(self): + self.setup_no_team_user() + + query = {"fields": ["event_id"], "query": "event.type:error", "limit": 10, "version": 2} + model = DiscoverSavedQuery.objects.create( + organization=self.org, + created_by_id=self.user.id, + name="v2 query", + query=query, + ) + + assert not model.projects.exists() + + with self.feature(self.feature_name): + url = reverse( + "sentry-api-0-discover-saved-query-detail", args=[self.org.slug, model.id] + ) + + response = self.client.delete(url) + + assert response.status_code == 403, response.data + assert response.data == {"detail": "You do not have permission to perform this action."} + class OrganizationDiscoverQueryVisitTest(APITestCase, SnubaTestCase): def setUp(self):