diff --git a/api_docs/changelog.md b/api_docs/changelog.md index 2de9d2825f..1c9cd5bb8d 100644 --- a/api_docs/changelog.md +++ b/api_docs/changelog.md @@ -26,6 +26,14 @@ format used by the Zulip server that they are interacting with. [`GET /events`](/api/get-events): Added `can_create_public_channel_group` realm setting, which is a [group-setting value](/api/group-setting-values) describing the set of users with permission to create channels. +* `PATCH /realm`, [`GET /events`](/api/get-events): Removed + `create_public_stream_policy` property, as the permission to create public + channels is now controlled by `can_create_public_channel_group` setting. +* [`POST /register`](/api/register-queue): `realm_create_public_stream_policy` + field is deprecated, having been replaced by `can_create_public_channel_group`. + Notably, this backwards-compatible `realm_create_public_stream_policy` value + now contains the superset of the true value that best approximates the actual + permission setting. **Feature level 263**: diff --git a/version.py b/version.py index ee40eead63..9bd8a05d94 100644 --- a/version.py +++ b/version.py @@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.9.3" # Changes should be accompanied by documentation explaining what the # new level means in api_docs/changelog.md, as well as "**Changes**" # entries in the endpoint's documentation in `zulip.yaml`. -API_FEATURE_LEVEL = 263 +API_FEATURE_LEVEL = 264 # Bump the minor PROVISION_VERSION to indicate that folks should provision # only when going from an old version of the code to a newer version. Bump diff --git a/web/tests/lib/events.js b/web/tests/lib/events.js index 7e49e6c2f0..63691223de 100644 --- a/web/tests/lib/events.js +++ b/web/tests/lib/events.js @@ -270,13 +270,6 @@ exports.fixtures = { value: 2, }, - realm__update__create_public_stream_policy: { - type: "realm", - op: "update", - property: "create_public_stream_policy", - value: 2, - }, - realm__update__create_web_public_stream_policy: { type: "realm", op: "update", diff --git a/zerver/actions/create_realm.py b/zerver/actions/create_realm.py index 3cb7cb3f23..6aee7a4077 100644 --- a/zerver/actions/create_realm.py +++ b/zerver/actions/create_realm.py @@ -121,9 +121,6 @@ def set_realm_permissions_based_on_org_type(realm: Realm) -> None: ): # Limit user creation to administrators. realm.invite_to_realm_policy = InviteToRealmPolicyEnum.ADMINS_ONLY - # Restrict public stream creation to staff, but allow private - # streams (useful for study groups, etc.). - realm.create_public_stream_policy = CommonPolicyEnum.ADMINS_ONLY # Don't allow members (students) to manage user groups or # stream subscriptions. realm.user_group_edit_policy = CommonPolicyEnum.MODERATORS_ONLY diff --git a/zerver/lib/events.py b/zerver/lib/events.py index 658dc21e35..4455cfc40c 100644 --- a/zerver/lib/events.py +++ b/zerver/lib/events.py @@ -89,7 +89,12 @@ from zerver.models.custom_profile_fields import custom_profile_fields_for_realm from zerver.models.linkifiers import linkifiers_for_realm from zerver.models.realm_emoji import get_all_custom_emoji_for_realm from zerver.models.realm_playgrounds import get_realm_playgrounds -from zerver.models.realms import CommonMessagePolicyEnum, EditTopicPolicyEnum, get_realm_domains +from zerver.models.realms import ( + CommonMessagePolicyEnum, + EditTopicPolicyEnum, + get_corresponding_policy_value_for_group_setting, + get_realm_domains, +) from zerver.models.streams import get_default_stream_groups from zerver.tornado.django_api import get_user_events, request_event_queue from zproject.backends import email_auth_enabled, password_auth_enabled @@ -287,6 +292,12 @@ def fetch_initial_state_data( state["realm_" + setting_name] = getattr(realm, permission_configuration.id_field_name) + state["realm_create_public_stream_policy"] = ( + get_corresponding_policy_value_for_group_setting( + realm, "can_create_public_channel_group", Realm.COMMON_POLICY_TYPES + ) + ) + # Most state is handled via the property_types framework; # these manual entries are for those realm settings that don't # fit into that framework. @@ -1235,6 +1246,13 @@ def apply_event( state["realm_email_auth_enabled"] = value["Email"]["enabled"] if key == "can_create_public_channel_group": + state["realm_create_public_stream_policy"] = ( + get_corresponding_policy_value_for_group_setting( + user_profile.realm, + "can_create_public_channel_group", + Realm.COMMON_POLICY_TYPES, + ) + ) state["can_create_public_streams"] = user_profile.has_permission(key) state["can_create_streams"] = ( state["can_create_private_streams"] diff --git a/zerver/migrations/0535_remove_realm_create_public_stream_policy.py b/zerver/migrations/0535_remove_realm_create_public_stream_policy.py new file mode 100644 index 0000000000..1eff0f9fc2 --- /dev/null +++ b/zerver/migrations/0535_remove_realm_create_public_stream_policy.py @@ -0,0 +1,16 @@ +# Generated by Django 5.0.6 on 2024-05-30 08:58 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("zerver", "0534_alter_realm_can_create_public_channel_group"), + ] + + operations = [ + migrations.RemoveField( + model_name="realm", + name="create_public_stream_policy", + ), + ] diff --git a/zerver/models/realms.py b/zerver/models/realms.py index 31e1bf4a04..4dd2549c06 100644 --- a/zerver/models/realms.py +++ b/zerver/models/realms.py @@ -263,6 +263,16 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub POLICY_NOBODY = 6 POLICY_OWNERS_ONLY = 7 + SYSTEM_GROUPS_ENUM_MAP = { + SystemGroups.OWNERS: POLICY_OWNERS_ONLY, + SystemGroups.ADMINISTRATORS: POLICY_ADMINS_ONLY, + SystemGroups.MODERATORS: POLICY_MODERATORS_ONLY, + SystemGroups.FULL_MEMBERS: POLICY_FULL_MEMBERS_ONLY, + SystemGroups.MEMBERS: POLICY_MEMBERS_ONLY, + SystemGroups.EVERYONE: POLICY_EVERYONE, + SystemGroups.NOBODY: POLICY_NOBODY, + } + COMMON_POLICY_TYPES = [field.value for field in CommonPolicyEnum] COMMON_MESSAGE_POLICY_TYPES = [field.value for field in CommonMessagePolicyEnum] @@ -293,9 +303,6 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub ) # Who in the organization is allowed to create streams. - create_public_stream_policy = models.PositiveSmallIntegerField( - default=CommonPolicyEnum.MEMBERS_ONLY - ) create_private_stream_policy = models.PositiveSmallIntegerField( default=CommonPolicyEnum.MEMBERS_ONLY ) @@ -638,7 +645,6 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub avatar_changes_disabled=bool, bot_creation_policy=int, create_private_stream_policy=int, - create_public_stream_policy=int, create_web_public_stream_policy=int, default_code_block_language=str, default_language=str, @@ -1093,6 +1099,27 @@ def get_org_type_display_name(org_type: int) -> str: return "" +def get_corresponding_policy_value_for_group_setting( + realm: Realm, + group_setting_name: str, + valid_policy_enums: List[int], +) -> int: + setting_group = getattr(realm, group_setting_name) + if ( + hasattr(setting_group, "named_user_group") + and setting_group.named_user_group.is_system_group + ): + enum_policy_value = Realm.SYSTEM_GROUPS_ENUM_MAP[setting_group.named_user_group.name] + if enum_policy_value in valid_policy_enums: + return enum_policy_value + + # If the group setting is not set to one of the role based groups + # that the previous enum setting allowed, then just return the + # enum value corresponding to largest group. + assert valid_policy_enums == Realm.COMMON_POLICY_TYPES + return Realm.POLICY_MEMBERS_ONLY + + class RealmDomain(models.Model): """For an organization with emails_restricted_to_domains enabled, the list of allowed domains""" diff --git a/zerver/models/users.py b/zerver/models/users.py index 115a81f5af..d8623c49ff 100644 --- a/zerver/models/users.py +++ b/zerver/models/users.py @@ -752,7 +752,6 @@ class UserProfile(AbstractBaseUser, PermissionsMixin, UserBaseSettings): "can_create_public_channel_group", "create_multiuse_invite_group", "create_private_stream_policy", - "create_public_stream_policy", "create_web_public_stream_policy", "delete_own_message_policy", "edit_topic_policy", diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml index 177ff49f61..a406c715b9 100644 --- a/zerver/openapi/zulip.yaml +++ b/zerver/openapi/zulip.yaml @@ -4240,14 +4240,6 @@ paths: **Changes**: New in Zulip 9.0 (feature level 264). Previously `realm_create_public_stream_policy` field used to control the permission to create public channels. - create_public_stream_policy: - type: integer - description: | - The [policy](/api/roles-and-permissions#permission-levels) - for which users can create public channels in this organization. - - **Changes**: Before Zulip 5.0 (feature level 102), permission to - create channels was controlled by the `create_stream_policy` setting. create_private_stream_policy: type: integer description: | @@ -15252,19 +15244,30 @@ paths: permission to create public channels. realm_create_public_stream_policy: type: integer + deprecated: true description: | Present if `realm` is present in `fetch_event_types`. - The [policy][permission-level] for which users can create public channels - in this organization. + A deprecated representation of a superset of the users who + have permission to create public channels in the organization, + available for backwards-compatibility. Clients should use + `can_create_public_channel_group` instead. + + It is an enum with the following possible values, corresponding + to roles/system groups: - 1 = Members only - 2 = Admins only - 3 = [Full members][calc-full-member] only - 4 = Admins and moderators only - **Changes**: Before Zulip 5.0 (feature level 102), permission to - create channels was controlled by the `realm_create_stream_policy` setting. + **Changes**: Deprecated in Zulip 9.0 (feature level 264) and + replaced by `realm_can_create_public_channel_group`, which + supports finer resolution of configurations, resulting in this + property being inaccurate following that transition. + + Before Zulip 5.0 (feature level 102), permission to create + channels was controlled by the `realm_create_stream_policy` setting. [permission-level]: /api/roles-and-permissions#permission-levels [calc-full-member]: /api/roles-and-permissions#determining-if-a-user-is-a-full-member diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index 115c6a420e..7b7a738ced 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -3397,7 +3397,6 @@ class RealmPropertyActionTest(BaseAction): message_retention_days=[10, 20], name=["Zulip", "New Name"], waiting_period_threshold=[1000, 2000], - create_public_stream_policy=Realm.COMMON_POLICY_TYPES, create_private_stream_policy=Realm.COMMON_POLICY_TYPES, create_web_public_stream_policy=Realm.CREATE_WEB_PUBLIC_STREAM_POLICY_TYPES, invite_to_stream_policy=Realm.COMMON_POLICY_TYPES, diff --git a/zerver/tests/test_realm.py b/zerver/tests/test_realm.py index c08f06b13f..29d46c6c5f 100644 --- a/zerver/tests/test_realm.py +++ b/zerver/tests/test_realm.py @@ -111,7 +111,6 @@ class RealmTest(ZulipTestCase): ) self.assertEqual(realm.can_create_public_channel_group_id, admins_group.id) - self.assertEqual(realm.create_public_stream_policy, CommonPolicyEnum.ADMINS_ONLY) self.assertEqual(realm.create_private_stream_policy, CommonPolicyEnum.MEMBERS_ONLY) self.assertEqual(realm.invite_to_realm_policy, InviteToRealmPolicyEnum.ADMINS_ONLY) self.assertEqual( @@ -133,7 +132,6 @@ class RealmTest(ZulipTestCase): ) self.assertEqual(realm.can_create_public_channel_group_id, admins_group.id) - self.assertEqual(realm.create_public_stream_policy, CommonPolicyEnum.ADMINS_ONLY) self.assertEqual(realm.create_private_stream_policy, CommonPolicyEnum.MEMBERS_ONLY) self.assertEqual(realm.invite_to_realm_policy, InviteToRealmPolicyEnum.ADMINS_ONLY) self.assertEqual( @@ -763,7 +761,6 @@ class RealmTest(ZulipTestCase): invalid_values = dict( bot_creation_policy=10, - create_public_stream_policy=10, create_private_stream_policy=10, create_web_public_stream_policy=10, invite_to_stream_policy=10, @@ -1484,7 +1481,6 @@ class RealmAPITest(ZulipTestCase): name=["Zulip", "New Name"], waiting_period_threshold=[10, 20], create_private_stream_policy=Realm.COMMON_POLICY_TYPES, - create_public_stream_policy=Realm.COMMON_POLICY_TYPES, create_web_public_stream_policy=Realm.CREATE_WEB_PUBLIC_STREAM_POLICY_TYPES, user_group_edit_policy=Realm.COMMON_POLICY_TYPES, private_message_policy=Realm.PRIVATE_MESSAGE_POLICY_TYPES, diff --git a/zerver/tests/test_subs.py b/zerver/tests/test_subs.py index 85d4a54527..d93cd7df0b 100644 --- a/zerver/tests/test_subs.py +++ b/zerver/tests/test_subs.py @@ -4613,9 +4613,6 @@ class SubscriptionAPITest(ZulipTestCase): invitee_user_id = user_profile.id realm = user_profile.realm - do_set_realm_property( - realm, "create_public_stream_policy", CommonPolicyEnum.MEMBERS_ONLY, acting_user=None - ) do_set_realm_property( realm, "invite_to_stream_policy", CommonPolicyEnum.ADMINS_ONLY, acting_user=None ) diff --git a/zerver/views/realm.py b/zerver/views/realm.py index e036d9efbc..f2eadba6cd 100644 --- a/zerver/views/realm.py +++ b/zerver/views/realm.py @@ -148,7 +148,6 @@ def update_realm( message_content_allowed_in_email_notifications: Optional[Json[bool]] = None, bot_creation_policy: Optional[Json[BotCreationPolicyEnum]] = None, can_create_public_channel_group: Optional[Json[GroupSettingChangeRequest]] = None, - create_public_stream_policy: Optional[Json[CommonPolicyEnum]] = None, create_private_stream_policy: Optional[Json[CommonPolicyEnum]] = None, create_web_public_stream_policy: Optional[Json[CreateWebPublicStreamPolicyEnum]] = None, invite_to_stream_policy: Optional[Json[CommonPolicyEnum]] = None,