diff --git a/web/e2e-tests/admin.test.ts b/web/e2e-tests/admin.test.ts index 0707398d93..d25a5bee1b 100644 --- a/web/e2e-tests/admin.test.ts +++ b/web/e2e-tests/admin.test.ts @@ -104,7 +104,6 @@ async function test_changing_create_streams_and_invite_to_stream_policies( ): Promise { const policies = { "create private stream": "#id_realm_create_private_stream_policy", - "create public stream": "#id_realm_create_public_stream_policy", "invite to stream": "#id_realm_invite_to_stream_policy", }; const policy_values = { diff --git a/web/src/server_events_dispatch.js b/web/src/server_events_dispatch.js index e32f02b78a..d3e9888afc 100644 --- a/web/src/server_events_dispatch.js +++ b/web/src/server_events_dispatch.js @@ -204,7 +204,6 @@ export function dispatch_normal_event(event) { avatar_changes_disabled: settings_account.update_avatar_change_display, bot_creation_policy: settings_bots.update_bot_permissions_ui, create_multiuse_invite_group: noop, - create_public_stream_policy: noop, create_private_stream_policy: noop, create_web_public_stream_policy: noop, invite_to_stream_policy: noop, @@ -268,7 +267,6 @@ export function dispatch_normal_event(event) { const stream_creation_settings = [ "create_private_stream_policy", - "create_public_stream_policy", "create_web_public_stream_policy", ]; if (stream_creation_settings.includes(event.property)) { @@ -297,6 +295,10 @@ export function dispatch_normal_event(event) { gear_menu.rerender(); } + if (key === "can_create_public_channel_group") { + stream_settings_ui.update_stream_privacy_choices(key); + } + if (key === "edit_topic_policy") { message_live_update.rerender_messages_view(); } diff --git a/web/src/settings_components.ts b/web/src/settings_components.ts index ce6e25611d..4840ace97e 100644 --- a/web/src/settings_components.ts +++ b/web/src/settings_components.ts @@ -204,7 +204,6 @@ export function get_subsection_property_elements($subsection: JQuery): HTMLEleme type simple_dropdown_realm_settings = Pick< typeof realm, | "realm_create_private_stream_policy" - | "realm_create_public_stream_policy" | "realm_create_web_public_stream_policy" | "realm_invite_to_stream_policy" | "realm_user_group_edit_policy" @@ -472,6 +471,7 @@ export let can_remove_subscribers_group_widget: DropdownWidget | null = null; export let can_access_all_users_group_widget: DropdownWidget | null = null; export let can_mention_group_widget: DropdownWidget | null = null; export let new_group_can_mention_group_widget: DropdownWidget | null = null; +export let can_create_public_channel_group_widget: DropdownWidget | null = null; export function get_widget_for_dropdown_list_settings( property_name: string, @@ -493,6 +493,8 @@ export function get_widget_for_dropdown_list_settings( return can_access_all_users_group_widget; case "can_mention_group": return can_mention_group_widget; + case "realm_can_create_public_channel_group": + return can_create_public_channel_group_widget; default: blueslip.error("No dropdown list widget for property", {property_name}); return null; @@ -535,6 +537,10 @@ export function set_new_group_can_mention_group_widget(widget: DropdownWidget): new_group_can_mention_group_widget = widget; } +export function set_can_create_public_channel_group_widget(widget: DropdownWidget): void { + can_create_public_channel_group_widget = widget; +} + export function set_dropdown_list_widget_setting_value( property_name: string, value: number | string, @@ -812,6 +818,7 @@ export function check_realm_settings_property_changed(elem: HTMLElement): boolea case "realm_default_code_block_language": case "realm_create_multiuse_invite_group": case "realm_can_access_all_users_group": + case "realm_can_create_public_channel_group": proposed_val = get_dropdown_list_widget_setting_value($elem); break; case "realm_message_content_edit_limit_seconds": @@ -1001,6 +1008,14 @@ export function populate_data_for_realm_settings_request( }; continue; } + + if (property_name === "can_create_public_channel_group") { + data[property_name] = JSON.stringify({ + new: input_value, + old: realm.realm_can_create_public_channel_group, + }); + continue; + } data[property_name] = input_value; } } diff --git a/web/src/settings_data.ts b/web/src/settings_data.ts index 49939f9ff0..af5b6ca75a 100644 --- a/web/src/settings_data.ts +++ b/web/src/settings_data.ts @@ -144,7 +144,13 @@ export function user_can_create_private_streams(): boolean { } export function user_can_create_public_streams(): boolean { - return user_has_permission(realm.realm_create_public_stream_policy); + if (!current_user.user_id) { + return false; + } + return user_groups.is_user_in_group( + realm.realm_can_create_public_channel_group, + current_user.user_id, + ); } export function user_can_create_web_public_streams(): boolean { diff --git a/web/src/settings_org.js b/web/src/settings_org.js index 209de2cdea..6325e4754c 100644 --- a/web/src/settings_org.js +++ b/web/src/settings_org.js @@ -120,7 +120,6 @@ export function get_org_type_dropdown_options() { const simple_dropdown_properties = [ "realm_create_private_stream_policy", - "realm_create_public_stream_policy", "realm_create_web_public_stream_policy", "realm_invite_to_stream_policy", "realm_user_group_edit_policy", @@ -487,6 +486,7 @@ export function discard_realm_property_element_changes(elem) { case "realm_default_code_block_language": case "realm_create_multiuse_invite_group": case "realm_can_access_all_users_group": + case "realm_can_create_public_channel_group": settings_components.set_dropdown_list_widget_setting_value( property_name, property_value, @@ -887,6 +887,37 @@ export function init_dropdown_widgets() { }); settings_components.set_can_access_all_users_group_widget(can_access_all_users_group_widget); can_access_all_users_group_widget.setup(); + + const can_create_public_channel_group_widget = new dropdown_widget.DropdownWidget({ + widget_name: "realm_can_create_public_channel_group", + get_options: () => + user_groups.get_realm_user_groups_for_dropdown_list_widget( + "can_create_public_channel_group", + "realm", + ), + $events_container: $("#settings_overlay_container #organization-permissions"), + item_click_callback(event, dropdown) { + dropdown.hide(); + event.preventDefault(); + event.stopPropagation(); + settings_components.can_create_public_channel_group_widget.render(); + settings_components.save_discard_realm_settings_widget_status_handler( + $("#org-stream-permissions"), + ); + }, + tippy_props: { + placement: "bottom-start", + }, + default_id: realm.realm_can_create_public_channel_group, + unique_id_type: dropdown_widget.DataTypes.NUMBER, + on_mount_callback(dropdown) { + $(dropdown.popper).css("min-width", "300px"); + }, + }); + settings_components.set_can_create_public_channel_group_widget( + can_create_public_channel_group_widget, + ); + can_create_public_channel_group_widget.setup(); } export function register_save_discard_widget_handlers( diff --git a/web/src/state_data.ts b/web/src/state_data.ts index cc5772bfed..ce646d5622 100644 --- a/web/src/state_data.ts +++ b/web/src/state_data.ts @@ -84,9 +84,9 @@ export const realm_schema = z.object({ realm_avatar_changes_disabled: z.boolean(), realm_bot_domain: z.string(), realm_can_access_all_users_group: z.number(), + realm_can_create_public_channel_group: z.number(), realm_create_multiuse_invite_group: z.number(), realm_create_private_stream_policy: z.number(), - realm_create_public_stream_policy: z.number(), realm_create_web_public_stream_policy: z.number(), realm_date_created: z.number(), realm_default_code_block_language: z.string(), diff --git a/web/src/stream_settings_ui.js b/web/src/stream_settings_ui.js index 2976bc4197..0d139984dc 100644 --- a/web/src/stream_settings_ui.js +++ b/web/src/stream_settings_ui.js @@ -950,7 +950,7 @@ export function update_stream_privacy_choices(policy) { if (policy === "create_private_stream_policy") { stream_ui_updates.update_private_stream_privacy_option_state($container); } - if (policy === "create_public_stream_policy") { + if (policy === "can_create_public_channel_group") { stream_settings_components.update_public_stream_privacy_option_state($container); } if (policy === "create_web_public_stream_policy") { diff --git a/web/src/ui_init.js b/web/src/ui_init.js index 300383537f..f453dbcc14 100644 --- a/web/src/ui_init.js +++ b/web/src/ui_init.js @@ -559,9 +559,9 @@ export function initialize_everything(state_data) { "realm_bot_creation_policy", "realm_bot_domain", "realm_can_access_all_users_group", + "realm_can_create_public_channel_group", "realm_create_multiuse_invite_group", "realm_create_private_stream_policy", - "realm_create_public_stream_policy", "realm_create_web_public_stream_policy", "realm_date_created", "realm_default_code_block_language", diff --git a/web/styles/settings.css b/web/styles/settings.css index a50375b9f8..43c980d014 100644 --- a/web/styles/settings.css +++ b/web/styles/settings.css @@ -831,7 +831,8 @@ input[type="checkbox"] { } #org-join-settings, -#org-guest-settings { +#org-guest-settings, +#org-stream-permissions { .dropdown-widget-button { width: 325px; color: hsl(0deg 0% 33%); diff --git a/web/templates/settings/organization_permissions_admin.hbs b/web/templates/settings/organization_permissions_admin.hbs index 5c6ae77aa6..36d28c5f63 100644 --- a/web/templates/settings/organization_permissions_admin.hbs +++ b/web/templates/settings/organization_permissions_admin.hbs @@ -68,12 +68,11 @@ {{> settings_save_discard_widget section_name="stream-permissions" }}
-
- - -
+ {{> ../dropdown_widget_with_label + widget_name="realm_can_create_public_channel_group" + label=(t 'Who can create public channels') + value_type="number"}} + {{> upgrade_tip_widget }} {{> settings_checkbox setting_name="realm_enable_spectator_access" diff --git a/web/tests/dispatch.test.js b/web/tests/dispatch.test.js index bdc9f36338..7c5efde6cb 100644 --- a/web/tests/dispatch.test.js +++ b/web/tests/dispatch.test.js @@ -495,14 +495,6 @@ run_test("realm settings", ({override}) => { }; test_realm_integer(event, "realm_create_private_stream_policy"); - update_called = false; - event = event_fixtures.realm__update__create_public_stream_policy; - stream_settings_ui.update_stream_privacy_choices = (property) => { - assert_same(property, "create_public_stream_policy"); - update_called = true; - }; - test_realm_integer(event, "realm_create_public_stream_policy"); - update_called = false; event = event_fixtures.realm__update__create_web_public_stream_policy; stream_settings_ui.update_stream_privacy_choices = (property) => { @@ -575,12 +567,19 @@ run_test("realm settings", ({override}) => { assert_same(realm.realm_enable_spectator_access, true); assert_same(update_called, true); + let update_stream_privacy_choices_called = false; + stream_settings_ui.update_stream_privacy_choices = (property) => { + assert_same(property, "can_create_public_channel_group"); + update_stream_privacy_choices_called = true; + }; + event = event_fixtures.realm__update_dict__default; realm.realm_create_multiuse_invite_group = 1; realm.realm_allow_message_editing = false; realm.realm_message_content_edit_limit_seconds = 0; realm.realm_edit_topic_policy = 3; realm.realm_authentication_methods = {Google: {enabled: false, available: true}}; + realm.realm_can_create_public_channel_group = 1; override(settings_org, "populate_auth_methods", noop); dispatch(event); assert_same(realm.realm_create_multiuse_invite_group, 3); @@ -590,6 +589,8 @@ run_test("realm settings", ({override}) => { assert_same(realm.realm_authentication_methods, { Google: {enabled: true, available: true}, }); + assert_same(realm.realm_can_create_public_channel_group, 3); + assert_same(update_stream_privacy_choices_called, true); event = event_fixtures.realm__update_dict__icon; override(realm_icon, "rerender", noop); diff --git a/web/tests/lib/events.js b/web/tests/lib/events.js index a1feb5e726..7e49e6c2f0 100644 --- a/web/tests/lib/events.js +++ b/web/tests/lib/events.js @@ -387,6 +387,7 @@ exports.fixtures = { authentication_methods: { Google: {enabled: true, available: true}, }, + can_create_public_channel_group: 3, }, }, diff --git a/web/tests/settings_data.test.js b/web/tests/settings_data.test.js index e1d1d2cf1f..424ba0220c 100644 --- a/web/tests/settings_data.test.js +++ b/web/tests/settings_data.test.js @@ -146,11 +146,6 @@ test_policy( "realm_create_private_stream_policy", settings_data.user_can_create_private_streams, ); -test_policy( - "user_can_create_public_streams", - "realm_create_public_stream_policy", - settings_data.user_can_create_public_streams, -); test_policy( "user_can_subscribe_other_users", "realm_invite_to_stream_policy", @@ -459,3 +454,42 @@ run_test("user_can_access_all_other_users", () => { realm.realm_can_access_all_users_group = everyone.id; assert.ok(settings_data.user_can_access_all_other_users()); }); + +run_test("user_can_create_public_streams", () => { + const admin_user_id = 1; + const moderator_user_id = 2; + const member_user_id = 3; + + const admins = { + name: "Admins", + id: 1, + members: new Set([admin_user_id]), + is_system_group: true, + direct_subgroup_ids: new Set([]), + }; + const moderators = { + name: "Moderators", + id: 2, + members: new Set([moderator_user_id]), + is_system_group: true, + direct_subgroup_ids: new Set([1]), + }; + + user_groups.initialize({realm_user_groups: [admins, moderators]}); + + assert.equal(settings_data.user_can_create_public_streams(), false); + + realm.realm_can_create_public_channel_group = 1; + current_user.user_id = admin_user_id; + assert.equal(settings_data.user_can_create_public_streams(), true); + + current_user.user_id = moderator_user_id; + assert.equal(settings_data.user_can_create_public_streams(), false); + + realm.realm_can_create_public_channel_group = 2; + current_user.user_id = moderator_user_id; + assert.equal(settings_data.user_can_create_public_streams(), true); + + current_user.user_id = member_user_id; + assert.equal(settings_data.user_can_create_public_streams(), false); +}); diff --git a/web/tests/settings_org.test.js b/web/tests/settings_org.test.js index 7642d2bc32..1b9e404b5e 100644 --- a/web/tests/settings_org.test.js +++ b/web/tests/settings_org.test.js @@ -101,7 +101,6 @@ function test_submit_settings_form(override, submit_form) { realm_default_language: '"es"', realm_invite_to_stream_policy: settings_config.common_policy_values.by_admins_only.code, realm_create_private_stream_policy: settings_config.common_policy_values.by_members.code, - realm_create_public_stream_policy: settings_config.common_policy_values.by_members.code, realm_invite_to_realm_policy: settings_config.common_policy_values.by_members.code, }); @@ -135,11 +134,6 @@ function test_submit_settings_form(override, submit_form) { $invite_to_stream_policy_elem.attr("id", "id_realm_invite_to_stream_policy"); $invite_to_stream_policy_elem.data = () => "number"; - const $create_public_stream_policy_elem = $("#id_realm_create_public_stream_policy"); - $create_public_stream_policy_elem.val("2"); - $create_public_stream_policy_elem.attr("id", "id_realm_create_public_stream_policy"); - $create_public_stream_policy_elem.data = () => "number"; - const $create_private_stream_policy_elem = $("#id_realm_create_private_stream_policy"); $create_private_stream_policy_elem.val("2"); $create_private_stream_policy_elem.attr("id", "id_realm_create_private_stream_policy"); @@ -164,7 +158,6 @@ function test_submit_settings_form(override, submit_form) { $subsection_elem.set_find_results(".prop-element", [ $bot_creation_policy_elem, $add_custom_emoji_policy_elem, - $create_public_stream_policy_elem, $create_private_stream_policy_elem, $invite_to_realm_policy_elem, $invite_to_stream_policy_elem, @@ -179,7 +172,6 @@ function test_submit_settings_form(override, submit_form) { invite_to_realm_policy: 2, invite_to_stream_policy: 1, add_custom_emoji_policy: 1, - create_public_stream_policy: 2, create_private_stream_policy: 2, }; assert.deepEqual(data, expected_value); @@ -335,7 +327,6 @@ function test_sync_realm_settings() { } test_common_policy("create_private_stream_policy"); - test_common_policy("create_public_stream_policy"); test_common_policy("invite_to_stream_policy"); test_common_policy("invite_to_realm_policy"); @@ -348,7 +339,6 @@ function test_sync_realm_settings() { $property_elem.attr("id", "id_realm_message_content_edit_limit_minutes"); $property_dropdown_elem.attr("id", "id_realm_message_content_edit_limit_seconds"); - realm.realm_create_public_stream_policy = 1; realm.realm_message_content_edit_limit_seconds = 120; settings_org.sync_realm_settings("message_content_edit_limit_seconds");