diff --git a/src/sentry/utils/demo_mode.py b/src/sentry/utils/demo_mode.py new file mode 100644 index 00000000000000..77b0fa9b537dcc --- /dev/null +++ b/src/sentry/utils/demo_mode.py @@ -0,0 +1,49 @@ +from sentry import options +from sentry.models.organization import Organization +from sentry.users.models.user import User + +READONLY_SCOPES = frozenset( + [ + "project:read", + "org:read", + "event:read", + "member:read", + "team:read", + "project:releases", + "alerts:read", + ] +) + + +def is_readonly_user(user: User | None) -> bool: + if not options.get("demo-mode.enabled"): + return False + + if not user: + return False + + email = getattr(user, "email", None) + + return email in options.get("demo-mode.users") + + +def is_demo_org(organization: Organization | None): + if not options.get("demo-mode.enabled"): + return False + + if not organization: + return False + + return organization.id in options.get("demo-mode.orgs") + + +def get_readonly_user(): + if not options.get("demo-mode.enabled"): + return None + + email = options.get("demo-mode.users")[0] + return User.objects.get(email=email) + + +def get_readonly_scopes() -> frozenset[str]: + return READONLY_SCOPES diff --git a/tests/sentry/utils/test_demo_mode.py b/tests/sentry/utils/test_demo_mode.py new file mode 100644 index 00000000000000..d60801ceb101fd --- /dev/null +++ b/tests/sentry/utils/test_demo_mode.py @@ -0,0 +1,88 @@ +from unittest.mock import patch + +from sentry.testutils.factories import Factories +from sentry.testutils.helpers.options import override_options +from sentry.testutils.pytest.fixtures import django_db_all +from sentry.utils.demo_mode import get_readonly_user, is_demo_org, is_readonly_user + + +@override_options({"demo-mode.enabled": True, "demo-mode.users": ["readonly@example.com"]}) +@django_db_all +def test_is_readonly_user_demo_mode_enabled_none(): + assert not is_readonly_user(None) + + +@override_options({"demo-mode.enabled": True, "demo-mode.users": ["readonly@example.com"]}) +@django_db_all +def test_is_readonly_user_demo_mode_enabled_readonly_user(): + user = Factories.create_user("readonly@example.com") + assert is_readonly_user(user) + + +@override_options({"demo-mode.enabled": True, "demo-mode.users": ["readonly@example.com"]}) +@django_db_all +def test_is_readonly_user_demo_mode_enabled_non_readonly_user(): + user = Factories.create_user("user@example.com") + assert not is_readonly_user(user) + + +@override_options({"demo-mode.enabled": False}) +@django_db_all +def test_is_readonly_user_demo_mode_disabled_none(): + assert not is_readonly_user(None) + + +@override_options({"demo-mode.enabled": False}) +@django_db_all +def test_is_readonly_user_demo_mode_disabled_readonly_user(): + user = Factories.create_user("readonly@example.com") + assert not is_readonly_user(user) + + +@override_options({"demo-mode.enabled": False}) +@django_db_all +def test_is_readonly_user_demo_mode_disabled_non_readonly_user(): + user = Factories.create_user("user@example.com") + assert not is_readonly_user(user) + + +@override_options({"demo-mode.enabled": False}) +@django_db_all +def test_is_demo_org_demo_mode_disabled(): + organization = Factories.create_organization() + assert not is_demo_org(organization) + + +@override_options({"demo-mode.enabled": True}) +@django_db_all +def test_is_demo_org_no_organization(): + assert not is_demo_org(None) + + +@override_options({"demo-mode.enabled": True, "demo-mode.orgs": [1, 2, 3]}) +@django_db_all +def test_is_demo_org_demo_mode_enabled(): + organization = Factories.create_organization(id=1) + assert is_demo_org(organization) + + +@override_options({"demo-mode.enabled": True, "demo-mode.orgs": [1, 2, 3]}) +@django_db_all +def test_is_demo_org_not_in_demo_orgs(): + organization = Factories.create_organization(id=4) + assert not is_demo_org(organization) + + +@override_options({"demo-mode.enabled": False}) +@django_db_all +def test_get_readonly_user_demo_mode_disabled(): + assert get_readonly_user() is None + + +@override_options({"demo-mode.enabled": True, "demo-mode.users": ["readonly@example.com"]}) +@django_db_all +def test_get_readonly_user_demo_mode_enabled(): + user = Factories.create_user("readonly@example.com") + with patch("sentry.utils.demo_mode.User.objects.get", return_value=user) as mock_user_get: + assert get_readonly_user() == user + mock_user_get.assert_called_once_with(email="readonly@example.com")