Skip to content

Commit 92662a6

Browse files
authored
fix(demo-mode): Restrict GroupAi endpoints to demo orgs only (#111509)
1 parent bc5591b commit 92662a6

2 files changed

Lines changed: 50 additions & 6 deletions

File tree

src/sentry/issues/endpoints/bases/group.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from sentry.api.base import Endpoint
1414
from sentry.api.bases.project import ProjectPermission
1515
from sentry.api.exceptions import ResourceDoesNotExist
16-
from sentry.demo_mode.utils import is_demo_mode_enabled, is_demo_user
16+
from sentry.demo_mode.utils import is_demo_mode_enabled, is_demo_org, is_demo_user
1717
from sentry.integrations.tasks import create_comment, update_comment
1818
from sentry.models.activity import Activity
1919
from sentry.models.group import Group, GroupStatus, get_group_with_redirect
@@ -157,6 +157,9 @@ def has_object_permission(self, request: Request, view: APIView, group: Any) ->
157157
if not is_demo_mode_enabled() or request.method not in self.ALLOWED_METHODS:
158158
return False
159159

160+
if not is_demo_org(group.project.organization):
161+
return False
162+
160163
return True
161164
return super().has_object_permission(request, view, group)
162165

tests/sentry/issues/endpoints/test_group.py

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,34 @@ class GroupAiPermissionTest(TestCase):
1515
def setUp(self) -> None:
1616
super().setUp()
1717
self.permission = GroupAiPermission()
18-
self.project = self.create_project()
19-
self.group = self.create_group(project=self.project)
18+
self.demo_org = self.create_organization(name="demo-org")
19+
self.demo_project = self.create_project(organization=self.demo_org)
20+
self.demo_group = self.create_group(project=self.demo_project)
2021
self.demo_user = self.create_user()
22+
self.create_member(
23+
user=self.demo_user,
24+
organization=self.demo_org,
25+
role="member",
26+
teams=[self.demo_project.teams.first()],
27+
)
28+
29+
# Keep legacy aliases so existing tests still work
30+
self.project = self.demo_project
31+
self.group = self.demo_group
32+
33+
# A separate org the demo user has no membership in
34+
self.other_org = self.create_organization(name="other-org")
35+
self.other_project = self.create_project(organization=self.other_org)
36+
self.other_group = self.create_group(project=self.other_project)
2137

2238
def _demo_mode_enabled(self) -> ContextManager[None]:
23-
return override_options({"demo-mode.enabled": True, "demo-mode.users": [self.demo_user.id]})
39+
return override_options(
40+
{
41+
"demo-mode.enabled": True,
42+
"demo-mode.users": [self.demo_user.id],
43+
"demo-mode.orgs": [self.demo_org.id],
44+
}
45+
)
2446

2547
def has_object_perm(
2648
self,
@@ -51,8 +73,27 @@ def test_demo_user_unsafe_methods_blocked(self) -> None:
5173
assert not self.has_object_perm(method, self.group, user=self.demo_user)
5274

5375
def test_demo_user_demo_mode_disabled(self) -> None:
54-
for method in ("GET", "POST", "PUT", "DELETE"):
55-
assert not self.has_object_perm(method, self.group, user=self.demo_user)
76+
"""When demo mode is off, listed demo users are denied entirely."""
77+
with override_options({"demo-mode.users": [self.demo_user.id]}):
78+
# is_demo_user() is True but is_demo_mode_enabled() is False → blocked
79+
assert not self.has_object_perm("GET", self.demo_group, user=self.demo_user)
80+
assert not self.has_object_perm("GET", self.other_group, user=self.demo_user)
81+
82+
def test_demo_user_blocked_from_non_demo_org_group(self) -> None:
83+
"""Demo user must not access groups belonging to a non-demo org."""
84+
with self._demo_mode_enabled():
85+
for method in ("GET", "POST"):
86+
assert not self.has_object_perm(method, self.other_group, user=self.demo_user), (
87+
f"Demo user got access to non-demo org group via {method}"
88+
)
89+
90+
def test_demo_user_allowed_on_demo_org_group(self) -> None:
91+
"""Demo user can access groups in the demo org."""
92+
with self._demo_mode_enabled():
93+
for method in ("GET", "POST"):
94+
assert self.has_object_perm(method, self.demo_group, user=self.demo_user), (
95+
f"Demo user denied access to demo org group via {method}"
96+
)
5697

5798
def test_regular_user_with_access(self) -> None:
5899
user = self.create_user()

0 commit comments

Comments
 (0)