streams: Check permission to create web-public streams based on group setting.

This commit is contained in:
Sahil Batra 2024-07-23 19:26:46 +05:30 committed by Tim Abbott
parent a15bc5e264
commit 09102c5780
6 changed files with 43 additions and 115 deletions

View File

@ -573,7 +573,9 @@ def fetch_initial_state_data(
realm.can_create_public_channel_group_id in settings_user_recursive_group_ids
)
state["can_create_web_public_streams"] = settings_user.can_create_web_public_streams()
state["can_create_web_public_streams"] = (
realm.can_create_web_public_channel_group_id in settings_user_recursive_group_ids
)
# TODO/compatibility: Deprecated in Zulip 5.0 (feature level
# 102); we can remove this once we no longer need to support
# legacy mobile app versions that read the old property.
@ -1230,7 +1232,6 @@ def apply_event(
)
policy_permission_dict = {
"create_web_public_stream_policy": "can_create_web_public_streams",
"invite_to_stream_policy": "can_subscribe_other_users",
"invite_to_realm_policy": "can_invite_others_to_realm",
}
@ -1250,13 +1251,6 @@ def apply_event(
state[policy_permission_dict[event["property"]]] = user_profile.has_permission(
event["property"]
)
# Finally, we need to recompute this value from its inputs.
state["can_create_streams"] = (
state["can_create_private_streams"]
or state["can_create_public_streams"]
or state["can_create_web_public_streams"]
)
elif event["op"] == "update_dict":
for key, value in event["data"].items():
state["realm_" + key] = value
@ -1269,7 +1263,11 @@ def apply_event(
)
state["realm_email_auth_enabled"] = value["Email"]["enabled"]
if key in ["can_create_public_channel_group", "can_create_private_channel_group"]:
if key in [
"can_create_public_channel_group",
"can_create_private_channel_group",
"can_create_web_public_channel_group",
]:
if key == "can_create_public_channel_group":
state["realm_create_public_stream_policy"] = (
get_corresponding_policy_value_for_group_setting(
@ -1279,7 +1277,7 @@ def apply_event(
)
)
state["can_create_public_streams"] = user_profile.has_permission(key)
else:
elif key == "can_create_private_channel_group":
state["realm_create_private_stream_policy"] = (
get_corresponding_policy_value_for_group_setting(
user_profile.realm,
@ -1288,6 +1286,8 @@ def apply_event(
)
)
state["can_create_private_streams"] = user_profile.has_permission(key)
else:
state["can_create_web_public_streams"] = user_profile.has_permission(key)
state["can_create_streams"] = (
state["can_create_private_streams"]

View File

@ -768,8 +768,8 @@ def list_to_streams(
if not user_profile.realm.web_public_streams_enabled():
raise JsonableError(_("Web-public channels are not enabled."))
if not user_profile.can_create_web_public_streams():
# We set create_web_public_stream_policy to allow only organization owners
# to create web-public streams, because of their sensitive nature.
# We set can_create_web_public_channel_group to allow only organization
# owners to create web-public streams, because of their sensitive nature.
raise JsonableError(_("Insufficient permission"))
if message_retention_days_not_none:

View File

@ -780,6 +780,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin, UserBaseSettings):
"add_custom_emoji_policy",
"can_create_private_channel_group",
"can_create_public_channel_group",
"can_create_web_public_channel_group",
"create_multiuse_invite_group",
"create_web_public_stream_policy",
"delete_own_message_policy",
@ -845,7 +846,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin, UserBaseSettings):
def can_create_web_public_streams(self) -> bool:
if not self.realm.web_public_streams_enabled():
return False
return self.has_permission("create_web_public_stream_policy")
return self.has_permission("can_create_web_public_channel_group")
def can_subscribe_other_users(self) -> bool:
return self.has_permission("invite_to_stream_policy")

View File

@ -3772,7 +3772,9 @@ class RealmPropertyActionTest(BaseAction):
self.do_set_realm_permission_group_setting_test(prop)
for prop in Realm.REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT:
if prop == "can_create_web_public_channel_group":
if Realm.REALM_PERMISSION_GROUP_SETTINGS[prop].require_system_group:
# Anonymous system groups aren't relevant when
# restricted to system groups.
continue
with self.settings(SEND_DIGEST_EMAILs=True):
self.do_set_realm_permission_group_setting_to_anonymous_groups_test(prop)

View File

@ -1959,9 +1959,9 @@ class RealmAPITest(ZulipTestCase):
self.do_test_realm_permission_group_setting_update_api(prop)
for prop in Realm.REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT:
if prop == "can_create_web_public_channel_group":
# This setting supports the new API format but
# allows only system groups.
if Realm.REALM_PERMISSION_GROUP_SETTINGS[prop].require_system_group:
# Anonymous system groups aren't relevant when
# restricted to system groups.
continue
with self.subTest(property=prop):
self.do_test_realm_permission_group_setting_update_api_with_anonymous_groups(prop)

View File

@ -120,7 +120,7 @@ from zerver.models import (
UserProfile,
)
from zerver.models.groups import SystemGroups
from zerver.models.realms import CommonPolicyEnum, CreateWebPublicStreamPolicyEnum, get_realm
from zerver.models.realms import CommonPolicyEnum, get_realm
from zerver.models.streams import get_default_stream_groups, get_stream
from zerver.models.users import active_non_guest_user_ids, get_user, get_user_profile_by_id_in_realm
from zerver.views.streams import compose_views
@ -810,7 +810,8 @@ class StreamAdminTest(ZulipTestCase):
self.assertFalse(user_profile.can_create_web_public_streams())
self.assertTrue(owner.can_create_web_public_streams())
# As per create_web_public_stream_policy, only owners can create web-public streams by default.
# As per can_create_web_public_channel_group, only owners
# can create web-public streams by default.
with self.assertRaisesRegex(JsonableError, "Insufficient permission"):
list_to_streams(
streams_raw,
@ -974,30 +975,36 @@ class StreamAdminTest(ZulipTestCase):
result = self.client_patch(f"/json/streams/{stream_id}", params)
self.assert_json_error(result, "Must be an organization administrator")
do_set_realm_property(
owners_group = NamedUserGroup.objects.get(
name=SystemGroups.OWNERS, realm=realm, is_system_group=True
)
do_change_realm_permission_group_setting(
realm,
"create_web_public_stream_policy",
CreateWebPublicStreamPolicyEnum.OWNERS_ONLY,
"can_create_web_public_channel_group",
owners_group,
acting_user=None,
)
do_change_user_role(user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
result = self.client_patch(f"/json/streams/{stream_id}", params)
self.assert_json_error(result, "Insufficient permission")
do_set_realm_property(
nobody_group = NamedUserGroup.objects.get(
name=SystemGroups.NOBODY, realm=realm, is_system_group=True
)
do_change_realm_permission_group_setting(
realm,
"create_web_public_stream_policy",
CreateWebPublicStreamPolicyEnum.NOBODY,
"can_create_web_public_channel_group",
nobody_group,
acting_user=None,
)
do_change_user_role(user_profile, UserProfile.ROLE_REALM_OWNER, acting_user=None)
result = self.client_patch(f"/json/streams/{stream_id}", params)
self.assert_json_error(result, "Insufficient permission")
do_set_realm_property(
do_change_realm_permission_group_setting(
realm,
"create_web_public_stream_policy",
CreateWebPublicStreamPolicyEnum.OWNERS_ONLY,
"can_create_web_public_channel_group",
owners_group,
acting_user=None,
)
do_change_user_role(user_profile, UserProfile.ROLE_REALM_OWNER, acting_user=None)
@ -4370,84 +4377,6 @@ class SubscriptionAPITest(ZulipTestCase):
result = self.common_subscribe_to_streams(self.test_user, [stream_name], allow_fail=True)
self.assert_json_error(result, "Invalid character in channel name, at position 4.")
def _test_user_settings_for_creating_streams(
self,
stream_policy: str,
*,
invite_only: bool,
is_web_public: bool,
) -> None:
user_profile = self.example_user("cordelia")
realm = user_profile.realm
do_set_realm_property(realm, stream_policy, CommonPolicyEnum.ADMINS_ONLY, acting_user=None)
do_change_user_role(user_profile, UserProfile.ROLE_MODERATOR, acting_user=None)
result = self.common_subscribe_to_streams(
user_profile,
["new_stream1"],
invite_only=invite_only,
is_web_public=is_web_public,
allow_fail=True,
)
self.assert_json_error(result, "Insufficient permission")
do_change_user_role(user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
self.common_subscribe_to_streams(user_profile, ["new_stream1"], invite_only=invite_only)
do_set_realm_property(
realm, stream_policy, CommonPolicyEnum.MODERATORS_ONLY, acting_user=None
)
do_change_user_role(user_profile, UserProfile.ROLE_MEMBER, acting_user=None)
# Make sure that we are checking the permission with a full member,
# as full member is the user just below moderator in the role hierarchy.
self.assertFalse(user_profile.is_provisional_member)
result = self.common_subscribe_to_streams(
user_profile,
["new_stream2"],
allow_fail=True,
invite_only=invite_only,
is_web_public=is_web_public,
)
self.assert_json_error(result, "Insufficient permission")
do_change_user_role(user_profile, UserProfile.ROLE_MODERATOR, acting_user=None)
self.common_subscribe_to_streams(user_profile, ["new_stream2"], invite_only=invite_only)
do_set_realm_property(realm, stream_policy, CommonPolicyEnum.MEMBERS_ONLY, acting_user=None)
do_change_user_role(user_profile, UserProfile.ROLE_GUEST, acting_user=None)
result = self.common_subscribe_to_streams(
user_profile,
["new_stream3"],
invite_only=invite_only,
is_web_public=is_web_public,
allow_fail=True,
)
self.assert_json_error(result, "Not allowed for guest users")
do_change_user_role(user_profile, UserProfile.ROLE_MEMBER, acting_user=None)
self.common_subscribe_to_streams(
self.test_user,
["new_stream4"],
invite_only=invite_only,
is_web_public=is_web_public,
)
do_set_realm_property(
realm, stream_policy, CommonPolicyEnum.FULL_MEMBERS_ONLY, acting_user=None
)
do_set_realm_property(realm, "waiting_period_threshold", 100000, acting_user=None)
result = self.common_subscribe_to_streams(
user_profile,
["new_stream5"],
invite_only=invite_only,
is_web_public=is_web_public,
allow_fail=True,
)
self.assert_json_error(result, "Insufficient permission")
do_set_realm_property(realm, "waiting_period_threshold", 0, acting_user=None)
self.common_subscribe_to_streams(user_profile, ["new_stream3"], invite_only=invite_only)
def _test_group_based_settings_for_creating_streams(
self,
stream_policy: str,
@ -4545,8 +4474,10 @@ class SubscriptionAPITest(ZulipTestCase):
)
def test_user_settings_for_creating_web_public_streams(self) -> None:
self._test_user_settings_for_creating_streams(
"create_web_public_stream_policy", invite_only=False, is_web_public=True
self._test_group_based_settings_for_creating_streams(
"can_create_web_public_channel_group",
invite_only=False,
is_web_public=True,
)
def test_stream_creator_id(self) -> None:
@ -4591,12 +4522,6 @@ class SubscriptionAPITest(ZulipTestCase):
# Other streams that weren't created using the api should have no creator.
self.assertIsNone(stream["creator_id"])
def test_web_public_stream_policies(self) -> None:
def validation_func(user_profile: UserProfile) -> bool:
return user_profile.can_create_web_public_streams()
self.check_has_permission_policies("create_web_public_stream_policy", validation_func)
def test_user_settings_for_subscribing_other_users(self) -> None:
"""
You can't subscribe other people to streams if you are a guest or your account is not old