mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
realm: Add setting to notify user on DMing guest.
Added `enable_guest_user_dm_warning` setting to decide whether clients should show a warning when a user is composing to a guest user in the organization. Fixes #30078. Co-authored-by: adnan-td <generaladnan139@gmail.com>
This commit is contained in:
@@ -20,6 +20,13 @@ format used by the Zulip server that they are interacting with.
|
||||
|
||||
## Changes in Zulip 10.0
|
||||
|
||||
**Feature level 348**
|
||||
|
||||
* [`POST /register`](/api/register-queue), [`POST /events`](/api/get-events),
|
||||
`PATCH /realm`: Added `enable_guest_user_dm_warning` setting to decide
|
||||
whether clients should show a warning when a user is composing to a
|
||||
guest user in the organization.
|
||||
|
||||
**Feature level 347**
|
||||
|
||||
* [Markdown message formatting](/api/message-formatting#links-to-channels-topics-and-messages):
|
||||
|
@@ -42,6 +42,20 @@ pricing](/help/zulip-cloud-billing#temporary-users-and-guests) for guest users.
|
||||
|
||||
{end_tabs}
|
||||
|
||||
## Configure warning for direct messages to guest users
|
||||
|
||||
{start_tabs}
|
||||
|
||||
{tab|desktop-web}
|
||||
|
||||
{settings_tab|organization-permissions}
|
||||
|
||||
1. Under **Guests**, toggle **Display a warning when composing a direct message with guest user recipients**.
|
||||
|
||||
{!save-changes.md!}
|
||||
|
||||
{end_tabs}
|
||||
|
||||
## Configure whether guests can see all other users
|
||||
|
||||
{!cloud-plus-only.md!}
|
||||
|
@@ -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 = 347 # Last bumped for /with/ in topic links.
|
||||
API_FEATURE_LEVEL = 348 # Last bumped for enable_guest_user_dm_warning.
|
||||
|
||||
# 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
|
||||
|
@@ -73,6 +73,10 @@ const admin_settings_label = {
|
||||
realm_enable_guest_user_indicator: $t({
|
||||
defaultMessage: "Display “(guest)” after names of guest users",
|
||||
}),
|
||||
realm_enable_guest_user_dm_warning: $t({
|
||||
defaultMessage:
|
||||
"Display a warning when composing a direct message with guest user recipients",
|
||||
}),
|
||||
};
|
||||
|
||||
function insert_tip_box(): void {
|
||||
@@ -246,6 +250,7 @@ export function build_page(): void {
|
||||
automatically_unmute_topics_in_muted_streams_policy_values:
|
||||
settings_config.automatically_follow_or_unmute_topics_policy_values,
|
||||
realm_enable_guest_user_indicator: realm.realm_enable_guest_user_indicator,
|
||||
realm_enable_guest_user_dm_warning: realm.realm_enable_guest_user_dm_warning,
|
||||
active_user_list_dropdown_widget_name: settings_users.active_user_list_dropdown_widget_name,
|
||||
deactivated_user_list_dropdown_widget_name:
|
||||
settings_users.deactivated_user_list_dropdown_widget_name,
|
||||
|
@@ -127,6 +127,7 @@ function clear_box(): void {
|
||||
// TODO: Better encapsulate at-mention warnings.
|
||||
compose_validate.clear_topic_resolved_warning();
|
||||
compose_validate.clear_stream_wildcard_warnings($("#compose_banners"));
|
||||
compose_validate.clear_guest_in_dm_recipient_warning();
|
||||
compose_validate.set_user_acknowledged_stream_wildcard_flag(false);
|
||||
|
||||
compose_state.set_recipient_edited_manually(false);
|
||||
@@ -408,6 +409,8 @@ export let start = (raw_opts: ComposeActionsStartOpts): void => {
|
||||
|
||||
// Show a warning if topic is resolved
|
||||
compose_validate.warn_if_topic_resolved(true);
|
||||
// Show a warning if dm recipient contains guest
|
||||
compose_validate.warn_if_guest_in_dm_recipient();
|
||||
// Show a warning if the user is in a search narrow when replying to a message
|
||||
if (opts.is_reply) {
|
||||
compose_validate.warn_if_in_search_view();
|
||||
|
@@ -43,6 +43,7 @@ export const CLASSNAMES = {
|
||||
recipient_not_subscribed: "recipient_not_subscribed",
|
||||
wildcard_warning: "wildcard_warning",
|
||||
private_stream_warning: "private_stream_warning",
|
||||
guest_in_dm_recipient_warning: "guest_in_dm_recipient_warning",
|
||||
unscheduled_message: "unscheduled_message",
|
||||
search_view: "search_view",
|
||||
// errors
|
||||
|
@@ -114,6 +114,7 @@ function update_fade(): void {
|
||||
export function update_on_recipient_change(): void {
|
||||
update_fade();
|
||||
update_narrow_to_recipient_visibility();
|
||||
compose_validate.warn_if_guest_in_dm_recipient();
|
||||
drafts.update_compose_draft_count();
|
||||
check_posting_policy_for_compose_box();
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ let last_focused_compose_type_input: HTMLTextAreaElement | undefined;
|
||||
// the narrow and the user should still be able to see the banner once after
|
||||
// performing these actions
|
||||
let recipient_viewed_topic_resolved_banner = false;
|
||||
let recipient_guest_ids_for_dm_warning: number[] = [];
|
||||
|
||||
export function set_recipient_edited_manually(flag: boolean): void {
|
||||
recipient_edited_manually = flag;
|
||||
@@ -58,6 +59,14 @@ export function has_recipient_viewed_topic_resolved_banner(): boolean {
|
||||
return recipient_viewed_topic_resolved_banner;
|
||||
}
|
||||
|
||||
export function set_recipient_guest_ids_for_dm_warning(guest_ids: number[]): void {
|
||||
recipient_guest_ids_for_dm_warning = guest_ids;
|
||||
}
|
||||
|
||||
export function get_recipient_guest_ids_for_dm_warning(): number[] {
|
||||
return recipient_guest_ids_for_dm_warning;
|
||||
}
|
||||
|
||||
export function composing(): boolean {
|
||||
// This is very similar to get_message_type(), but it returns
|
||||
// a boolean.
|
||||
|
@@ -1,7 +1,9 @@
|
||||
import $ from "jquery";
|
||||
import _ from "lodash";
|
||||
|
||||
import * as resolved_topic from "../shared/src/resolved_topic.ts";
|
||||
import render_compose_banner from "../templates/compose_banner/compose_banner.hbs";
|
||||
import render_guest_in_dm_recipient_warning from "../templates/compose_banner/guest_in_dm_recipient_warning.hbs";
|
||||
import render_not_subscribed_warning from "../templates/compose_banner/not_subscribed_warning.hbs";
|
||||
import render_private_stream_warning from "../templates/compose_banner/private_stream_warning.hbs";
|
||||
import render_stream_wildcard_warning from "../templates/compose_banner/stream_wildcard_warning.hbs";
|
||||
@@ -389,6 +391,72 @@ export function warn_if_in_search_view(): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function clear_guest_in_dm_recipient_warning(): void {
|
||||
// We don't call set_recipient_guest_ids_for_dm_warning here, so
|
||||
// that reopening the same draft won't make the banner reappear.
|
||||
const classname = compose_banner.CLASSNAMES.guest_in_dm_recipient_warning;
|
||||
$(`#compose_banners .${CSS.escape(classname)}`).remove();
|
||||
}
|
||||
|
||||
// Only called on recipient change. Adds new banner if not already
|
||||
// exists or updates the existing banner or removes banner if no
|
||||
// guest in the dm.
|
||||
export function warn_if_guest_in_dm_recipient(): void {
|
||||
if (!compose_state.composing()) {
|
||||
return;
|
||||
}
|
||||
const recipient_ids = compose_pm_pill.get_user_ids();
|
||||
const guest_ids = people.filter_other_guest_ids(recipient_ids);
|
||||
|
||||
if (
|
||||
!realm.realm_enable_guest_user_dm_warning ||
|
||||
compose_state.get_message_type() !== "private" ||
|
||||
guest_ids.length === 0
|
||||
) {
|
||||
clear_guest_in_dm_recipient_warning();
|
||||
compose_state.set_recipient_guest_ids_for_dm_warning([]);
|
||||
return;
|
||||
}
|
||||
// If warning was shown earlier for same guests in the recipients, do nothing.
|
||||
if (_.isEqual(compose_state.get_recipient_guest_ids_for_dm_warning(), guest_ids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const guest_names = people.user_ids_to_full_names_array(guest_ids);
|
||||
let banner_text: string;
|
||||
|
||||
if (guest_names.length === 1) {
|
||||
banner_text = $t(
|
||||
{defaultMessage: "{name} is a guest in this organization."},
|
||||
{name: guest_names[0]},
|
||||
);
|
||||
} else {
|
||||
const names_string = util.format_array_as_list(guest_names, "long", "conjunction");
|
||||
banner_text = $t(
|
||||
{defaultMessage: "{names} are guests in this organization."},
|
||||
{names: names_string},
|
||||
);
|
||||
}
|
||||
|
||||
const classname = compose_banner.CLASSNAMES.guest_in_dm_recipient_warning;
|
||||
let $banner = $(`#compose_banners .${CSS.escape(classname)}`);
|
||||
|
||||
compose_state.set_recipient_guest_ids_for_dm_warning(guest_ids);
|
||||
// Update banner text if banner already exists.
|
||||
if ($banner.length === 1) {
|
||||
$banner.find(".banner_content").text(banner_text);
|
||||
return;
|
||||
}
|
||||
|
||||
$banner = $(
|
||||
render_guest_in_dm_recipient_warning({
|
||||
banner_text,
|
||||
classname: compose_banner.CLASSNAMES.guest_in_dm_recipient_warning,
|
||||
}),
|
||||
);
|
||||
compose_banner.append_compose_banner_to_banner_list($banner, $("#compose_banners"));
|
||||
}
|
||||
|
||||
function show_stream_wildcard_warnings(opts: StreamWildcardOptions): void {
|
||||
const subscriber_count = peer_data.get_subscriber_count(opts.stream_id) || 0;
|
||||
const stream_name = sub_store.maybe_get_stream_name(opts.stream_id);
|
||||
|
@@ -687,6 +687,17 @@ export function pm_with_operand_ids(operand: string): number[] | undefined {
|
||||
return user_ids;
|
||||
}
|
||||
|
||||
export function filter_other_guest_ids(user_ids: number[]): number[] {
|
||||
return sort_numerically(
|
||||
user_ids.filter((id) => id !== current_user.user_id && get_by_user_id(id)?.is_guest),
|
||||
);
|
||||
}
|
||||
|
||||
export function user_ids_to_full_names_array(user_ids: number[]): string[] {
|
||||
const names = user_ids.map((user_id) => get_by_user_id(user_id).full_name).sort(util.strcmp);
|
||||
return names;
|
||||
}
|
||||
|
||||
export function emails_to_slug(emails_string: string): string | undefined {
|
||||
let slug = reply_to_to_user_ids_string(emails_string);
|
||||
|
||||
|
@@ -16,6 +16,7 @@ import * as compose_closed_ui from "./compose_closed_ui.ts";
|
||||
import * as compose_pm_pill from "./compose_pm_pill.ts";
|
||||
import * as compose_recipient from "./compose_recipient.ts";
|
||||
import * as compose_state from "./compose_state.ts";
|
||||
import * as compose_validate from "./compose_validate.ts";
|
||||
import {electron_bridge} from "./electron_bridge.ts";
|
||||
import * as emoji from "./emoji.ts";
|
||||
import * as emoji_picker from "./emoji_picker.ts";
|
||||
@@ -262,6 +263,7 @@ export function dispatch_normal_event(event) {
|
||||
want_advertise_in_communities_directory: noop,
|
||||
wildcard_mention_policy: noop,
|
||||
enable_read_receipts: settings_account.update_send_read_receipts_tooltip,
|
||||
enable_guest_user_dm_warning: compose_validate.warn_if_guest_in_dm_recipient,
|
||||
enable_guest_user_indicator: noop,
|
||||
};
|
||||
switch (event.op) {
|
||||
|
@@ -337,6 +337,7 @@ export const realm_schema = z.object({
|
||||
}),
|
||||
),
|
||||
realm_empty_topic_display_name: z.string(),
|
||||
realm_enable_guest_user_dm_warning: z.boolean(),
|
||||
realm_enable_guest_user_indicator: z.boolean(),
|
||||
realm_enable_read_receipts: z.boolean(),
|
||||
realm_enable_spectator_access: z.boolean(),
|
||||
|
@@ -0,0 +1,6 @@
|
||||
<div class="above_compose_banner main-view-banner warning-style {{classname}}">
|
||||
<p class="banner_content">
|
||||
{{banner_text}}
|
||||
</p>
|
||||
<a role="button" class="zulip-icon zulip-icon-close main-view-banner-close-button"></a>
|
||||
</div>
|
@@ -321,6 +321,12 @@
|
||||
is_checked=realm_enable_guest_user_indicator
|
||||
label=admin_settings_label.realm_enable_guest_user_indicator}}
|
||||
|
||||
{{> settings_checkbox
|
||||
setting_name="realm_enable_guest_user_dm_warning"
|
||||
prefix="id_"
|
||||
is_checked=realm_enable_guest_user_dm_warning
|
||||
label=admin_settings_label.realm_enable_guest_user_dm_warning}}
|
||||
|
||||
{{> ../dropdown_widget_with_label
|
||||
widget_name="realm_can_access_all_users_group"
|
||||
label=group_setting_labels.can_access_all_users_group
|
||||
|
@@ -630,6 +630,7 @@ test_ui("update_fade", ({override, override_rewire}) => {
|
||||
update_narrow_to_recipient_visibility_called = true;
|
||||
});
|
||||
override_rewire(drafts, "update_compose_draft_count", noop);
|
||||
override(compose_pm_pill, "get_user_ids", () => []);
|
||||
|
||||
compose_state.set_message_type(undefined);
|
||||
compose_recipient.update_on_recipient_change();
|
||||
|
@@ -42,6 +42,7 @@ const compose_fade = mock_esm("../src/compose_fade", {
|
||||
});
|
||||
const compose_pm_pill = mock_esm("../src/compose_pm_pill", {
|
||||
get_user_ids_string: () => "",
|
||||
get_user_ids: () => [],
|
||||
});
|
||||
const compose_ui = mock_esm("../src/compose_ui", {
|
||||
autosize_textarea: noop,
|
||||
|
@@ -22,6 +22,11 @@ const {set_current_user, set_realm} = zrequire("state_data");
|
||||
const stream_data = zrequire("stream_data");
|
||||
const compose_recipient = zrequire("/compose_recipient");
|
||||
const user_groups = zrequire("user_groups");
|
||||
const {initialize_user_settings} = zrequire("user_settings");
|
||||
|
||||
mock_esm("../src/ui_util", {
|
||||
place_caret_at_end: noop,
|
||||
});
|
||||
|
||||
mock_esm("../src/group_permission_settings", {
|
||||
get_group_permission_setting_config: () => ({
|
||||
@@ -33,6 +38,8 @@ const realm = {};
|
||||
set_realm(realm);
|
||||
const current_user = {};
|
||||
set_current_user(current_user);
|
||||
const user_settings = {defualt_language: "en"};
|
||||
initialize_user_settings({user_settings});
|
||||
|
||||
const me = {
|
||||
email: "me@example.com",
|
||||
@@ -54,6 +61,13 @@ const bob = {
|
||||
is_admin: true,
|
||||
};
|
||||
|
||||
const guest = {
|
||||
email: "guest@example.com",
|
||||
user_id: 33,
|
||||
full_name: "Guest",
|
||||
is_guest: true,
|
||||
};
|
||||
|
||||
const social_sub = {
|
||||
stream_id: 101,
|
||||
name: "social",
|
||||
@@ -66,6 +80,7 @@ people.initialize_current_user(me.user_id);
|
||||
|
||||
people.add_active_user(alice);
|
||||
people.add_active_user(bob);
|
||||
people.add_active_user(guest);
|
||||
|
||||
const welcome_bot = {
|
||||
email: "welcome-bot@example.com",
|
||||
@@ -116,6 +131,30 @@ function stub_message_row($textarea) {
|
||||
};
|
||||
}
|
||||
|
||||
function initialize_pm_pill(mock_template) {
|
||||
$.clear_all_elements();
|
||||
|
||||
$("#compose-send-button").prop("disabled", false);
|
||||
$("#compose-send-button").trigger("focus");
|
||||
$("#compose-send-button .loader").hide();
|
||||
|
||||
const $pm_pill_container = $.create("fake-pm-pill-container");
|
||||
$("#private_message_recipient")[0] = {};
|
||||
$("#private_message_recipient").set_parent($pm_pill_container);
|
||||
$pm_pill_container.set_find_results(".input", $("#private_message_recipient"));
|
||||
$("#private_message_recipient").before = noop;
|
||||
|
||||
compose_pm_pill.initialize({
|
||||
on_pill_create_or_remove: compose_recipient.update_placeholder_text,
|
||||
});
|
||||
|
||||
$("#zephyr-mirror-error").is = noop;
|
||||
|
||||
mock_template("input_pill.hbs", false, () => "<div>pill-html</div>");
|
||||
|
||||
mock_banners();
|
||||
}
|
||||
|
||||
test_ui("validate_stream_message_address_info", ({mock_template}) => {
|
||||
// For this test we basically only use FakeComposeBox
|
||||
// to set up the DOM environment. We don't assert about
|
||||
@@ -153,30 +192,6 @@ test_ui("validate_stream_message_address_info", ({mock_template}) => {
|
||||
});
|
||||
|
||||
test_ui("validate", ({mock_template, override}) => {
|
||||
function initialize_pm_pill() {
|
||||
$.clear_all_elements();
|
||||
|
||||
$("#compose-send-button").prop("disabled", false);
|
||||
$("#compose-send-button").trigger("focus");
|
||||
$("#compose-send-button .loader").hide();
|
||||
|
||||
const $pm_pill_container = $.create("fake-pm-pill-container");
|
||||
$("#private_message_recipient")[0] = {};
|
||||
$("#private_message_recipient").set_parent($pm_pill_container);
|
||||
$pm_pill_container.set_find_results(".input", $("#private_message_recipient"));
|
||||
$("#private_message_recipient").before = noop;
|
||||
|
||||
compose_pm_pill.initialize({
|
||||
on_pill_create_or_remove: compose_recipient.update_placeholder_text,
|
||||
});
|
||||
|
||||
$("#zephyr-mirror-error").is = noop;
|
||||
|
||||
mock_template("input_pill.hbs", false, () => "<div>pill-html</div>");
|
||||
|
||||
mock_banners();
|
||||
}
|
||||
|
||||
function add_content_to_compose_box() {
|
||||
$("textarea#compose-textarea").val("foobarfoobar");
|
||||
}
|
||||
@@ -184,7 +199,7 @@ test_ui("validate", ({mock_template, override}) => {
|
||||
// test validating direct messages
|
||||
compose_state.set_message_type("private");
|
||||
|
||||
initialize_pm_pill();
|
||||
initialize_pm_pill(mock_template);
|
||||
add_content_to_compose_box();
|
||||
compose_state.private_message_recipient("");
|
||||
let pm_recipient_error_rendered = false;
|
||||
@@ -238,7 +253,7 @@ test_ui("validate", ({mock_template, override}) => {
|
||||
assert.ok(compose_validate.validate());
|
||||
override(realm, "realm_is_zephyr_mirror_realm", false);
|
||||
|
||||
initialize_pm_pill();
|
||||
initialize_pm_pill(mock_template);
|
||||
add_content_to_compose_box();
|
||||
compose_state.private_message_recipient("welcome-bot@example.com");
|
||||
$("#send_message_form").set_find_results(".message-textarea", $("textarea#compose-textarea"));
|
||||
@@ -258,7 +273,7 @@ test_ui("validate", ({mock_template, override}) => {
|
||||
}
|
||||
return "<banner-stub>";
|
||||
});
|
||||
initialize_pm_pill();
|
||||
initialize_pm_pill(mock_template);
|
||||
compose_state.private_message_recipient("welcome-bot@example.com");
|
||||
$("textarea#compose-textarea").toggleClass = (classname, value) => {
|
||||
assert.equal(classname, "invalid");
|
||||
@@ -281,7 +296,7 @@ test_ui("validate", ({mock_template, override}) => {
|
||||
assert.ok(zephyr_checked);
|
||||
assert.ok(zephyr_error_rendered);
|
||||
|
||||
initialize_pm_pill();
|
||||
initialize_pm_pill(mock_template);
|
||||
add_content_to_compose_box();
|
||||
|
||||
// test validating stream messages
|
||||
@@ -842,3 +857,68 @@ test_ui("test warn_if_topic_resolved", ({override, mock_template}) => {
|
||||
compose_validate.warn_if_topic_resolved(false);
|
||||
assert.ok(!error_shown);
|
||||
});
|
||||
|
||||
test_ui("test_warn_if_guest_in_dm_recipient", ({mock_template}) => {
|
||||
let is_active = false;
|
||||
|
||||
mock_template("compose_banner/guest_in_dm_recipient_warning.hbs", false, (data) => {
|
||||
assert.equal(data.classname, compose_banner.CLASSNAMES.guest_in_dm_recipient_warning);
|
||||
assert.equal(
|
||||
data.banner_text,
|
||||
$t({defaultMessage: "Guest is a guest in this organization."}),
|
||||
);
|
||||
is_active = true;
|
||||
return "<banner-stub>";
|
||||
});
|
||||
|
||||
compose_state.set_message_type("private");
|
||||
initialize_pm_pill(mock_template);
|
||||
compose_state.private_message_recipient("guest@example.com");
|
||||
const classname = compose_banner.CLASSNAMES.guest_in_dm_recipient_warning;
|
||||
let $banner = $(`#compose_banners .${CSS.escape(classname)}`);
|
||||
|
||||
// if setting is disabled, remove warning if exists
|
||||
realm.realm_enable_guest_user_dm_warning = false;
|
||||
compose_validate.warn_if_guest_in_dm_recipient();
|
||||
assert.ok(!is_active);
|
||||
|
||||
// to show warning for guest emails, banner should be created
|
||||
realm.realm_enable_guest_user_dm_warning = true;
|
||||
$banner.length = 0;
|
||||
compose_validate.warn_if_guest_in_dm_recipient();
|
||||
assert.ok(is_active);
|
||||
assert.deepEqual(compose_state.get_recipient_guest_ids_for_dm_warning(), [33]);
|
||||
|
||||
// don't show warning for same guests if user closed the banner.
|
||||
is_active = false;
|
||||
compose_validate.warn_if_guest_in_dm_recipient();
|
||||
assert.ok(!is_active);
|
||||
|
||||
// on modifying the guest recipient, update banner if already shown.
|
||||
is_active = true;
|
||||
const new_guest = {
|
||||
email: "new_guest@example.com",
|
||||
user_id: 34,
|
||||
full_name: "New Guest",
|
||||
is_guest: true,
|
||||
};
|
||||
people.add_active_user(new_guest);
|
||||
|
||||
initialize_pm_pill(mock_template);
|
||||
compose_state.private_message_recipient("guest@example.com, new_guest@example.com");
|
||||
$banner = $(`#compose_banners .${CSS.escape(classname)}`);
|
||||
$banner.length = 1;
|
||||
let is_updated = false;
|
||||
$banner.set_find_results(".banner_content", {
|
||||
text(content) {
|
||||
assert.equal(
|
||||
content,
|
||||
$t({defaultMessage: "Guest and New Guest are guests in this organization."}),
|
||||
);
|
||||
is_updated = true;
|
||||
},
|
||||
});
|
||||
compose_validate.warn_if_guest_in_dm_recipient();
|
||||
assert.ok(is_updated);
|
||||
assert.deepEqual(compose_state.get_recipient_guest_ids_for_dm_warning(), [33, 34]);
|
||||
});
|
||||
|
@@ -835,6 +835,45 @@ test_people("dm_matches_search_string", () => {
|
||||
assert.ok(!result);
|
||||
});
|
||||
|
||||
test_people("filter_other_guest_ids", ({override}) => {
|
||||
people.add_active_user(emp401);
|
||||
people.add_active_user(emp402);
|
||||
people.add_active_user(guest);
|
||||
|
||||
assert.equal(emp401.user_id, 401);
|
||||
assert.equal(emp402.user_id, 402);
|
||||
assert.equal(guest.user_id, 33);
|
||||
|
||||
let ids = [401, 402];
|
||||
let guest_ids = people.filter_other_guest_ids(ids);
|
||||
assert.equal(guest_ids.length, 0);
|
||||
|
||||
ids = [401, 402, 33];
|
||||
guest_ids = people.filter_other_guest_ids(ids);
|
||||
assert.equal(guest_ids.length, 1);
|
||||
assert.equal(guest_ids[0], 33);
|
||||
|
||||
override(current_user, "is_guest", true);
|
||||
override(current_user, "user_id", 1);
|
||||
// User ID of the current user will not be included in result.
|
||||
guest_ids = people.filter_other_guest_ids([1]);
|
||||
assert.equal(guest_ids.length, 0);
|
||||
});
|
||||
|
||||
test_people("user_ids_to_full_names_array", () => {
|
||||
people.add_active_user(emp401);
|
||||
people.add_active_user(emp402);
|
||||
|
||||
assert.equal(emp401.user_id, 401);
|
||||
assert.equal(emp402.user_id, 402);
|
||||
|
||||
const ids = [401, 402];
|
||||
const names = people.user_ids_to_full_names_array(ids);
|
||||
assert.equal(names.length, 2);
|
||||
assert.equal(names[0], emp401.full_name);
|
||||
assert.equal(names[1], emp402.full_name);
|
||||
});
|
||||
|
||||
test_people("multi_user_methods", () => {
|
||||
people.add_active_user(emp401);
|
||||
people.add_active_user(emp402);
|
||||
|
17
zerver/migrations/0663_realm_enable_guest_user_dm_warning.py
Normal file
17
zerver/migrations/0663_realm_enable_guest_user_dm_warning.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 5.0.10 on 2025-02-06 13:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("zerver", "0662_clear_realm_channel_fields_if_configured_channel_deactivated"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="realm",
|
||||
name="enable_guest_user_dm_warning",
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
@@ -627,6 +627,9 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
|
||||
# Whether clients should display "(guest)" after names of guest users.
|
||||
enable_guest_user_indicator = models.BooleanField(default=True)
|
||||
|
||||
# Whether to notify client when a DM has a guest recipient.
|
||||
enable_guest_user_dm_warning = models.BooleanField(default=True)
|
||||
|
||||
# Define the types of the various automatically managed properties
|
||||
property_types: dict[str, type | UnionType] = dict(
|
||||
allow_edit_history=bool,
|
||||
@@ -640,6 +643,7 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
|
||||
disallow_disposable_email_addresses=bool,
|
||||
email_changes_disabled=bool,
|
||||
emails_restricted_to_domains=bool,
|
||||
enable_guest_user_dm_warning=bool,
|
||||
enable_guest_user_indicator=bool,
|
||||
enable_read_receipts=bool,
|
||||
enable_spectator_access=bool,
|
||||
|
@@ -4748,6 +4748,13 @@ paths:
|
||||
Whether [new users joining](/help/restrict-account-creation#configuring-email-domain-restrictions)
|
||||
this organization are required to have an email
|
||||
address in one of the `realm_domains` configured for the organization.
|
||||
enable_guest_user_dm_warning:
|
||||
type: boolean
|
||||
description: |
|
||||
Whether clients should show a warning when a user is composing
|
||||
a DM to a guest user in this organization.
|
||||
|
||||
**Changes**: New in Zulip 10.0 (feature level 348).
|
||||
enable_guest_user_indicator:
|
||||
type: boolean
|
||||
description: |
|
||||
@@ -17609,6 +17616,15 @@ paths:
|
||||
- 2 = Zulip Cloud free plan (LIMITED)
|
||||
- 3 = Zulip Cloud Standard plan (STANDARD)
|
||||
- 4 = Zulip Cloud Standard plan, sponsored for free (STANDARD_FREE)
|
||||
realm_enable_guest_user_dm_warning:
|
||||
type: boolean
|
||||
description: |
|
||||
Present if `realm` is present in `fetch_event_types`.
|
||||
|
||||
Whether clients should show a warning when a user is composing
|
||||
a DM to a guest user in this organization.
|
||||
|
||||
**Changes**: New in Zulip 10.0 (feature level 348).
|
||||
realm_enable_guest_user_indicator:
|
||||
type: boolean
|
||||
description: |
|
||||
|
@@ -165,6 +165,7 @@ class HomeTest(ZulipTestCase):
|
||||
"realm_embedded_bots",
|
||||
"realm_emoji",
|
||||
"realm_empty_topic_display_name",
|
||||
"realm_enable_guest_user_dm_warning",
|
||||
"realm_enable_guest_user_indicator",
|
||||
"realm_enable_read_receipts",
|
||||
"realm_enable_spectator_access",
|
||||
|
@@ -163,6 +163,7 @@ def update_realm(
|
||||
Json[int | str] | None,
|
||||
ApiParamConfig("move_messages_between_streams_limit_seconds"),
|
||||
] = None,
|
||||
enable_guest_user_dm_warning: Json[bool] | None = None,
|
||||
enable_guest_user_indicator: Json[bool] | None = None,
|
||||
can_access_all_users_group: Json[GroupSettingChangeRequest] | None = None,
|
||||
) -> HttpResponse:
|
||||
|
Reference in New Issue
Block a user