From 80969a62e6c9b4afccf688e89c7974d84a43fec8 Mon Sep 17 00:00:00 2001 From: Vector73 Date: Thu, 15 Aug 2024 10:59:15 +0530 Subject: [PATCH] settings: Add `can_delete_any_message_group` setting. Fixes #30717. --- api_docs/changelog.md | 7 + tools/lib/capitalization.py | 2 +- version.py | 2 +- web/src/admin.js | 1 + web/src/message_edit.js | 2 +- web/src/server_events_dispatch.js | 1 + web/src/settings_components.ts | 3 + web/src/settings_data.ts | 10 + web/src/settings_org.js | 64 ++++- web/src/state_data.ts | 1 + .../organization_permissions_admin.hbs | 10 +- web/tests/message_edit.test.js | 7 +- web/tests/popover_menus_data.test.js | 16 +- web/tests/settings_data.test.js | 5 + web/tests/settings_org.test.js | 1 + zerver/lib/event_schema.py | 1 + ...0565_realm_can_delete_any_message_group.py | 23 ++ ...efault_for_can_delete_any_message_group.py | 39 +++ ...lter_realm_can_delete_any_message_group.py | 22 ++ zerver/models/realms.py | 17 ++ zerver/models/users.py | 4 + zerver/openapi/zulip.yaml | 20 ++ zerver/tests/test_home.py | 1 + zerver/tests/test_message_delete.py | 236 ++++++++++++++++-- zerver/views/message_edit.py | 3 +- zerver/views/realm.py | 1 + 26 files changed, 446 insertions(+), 53 deletions(-) create mode 100644 zerver/migrations/0565_realm_can_delete_any_message_group.py create mode 100644 zerver/migrations/0566_set_default_for_can_delete_any_message_group.py create mode 100644 zerver/migrations/0567_alter_realm_can_delete_any_message_group.py diff --git a/api_docs/changelog.md b/api_docs/changelog.md index 44ca4db5f8..27b7d5402c 100644 --- a/api_docs/changelog.md +++ b/api_docs/changelog.md @@ -20,6 +20,13 @@ format used by the Zulip server that they are interacting with. ## Changes in Zulip 10.0 +**Feature level 281** + +* [`GET /events`](/api/get-events), [`POST /register`](/api/register-queue): + Added a new realm setting `realm_can_delete_any_message_group` which is a + [group-setting value](/api/group-setting-values) describing the set of + users with permission to delete any message in the organization. + **Feature level 280** * `PATCH /realm`, [`POST /register`](/api/register-queue), diff --git a/tools/lib/capitalization.py b/tools/lib/capitalization.py index 9194dea3ac..e2dec6a2ce 100644 --- a/tools/lib/capitalization.py +++ b/tools/lib/capitalization.py @@ -157,7 +157,7 @@ IGNORED_PHRASES = [ # Used in message-move-time-limit setting label r"does not apply to moderators and administrators", # Used in message-delete-time-limit setting label - r"does not apply to administrators", + r"does not apply to users who can delete any message", # Used as indicator with names for guest users. r"guest", # Used in pills for deactivated users. diff --git a/version.py b/version.py index 318918baba..01d2abce11 100644 --- a/version.py +++ b/version.py @@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3" # new level means in api_docs/changelog.md, as well as "**Changes**" # entries in the endpoint's documentation in `zulip.yaml`. -API_FEATURE_LEVEL = 280 # Last bumped for can_create_web_public_channel_group +API_FEATURE_LEVEL = 281 # Last bumped for realm_can_delete_any_message_group # Bump the minor PROVISION_VERSION to indicate that folks should provision diff --git a/web/src/admin.js b/web/src/admin.js index 56f904416a..17ccd514e2 100644 --- a/web/src/admin.js +++ b/web/src/admin.js @@ -183,6 +183,7 @@ export function build_page() { can_invite_users_by_email: settings_data.user_can_invite_users_by_email(), realm_invite_required: realm.realm_invite_required, policy_values: settings_config.common_policy_values, + realm_can_delete_any_message_group: realm.realm_can_delete_any_message_group, realm_delete_own_message_policy: realm.realm_delete_own_message_policy, DELETE_OWN_MESSAGE_POLICY_ADMINS_ONLY: settings_config.common_message_policy_values.by_admins_only.code, diff --git a/web/src/message_edit.js b/web/src/message_edit.js index 17ae158d58..b6e871bd65 100644 --- a/web/src/message_edit.js +++ b/web/src/message_edit.js @@ -178,7 +178,7 @@ export function is_message_sent_by_my_bot(message) { } export function get_deletability(message) { - if (current_user.is_admin) { + if (settings_data.user_can_delete_any_message()) { return true; } diff --git a/web/src/server_events_dispatch.js b/web/src/server_events_dispatch.js index a31d9b3a1c..36358d0be7 100644 --- a/web/src/server_events_dispatch.js +++ b/web/src/server_events_dispatch.js @@ -204,6 +204,7 @@ export function dispatch_normal_event(event) { user_group_edit_policy: noop, avatar_changes_disabled: settings_account.update_avatar_change_display, bot_creation_policy: settings_bots.update_bot_permissions_ui, + can_delete_any_message_group: noop, create_multiuse_invite_group: noop, invite_to_stream_policy: noop, default_code_block_language: noop, diff --git a/web/src/settings_components.ts b/web/src/settings_components.ts index 15c4ced74d..d2fa8c6ec3 100644 --- a/web/src/settings_components.ts +++ b/web/src/settings_components.ts @@ -479,6 +479,7 @@ const dropdown_widget_map = new Map([ ["realm_can_create_public_channel_group", null], ["realm_can_create_private_channel_group", null], ["realm_can_create_web_public_channel_group", null], + ["realm_can_delete_any_message_group", null], ["realm_direct_message_initiator_group", null], ["realm_direct_message_permission_group", null], ]); @@ -794,6 +795,7 @@ export function check_realm_settings_property_changed(elem: HTMLElement): boolea case "realm_can_create_public_channel_group": case "realm_can_create_private_channel_group": case "realm_can_create_web_public_channel_group": + case "realm_can_delete_any_message_group": case "realm_direct_message_initiator_group": case "realm_direct_message_permission_group": proposed_val = get_dropdown_list_widget_setting_value($elem); @@ -990,6 +992,7 @@ export function populate_data_for_realm_settings_request( "can_create_private_channel_group", "can_create_public_channel_group", "can_create_web_public_channel_group", + "can_delete_any_message_group", "direct_message_initiator_group", "direct_message_permission_group", ]); diff --git a/web/src/settings_data.ts b/web/src/settings_data.ts index 4821e13c97..f95aeb724f 100644 --- a/web/src/settings_data.ts +++ b/web/src/settings_data.ts @@ -193,6 +193,16 @@ export function user_can_move_messages_to_another_topic(): boolean { return user_has_permission(realm.realm_edit_topic_policy); } +export function user_can_delete_any_message(): boolean { + if (page_params.is_spectator) { + return false; + } + return user_groups.is_user_in_group( + realm.realm_can_delete_any_message_group, + current_user.user_id, + ); +} + export function user_can_delete_own_message(): boolean { return user_has_permission(realm.realm_delete_own_message_policy); } diff --git a/web/src/settings_org.js b/web/src/settings_org.js index f9143d7bf1..866b934e19 100644 --- a/web/src/settings_org.js +++ b/web/src/settings_org.js @@ -261,36 +261,68 @@ function set_msg_move_limit_setting(property_name) { enable_or_disable_related_message_move_time_limit_setting(property_name, disable_setting); } -function message_delete_limit_setting_enabled(setting_value) { +function message_delete_limit_setting_enabled() { // This function is used to check whether the time-limit setting - // should be enabled. The setting is disabled when delete_own_message_policy - // is set to 'admins only' as admins can delete messages irrespective of - // time limit. - if (setting_value === settings_config.common_message_policy_values.by_admins_only.code) { + // should be enabled. The setting is disabled when every user + // who is allowed to delete their own messages is also allowed + // to delete any message in the organization. + const realm_delete_own_message_policy = Number.parseInt( + $("#id_realm_delete_own_message_policy").val(), + 10, + ); + const realm_can_delete_any_message_group_id = + settings_components.get_dropdown_list_widget_setting_value( + $("#id_realm_can_delete_any_message_group"), + ); + const realm_can_delete_any_message_group_name = user_groups.get_user_group_from_id( + realm_can_delete_any_message_group_id, + ).name; + const common_message_policy_values = settings_config.common_message_policy_values; + + if (realm_delete_own_message_policy === common_message_policy_values.by_admins_only.code) { + return false; + } + if (realm_can_delete_any_message_group_name === "role:administrators") { + return true; + } + if (realm_delete_own_message_policy === common_message_policy_values.by_moderators_only.code) { + return false; + } + if (realm_can_delete_any_message_group_name === "role:moderators") { + return true; + } + if (realm_delete_own_message_policy === common_message_policy_values.by_full_members.code) { + return false; + } + if (realm_can_delete_any_message_group_name === "role:fullmembers") { + return true; + } + if (realm_delete_own_message_policy === common_message_policy_values.by_members.code) { return false; } return true; } -function set_delete_own_message_policy_dropdown(setting_value) { - $("#id_realm_delete_own_message_policy").val(setting_value); +function check_disable_message_delete_limit_setting_dropdown() { settings_ui.disable_sub_setting_onchange( - message_delete_limit_setting_enabled(setting_value), + message_delete_limit_setting_enabled(), "id_realm_message_content_delete_limit_seconds", true, ); - const limit_setting_dropdown_value = settings_components.get_time_limit_dropdown_setting_value( - "realm_message_content_delete_limit_seconds", - ); - if (limit_setting_dropdown_value === "custom_period") { + if ($("#id_realm_message_content_delete_limit_minutes").length) { settings_ui.disable_sub_setting_onchange( - message_delete_limit_setting_enabled(setting_value), + message_delete_limit_setting_enabled(), "id_realm_message_content_delete_limit_minutes", true, ); } } +function set_delete_own_message_policy_dropdown(setting_value) { + $("#id_realm_delete_own_message_policy").val(setting_value); + check_disable_message_delete_limit_setting_dropdown(); +} + function set_msg_delete_limit_dropdown() { settings_components.set_time_limit_setting("realm_message_content_delete_limit_seconds"); } @@ -453,6 +485,9 @@ function update_dependent_subsettings(property_name) { case "realm_allow_message_editing": update_message_edit_sub_settings(realm.realm_allow_message_editing); break; + case "realm_can_delete_any_message_group": + check_disable_message_delete_limit_setting_dropdown(); + break; case "realm_delete_own_message_policy": set_delete_own_message_policy_dropdown(realm.realm_delete_own_message_policy); break; @@ -506,6 +541,7 @@ export function discard_realm_property_element_changes(elem) { case "realm_can_create_public_channel_group": case "realm_can_create_private_channel_group": case "realm_can_create_web_public_channel_group": + case "realm_can_delete_any_message_group": settings_components.set_dropdown_list_widget_setting_value( property_name, property_value, @@ -825,6 +861,8 @@ export function set_up_dropdown_widget_for_realm_group_settings() { if (setting_name === "direct_message_permission_group") { dropdown_list_item_click_callback = check_disable_direct_message_initiator_group_dropdown; + } else if (setting_name === "can_delete_any_message_group") { + dropdown_list_item_click_callback = check_disable_message_delete_limit_setting_dropdown; } set_up_dropdown_widget( "realm_" + setting_name, diff --git a/web/src/state_data.ts b/web/src/state_data.ts index 52d8e3f6d8..35e5a80e64 100644 --- a/web/src/state_data.ts +++ b/web/src/state_data.ts @@ -267,6 +267,7 @@ const realm_schema = z.object({ realm_can_create_public_channel_group: z.number(), realm_can_create_private_channel_group: z.number(), realm_can_create_web_public_channel_group: z.number(), + realm_can_delete_any_message_group: z.number(), realm_create_multiuse_invite_group: z.number(), realm_create_private_stream_policy: z.number(), realm_date_created: z.number(), diff --git a/web/templates/settings/organization_permissions_admin.hbs b/web/templates/settings/organization_permissions_admin.hbs index cbf7681331..a711531034 100644 --- a/web/templates/settings/organization_permissions_admin.hbs +++ b/web/templates/settings/organization_permissions_admin.hbs @@ -236,9 +236,11 @@ {{> settings_save_discard_widget section_name="msg-deletion" }}
- + {{> ../dropdown_widget_with_label + widget_name="realm_can_delete_any_message_group" + label=(t 'Who can delete any message') + value_type="number" }} +