settings: Use can_add_subscribers_group instead of realm policy.

We are using `can_add_subscribers_group` instead of
`invite_to_stream_policy` to check whether a user can subscribe other
users.
We've removed `invite_to_stream_policy` from the frontend wherever
applicable.
This commit is contained in:
Shubham Padia
2025-01-13 20:03:37 +00:00
committed by Tim Abbott
parent 34ade0d9a2
commit 3bf87228a2
14 changed files with 70 additions and 211 deletions

View File

@@ -223,7 +223,6 @@ export function dispatch_normal_event(event) {
can_move_messages_between_channels_group: noop,
can_move_messages_between_topics_group: noop,
create_multiuse_invite_group: noop,
invite_to_stream_policy: noop,
default_code_block_language: noop,
default_language: noop,
description: noop,

View File

@@ -242,7 +242,6 @@ export function get_subsection_property_elements($subsection: JQuery): HTMLEleme
}
export const simple_dropdown_realm_settings_schema = realm_schema.pick({
realm_invite_to_stream_policy: true,
realm_wildcard_mention_policy: true,
realm_org_type: true,
});

View File

@@ -8,12 +8,6 @@ import type {GroupSettingValue} from "./state_data.ts";
import * as user_groups from "./user_groups.ts";
import {user_settings} from "./user_settings.ts";
let user_join_date: Date;
export function initialize(current_user_join_date: Date): void {
// We keep the `user_join_date` as the present day's date if the user is a spectator
user_join_date = current_user_join_date;
}
/*
This is a close cousin of settings_config,
but this has a bit more logic, and we
@@ -58,38 +52,6 @@ export function user_can_change_logo(): boolean {
return current_user.is_admin && realm.zulip_plan_is_not_limited;
}
function user_has_permission(policy_value: number): boolean {
if (current_user.is_admin) {
return true;
}
if (page_params.is_spectator || current_user.is_guest) {
return false;
}
if (policy_value === settings_config.common_policy_values.by_admins_only.code) {
return false;
}
if (current_user.is_moderator) {
return true;
}
if (policy_value === settings_config.common_policy_values.by_moderators_only.code) {
return false;
}
if (policy_value === settings_config.common_policy_values.by_members.code) {
return true;
}
const current_datetime = new Date();
const person_date_joined = new Date(user_join_date);
const user_join_days =
(current_datetime.getTime() - person_date_joined.getTime()) / 1000 / 86400;
return user_join_days >= realm.realm_waiting_period_threshold;
}
export function user_has_permission_for_group_setting(
setting_value: GroupSettingValue,
setting_name: string,
@@ -129,7 +91,11 @@ export function user_can_create_multiuse_invite(): boolean {
}
export function user_can_subscribe_other_users(): boolean {
return user_has_permission(realm.realm_invite_to_stream_policy);
return user_has_permission_for_group_setting(
realm.realm_can_add_subscribers_group,
"can_add_subscribers_group",
"realm",
);
}
export function user_can_create_private_streams(): boolean {

View File

@@ -362,7 +362,6 @@ export const realm_schema = z.object({
realm_inline_image_preview: z.boolean(),
realm_inline_url_embed_preview: z.boolean(),
realm_invite_required: z.boolean(),
realm_invite_to_stream_policy: z.number(),
realm_is_zephyr_mirror_realm: z.boolean(),
realm_jitsi_server_url: z.nullable(z.string()),
realm_linkifiers: z.array(realm_linkifier_schema),

View File

@@ -104,7 +104,6 @@ import * as scroll_util from "./scroll_util.ts";
import * as search from "./search.ts";
import * as server_events from "./server_events.js";
import * as settings from "./settings.ts";
import * as settings_data from "./settings_data.ts";
import * as settings_notifications from "./settings_notifications.ts";
import * as settings_panel_menu from "./settings_panel_menu.ts";
import * as settings_preferences from "./settings_preferences.ts";
@@ -457,18 +456,6 @@ export function initialize_everything(state_data) {
people.initialize(current_user.user_id, state_data.people);
starred_messages.initialize(state_data.starred_messages);
let date_joined;
if (!page_params.is_spectator) {
const user = people.get_by_user_id(current_user.user_id);
date_joined = user.date_joined;
} else {
// Spectators don't have an account, so we just prevent their
// date_joined is now.
date_joined = new Date();
}
settings_data.initialize(date_joined);
// The emoji module must be initialized before the right sidebar
// module, so that we can display custom emoji in statuses.
emoji.initialize({

View File

@@ -685,11 +685,8 @@ test_ui("warn_if_mentioning_unsubscribed_user", ({override, mock_template}) => {
const $textarea = $("<textarea>").attr("id", "compose-textarea");
stub_message_row($textarea);
compose_state.set_stream_id("");
override(
realm,
"realm_invite_to_stream_policy",
settings_config.common_policy_values.by_members.code,
);
override(realm, "realm_can_add_subscribers_group", everyone.id);
let mentioned_details = {
user: {

View File

@@ -530,10 +530,7 @@ run_test("realm settings", ({override}) => {
assert.equal(realm[parameter_name], 1);
}
let event = event_fixtures.realm__update__invite_to_stream_policy;
test_realm_integer(event, "realm_invite_to_stream_policy");
event = event_fixtures.realm__update__bot_creation_policy;
let event = event_fixtures.realm__update__bot_creation_policy;
test_realm_integer(event, "realm_bot_creation_policy");
event = event_fixtures.realm__update__invite_required;
@@ -601,6 +598,7 @@ run_test("realm settings", ({override}) => {
override(realm, "realm_message_content_edit_limit_seconds", 0);
override(realm, "realm_authentication_methods", {Google: {enabled: false, available: true}});
override(realm, "realm_can_add_custom_emoji_group", 1);
override(realm, "realm_can_add_subscribers_group", 1);
override(realm, "realm_can_create_public_channel_group", 1);
override(realm, "realm_can_invite_users_group", 1);
override(realm, "realm_can_move_messages_between_topics_group", 1);
@@ -617,6 +615,7 @@ run_test("realm settings", ({override}) => {
Google: {enabled: true, available: true},
});
assert_same(realm.realm_can_add_custom_emoji_group, 3);
assert_same(realm.realm_can_add_subscribers_group, 3);
assert_same(realm.realm_can_create_public_channel_group, 3);
assert_same(realm.realm_can_invite_users_group, 3);
assert_same(realm.realm_can_move_messages_between_topics_group, 3);

View File

@@ -308,13 +308,6 @@ exports.fixtures = {
value: false,
},
realm__update__invite_to_stream_policy: {
type: "realm",
op: "update",
property: "invite_to_stream_policy",
value: 2,
},
realm__update__name: {
type: "realm",
op: "update",
@@ -369,6 +362,7 @@ exports.fixtures = {
Google: {enabled: true, available: true},
},
can_add_custom_emoji_group: 3,
can_add_subscribers_group: 3,
can_create_public_channel_group: 3,
can_invite_users_group: 3,
can_move_messages_between_topics_group: 3,

View File

@@ -36,5 +36,13 @@ exports.server_supported_permission_settings = {
default_group_name: "role:everyone",
allowed_system_groups: ["role:everyone", "role:members"],
},
can_add_subscribers_group: {
require_system_group: false,
allow_internet_group: false,
allow_nobody_group: true,
allow_everyone_group: false,
default_group_name: "role:members",
allowed_system_groups: [],
},
},
};

View File

@@ -26,13 +26,6 @@ initialize_user_settings({user_settings});
test people.js.
*/
const isaac = {
email: "isaac@example.com",
delivery_email: "isaac-delivery@example.com",
user_id: 30,
full_name: "Isaac",
};
const admins = {
description: "Administrators",
name: "role:administrators",
@@ -183,60 +176,16 @@ run_test("user_can_change_logo", ({override}) => {
assert.equal(can_change_logo(), false);
});
function test_policy(label, policy, validation_func) {
run_test(label, ({override}) => {
override(current_user, "is_admin", true);
override(realm, policy, settings_config.common_policy_values.by_admins_only.code);
assert.equal(validation_func(), true);
override(current_user, "is_admin", false);
assert.equal(validation_func(), false);
override(current_user, "is_moderator", true);
override(realm, policy, settings_config.common_policy_values.by_moderators_only.code);
assert.equal(validation_func(), true);
override(current_user, "is_moderator", false);
assert.equal(validation_func(), false);
override(current_user, "is_guest", true);
override(realm, policy, settings_config.common_policy_values.by_members.code);
assert.equal(validation_func(), false);
override(current_user, "is_guest", false);
assert.equal(validation_func(), true);
page_params.is_spectator = true;
override(realm, policy, settings_config.common_policy_values.by_members.code);
assert.equal(validation_func(), false);
page_params.is_spectator = false;
assert.equal(validation_func(), true);
override(realm, policy, settings_config.common_policy_values.by_full_members.code);
override(current_user, "user_id", 30);
isaac.date_joined = new Date(Date.now());
settings_data.initialize(isaac.date_joined);
override(realm, "realm_waiting_period_threshold", 10);
assert.equal(validation_func(), false);
isaac.date_joined = new Date(Date.now() - 20 * 86400000);
settings_data.initialize(isaac.date_joined);
assert.equal(validation_func(), true);
});
}
test_policy(
"user_can_subscribe_other_users",
"realm_invite_to_stream_policy",
settings_data.user_can_subscribe_other_users,
);
test_realm_group_settings(
"realm_can_add_custom_emoji_group",
settings_data.user_can_add_custom_emoji,
);
test_realm_group_settings(
"realm_can_add_subscribers_group",
settings_data.user_can_subscribe_other_users,
);
test_realm_group_settings(
"realm_can_delete_any_message_group",
settings_data.user_can_delete_any_message,

View File

@@ -19,7 +19,6 @@ mock_esm("../src/loading", {
mock_esm("../src/scroll_util", {scroll_element_into_container: noop});
set_global("document", "document-stub");
const settings_config = zrequire("settings_config");
const settings_bots = zrequire("settings_bots");
const settings_account = zrequire("settings_account");
const settings_components = zrequire("settings_components");
@@ -104,7 +103,6 @@ function test_submit_settings_form(override, submit_form) {
realm_bot_creation_policy: settings_bots.bot_creation_policy_values.restricted.code,
realm_waiting_period_threshold: 1,
realm_default_language: '"es"',
realm_invite_to_stream_policy: settings_config.common_policy_values.by_admins_only.code,
});
override(global, "setTimeout", (func) => func());
@@ -131,21 +129,13 @@ function test_submit_settings_form(override, submit_form) {
$("#id_realm_waiting_period_threshold").val(10);
const $invite_to_stream_policy_elem = $("#id_realm_invite_to_stream_policy");
$invite_to_stream_policy_elem.val("1");
$invite_to_stream_policy_elem.attr("id", "id_realm_invite_to_stream_policy");
$invite_to_stream_policy_elem.data = () => "number";
const $bot_creation_policy_elem = $("#id_realm_bot_creation_policy");
$bot_creation_policy_elem.val("1");
$bot_creation_policy_elem.attr("id", "id_realm_bot_creation_policy");
$bot_creation_policy_elem.data = () => "number";
let $subsection_elem = $(`#org-${CSS.escape(subsection)}`);
$subsection_elem.set_find_results(".prop-element", [
$bot_creation_policy_elem,
$invite_to_stream_policy_elem,
]);
$subsection_elem.set_find_results(".prop-element", [$bot_creation_policy_elem]);
patched = false;
submit_form.call({to_$: () => $(".save-discard-widget-button.save-button")}, ev);
@@ -153,7 +143,6 @@ function test_submit_settings_form(override, submit_form) {
let expected_value = {
bot_creation_policy: 1,
invite_to_stream_policy: 1,
};
assert.deepEqual(data, expected_value);
@@ -283,33 +272,6 @@ function test_sync_realm_settings({override}) {
$.create("save-button-controls-stub").addClass("hide"),
);
function test_common_policy(property_name) {
const $property_elem = $(`#id_realm_${CSS.escape(property_name)}`);
$property_elem.length = 1;
$property_elem.attr("id", `id_realm_${CSS.escape(property_name)}`);
$property_elem.closest = () => $subsection_stub;
$property_elem[0] = `#id_realm_${CSS.escape(property_name)}`;
/* Each policy is initialized to 'by_members' and then all the values are tested
in the following order - by_admins_only, by_moderators_only, by_full_members,
by_members. */
override(
realm,
`realm_${property_name}`,
settings_config.common_policy_values.by_members.code,
);
$property_elem.val(settings_config.common_policy_values.by_members.code);
for (const policy_value of Object.values(settings_config.common_policy_values)) {
override(realm, `realm_${property_name}`, policy_value.code);
settings_org.sync_realm_settings(property_name);
assert.equal($property_elem.val(), policy_value.code);
}
}
test_common_policy("invite_to_stream_policy");
{
/* Test message content edit limit minutes sync */
const $property_elem = $("#id_realm_message_content_edit_limit_minutes");
@@ -361,31 +323,6 @@ function test_sync_realm_settings({override}) {
settings_org.sync_realm_settings("emails_restricted_to_domains");
assert.equal($("#id_realm_org_join_restrictions").val(), "no_restriction");
}
{
// Test hiding save-discard buttons on live-updating.
const $property_elem = $("#id_realm_invite_to_stream_policy");
$property_elem.length = 1;
$property_elem.attr("id", "id_realm_invite_to_stream_policy");
$property_elem.closest = () => $subsection_stub;
const save_button_stubs = createSaveButtons("subsection-stub");
$subsection_stub.set_find_results(
".save-button-controls",
save_button_stubs.$save_button_controls,
);
$property_elem.val(settings_config.common_policy_values.by_admins_only.code);
override(
realm,
"realm_invite_to_stream_policy",
settings_config.common_policy_values.by_members.code,
);
save_button_stubs.$save_button_controls.removeClass("hide");
$subsection_stub.set_find_results(".prop-element", [$property_elem]);
settings_org.sync_realm_settings("invite_to_stream_policy");
assert.equal(save_button_stubs.props.hidden, true);
}
}
function test_parse_time_limit({override}) {

View File

@@ -14,7 +14,6 @@ page_params.development_environment = true;
const color_data = zrequire("color_data");
const peer_data = zrequire("peer_data");
const people = zrequire("people");
const settings_config = zrequire("settings_config");
const sub_store = zrequire("sub_store");
const stream_data = zrequire("stream_data");
const hash_util = zrequire("hash_util");
@@ -359,17 +358,14 @@ test("get_streams_for_user", ({override}) => {
for (const sub of subs) {
stream_data.add_sub(sub);
}
override(current_user, "user_id", me.user_id);
peer_data.set_subscribers(denmark.stream_id, [me.user_id, test_user.user_id]);
peer_data.set_subscribers(social.stream_id, [test_user.user_id]);
peer_data.set_subscribers(test.stream_id, [test_user.user_id]);
peer_data.set_subscribers(world.stream_id, [me.user_id]);
override(
realm,
"realm_invite_to_stream_policy",
settings_config.common_policy_values.by_admins_only.code,
);
override(realm, "realm_can_add_subscribers_group", students.id);
assert.deepEqual(stream_data.get_streams_for_user(me.user_id).can_subscribe, [social, errors]);
// test_user is subscribed to all three streams, but current user (me)
@@ -384,19 +380,13 @@ test("get_streams_for_user", ({override}) => {
social,
]);
assert.deepEqual(stream_data.get_streams_for_user(test_user.user_id).can_subscribe, []);
// Verify can subscribe if we're an administrator.
// Verify that administrator cannot subscribe if they are not part
// of the appropriate group.
override(current_user, "is_admin", true);
assert.deepEqual(stream_data.get_streams_for_user(test_user.user_id).can_subscribe, [
world,
errors,
]);
override(current_user, "is_admin", false);
assert.equal(user_groups.is_user_in_group(students.id, current_user.user_id), false);
assert.deepEqual(stream_data.get_streams_for_user(test_user.user_id).can_subscribe, []);
override(
realm,
"realm_invite_to_stream_policy",
settings_config.common_policy_values.by_members.code,
);
override(realm, "realm_can_add_subscribers_group", everyone_group.id);
assert.deepEqual(stream_data.get_streams_for_user(test_user.user_id).can_subscribe, [
world,
errors,
@@ -433,6 +423,8 @@ test("renames", () => {
});
test("admin_options", ({override}) => {
override(realm, "realm_can_add_subscribers_group", admins_group.id);
function make_sub(can_administer_channel_group) {
const sub = {
subscribed: false,
@@ -518,6 +510,7 @@ test("admin_options", ({override}) => {
});
test("stream_settings", ({override}) => {
override(realm, "realm_can_add_subscribers_group", admins_group.id);
const cinnamon = {
stream_id: 1,
name: "c",
@@ -1076,11 +1069,14 @@ test("get_invite_stream_data", ({override}) => {
people.init();
people.add_active_user(me);
people.initialize_current_user(me.user_id);
override(current_user, "user_id", me.user_id);
override(current_user, "is_admin", true);
stream_data.add_sub(orie);
stream_data.set_realm_default_streams([orie.stream_id]);
override(realm, "realm_can_add_subscribers_group", everyone_group.id);
const expected_list = [
{
name: "Orie",

View File

@@ -2,6 +2,7 @@
const assert = require("node:assert/strict");
const example_settings = require("./lib/example_settings.cjs");
const {zrequire} = require("./lib/namespace.cjs");
const {run_test} = require("./lib/test.cjs");
@@ -10,10 +11,12 @@ const people = zrequire("people");
const {set_current_user, set_realm} = zrequire("state_data");
const stream_data = zrequire("stream_data");
const stream_pill = zrequire("stream_pill");
const user_groups = zrequire("user_groups");
const current_user = {};
const realm = {};
set_current_user(current_user);
set_realm({});
set_realm(realm);
const denmark = {
stream_id: 101,
@@ -60,9 +63,24 @@ const me = {
people.add_active_user(me);
people.initialize_current_user(me.user_id);
const me_group = {
name: "me_group",
id: 1,
members: new Set([me.user_id]),
is_system_group: false,
direct_subgroup_ids: new Set([]),
};
user_groups.initialize({realm_user_groups: [me_group]});
run_test("create_item", ({override}) => {
override(current_user, "user_id", me.user_id);
override(current_user, "is_admin", true);
override(
realm,
"server_supported_permission_settings",
example_settings.server_supported_permission_settings,
);
override(realm, "realm_can_add_subscribers_group", me_group.id);
function test_create_item(
stream_name,
current_items,

View File

@@ -23,6 +23,15 @@ mock_esm("../src/browser_history", {
mock_esm("../src/hash_parser", {
get_current_hash_section: () => denmark_stream_id,
});
mock_esm("../src/group_permission_settings", {
get_group_permission_setting_config() {
return {
allow_everyone_group: false,
};
},
});
set_global("page_params", {});
const {set_current_user, set_realm} = zrequire("state_data");
@@ -31,7 +40,8 @@ const stream_settings_ui = zrequire("stream_settings_ui");
const user_groups = zrequire("user_groups");
const {initialize_user_settings} = zrequire("user_settings");
set_realm({});
const realm = {};
set_realm(realm);
set_current_user({});
initialize_user_settings({user_settings: {}});
@@ -53,8 +63,9 @@ const initialize_user_groups = () => {
user_groups.initialize({realm_user_groups: [admins_group, nobody_group]});
};
run_test("redraw_left_panel", ({mock_template}) => {
run_test("redraw_left_panel", ({override, mock_template}) => {
initialize_user_groups();
override(realm, "realm_can_add_subscribers_group", admins_group.id);
// set-up sub rows stubs
const denmark = {