From 4e2931cefdfe58a0ae0e202e3f2cc5547a1a57e6 Mon Sep 17 00:00:00 2001 From: N-Shar-ma Date: Tue, 3 Jan 2023 12:59:15 +0530 Subject: [PATCH] compose: Disable "Message X" button for DMs when DMs are not allowed. When in a private narrow, the "Message X" button is disabled if direct messages are not allowed in the organisation and the current recipient is not a bot. Note that when the recipient is a user group with 1, more or all bots, the button is disabled then too as such PMs are not allowed. Only when the recipient is a single bot, then it's not disabled, as DMs with one bot are allowed even in organisations where DMs are disabled. --- web/src/compose_closed_ui.js | 27 +++++++++++++++++++++++++-- web/src/people.js | 20 ++++++++++++++++++++ web/tests/compose.test.js | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/web/src/compose_closed_ui.js b/web/src/compose_closed_ui.js index 216c3cb423..82f09964b2 100644 --- a/web/src/compose_closed_ui.js +++ b/web/src/compose_closed_ui.js @@ -53,6 +53,15 @@ export function get_recipient_label(message) { return ""; } +function update_reply_button_state(disable = false, title) { + $(".compose_reply_button").attr("disabled", disable); + if (!title) { + const title_text = $t({defaultMessage: "Reply to selected message"}); + title = title_text + " (r)"; + } + $(".compose_reply_button").prop("title", title); +} + function update_stream_button(btn_text, title) { $("#left_bar_compose_stream_button_big").text(btn_text); $("#left_bar_compose_stream_button_big").prop("title", title); @@ -63,17 +72,31 @@ function update_conversation_button(btn_text, title) { $("#left_bar_compose_private_button_big").prop("title", title); } -function update_buttons(text_stream) { +function update_buttons(text_stream, disable_reply, title_reply) { const title_stream = text_stream + " (c)"; const text_conversation = $t({defaultMessage: "New direct message"}); const title_conversation = text_conversation + " (x)"; update_stream_button(text_stream, title_stream); update_conversation_button(text_conversation, title_conversation); + update_reply_button_state(disable_reply, title_reply); } export function update_buttons_for_private() { const text_stream = $t({defaultMessage: "New stream message"}); - update_buttons(text_stream); + if ( + !narrow_state.pm_ids_string() || + people.user_can_direct_message(narrow_state.pm_ids_string()) + ) { + update_buttons(text_stream); + return; + } + // disable the [Message X] button when in a private narrow + // if the user cannot dm the current recipient + const disable_reply = true; + const title_reply = $t({ + defaultMessage: "You are not allowed to send private messages in this organization.", + }); + update_buttons(text_stream, disable_reply, title_reply); } export function update_buttons_for_stream() { diff --git a/web/src/people.js b/web/src/people.js index d275cec25b..d3344862ff 100644 --- a/web/src/people.js +++ b/web/src/people.js @@ -702,6 +702,26 @@ export function user_is_bot(user_id) { return user.is_bot; } +export function user_can_direct_message(recipient_ids_string) { + // Common function for checking if a user can send a direct + // message to the target user (or group of users) represented by a + // user ids string. + + // Regardless of policy, we allow sending private messages to bots. + const recipient_ids = user_ids_string_to_ids_array(recipient_ids_string); + if (recipient_ids.length === 1 && user_is_bot(recipient_ids[0])) { + return true; + } + + if ( + page_params.realm_private_message_policy === + settings_config.private_message_policy_values.disabled.code + ) { + return false; + } + return true; +} + function gravatar_url_for_email(email) { const hash = md5(email.toLowerCase()); const avatar_url = "https://secure.gravatar.com/avatar/" + hash + "?d=identicon"; diff --git a/web/tests/compose.test.js b/web/tests/compose.test.js index cdf393c41c..5941496a43 100644 --- a/web/tests/compose.test.js +++ b/web/tests/compose.test.js @@ -12,6 +12,8 @@ const blueslip = require("./lib/zblueslip"); const $ = require("./lib/zjquery"); const {page_params, user_settings} = require("./lib/zpage_params"); +const settings_config = zrequire("settings_config"); + const noop = () => {}; set_global("document", { @@ -37,6 +39,7 @@ const compose_fade = mock_esm("../src/compose_fade"); const compose_pm_pill = mock_esm("../src/compose_pm_pill"); const loading = mock_esm("../src/loading"); const markdown = mock_esm("../src/markdown"); +const narrow_state = mock_esm("../src/narrow_state"); const reminder = mock_esm("../src/reminder"); const rendered_markdown = mock_esm("../src/rendered_markdown"); const resize = mock_esm("../src/resize"); @@ -77,6 +80,7 @@ const alice = { email: "alice@example.com", user_id: 31, full_name: "Alice", + is_bot: false, }; const bob = { @@ -85,12 +89,20 @@ const bob = { full_name: "Bob", }; +const bot = { + email: "bot@example.com", + user_id: 33, + full_name: "Bot", + is_bot: true, +}; + people.add_active_user(new_user); people.add_active_user(me); people.initialize_current_user(me.user_id); people.add_active_user(alice); people.add_active_user(bob); +people.add_active_user(bot); const social = { stream_id: 101, @@ -767,7 +779,29 @@ test_ui("create_message_object", ({override, override_rewire}) => { people.email_list_to_user_ids_string = email_list_to_user_ids_string; }); -test_ui("narrow_button_titles", () => { +test_ui("DM policy disabled", ({override, override_rewire}) => { + // Disable dms in the organisation + override( + page_params, + "realm_private_message_policy", + settings_config.private_message_policy_values.disabled.code, + ); + let reply_disabled = false; + override_rewire(compose_closed_ui, "update_reply_button_state", (disabled = false) => { + reply_disabled = disabled; + }); + // For single bot recipient, Bot, the "Message X" button is not disabled + override(narrow_state, "pm_ids_string", () => "33"); + compose_closed_ui.update_buttons_for_private(); + assert.ok(!reply_disabled); + // For human user, Alice, the "Message X" button is disabled + override(narrow_state, "pm_ids_string", () => "31"); + compose_closed_ui.update_buttons_for_private(); + assert.ok(reply_disabled); +}); + +test_ui("narrow_button_titles", ({override}) => { + override(narrow_state, "pm_ids_string", () => "31"); compose_closed_ui.update_buttons_for_private(); assert.equal( $("#left_bar_compose_stream_button_big").text(),