user_groups: Use can_leave_group setting to check permisison.

This commit adds code to use can_leave_group setting when
checking permission to leave group in webapp.
This commit is contained in:
Shubham Padia 2024-10-14 11:29:10 +00:00 committed by Tim Abbott
parent bf46747735
commit 1862c3b333
9 changed files with 157 additions and 3 deletions

View File

@ -231,6 +231,16 @@ export function can_join_user_group(group_id: number): boolean {
return can_manage_user_group(group_id); return can_manage_user_group(group_id);
} }
export function can_leave_user_group(group_id: number): boolean {
const group = user_groups.get_user_group_from_id(group_id);
if (user_has_permission_for_group_setting(group.can_leave_group, "can_leave_group", "group")) {
return true;
}
return can_manage_user_group(group_id);
}
export function user_can_create_user_groups(): boolean { export function user_can_create_user_groups(): boolean {
return user_has_permission_for_group_setting( return user_has_permission_for_group_setting(
realm.realm_can_create_groups, realm.realm_can_create_groups,

View File

@ -147,6 +147,7 @@ export const user_group_schema = z.object({
direct_subgroup_ids: z.array(z.number()), direct_subgroup_ids: z.array(z.number()),
can_add_members_group: group_setting_value_schema, can_add_members_group: group_setting_value_schema,
can_join_group: group_setting_value_schema, can_join_group: group_setting_value_schema,
can_leave_group: group_setting_value_schema,
can_manage_group: group_setting_value_schema, can_manage_group: group_setting_value_schema,
can_mention_group: z.number(), can_mention_group: z.number(),
deactivated: z.boolean(), deactivated: z.boolean(),

View File

@ -18,6 +18,7 @@ export type UserGroupUpdateEvent = {
description?: string; description?: string;
can_add_members_group?: number; can_add_members_group?: number;
can_join_group?: number; can_join_group?: number;
can_leave_group?: number;
can_manage_group?: number; can_manage_group?: number;
can_mention_group?: number; can_mention_group?: number;
deactivated?: boolean; deactivated?: boolean;

View File

@ -272,7 +272,7 @@ function update_group_membership_button(group_id) {
} }
const can_join_group = settings_data.can_join_user_group(group_id); const can_join_group = settings_data.can_join_user_group(group_id);
const can_leave_group = settings_data.can_manage_user_group(group_id); const can_leave_group = settings_data.can_leave_user_group(group_id);
let can_update_membership = true; let can_update_membership = true;
if (!is_member && !can_join_group) { if (!is_member && !can_join_group) {
@ -339,7 +339,7 @@ export function handle_member_edit_event(group_id, user_ids) {
const item = group; const item = group;
item.is_member = user_groups.is_user_in_group(group_id, people.my_current_user_id()); item.is_member = user_groups.is_user_in_group(group_id, people.my_current_user_id());
item.can_join = settings_data.can_join_user_group(item.id); item.can_join = settings_data.can_join_user_group(item.id);
item.can_leave = settings_data.can_manage_user_group(item.id); item.can_leave = settings_data.can_leave_user_group(item.id);
const html = render_browse_user_groups_list_item(item); const html = render_browse_user_groups_list_item(item);
const $new_row = $(html); const $new_row = $(html);
@ -670,6 +670,10 @@ export function update_group(event) {
sync_group_permission_setting("can_join_group", group); sync_group_permission_setting("can_join_group", group);
update_group_membership_button(group.id); update_group_membership_button(group.id);
} }
if (event.data.can_leave_group !== undefined) {
sync_group_permission_setting("can_leave_group", group);
update_group_membership_button(group.id);
}
} }
} }
@ -883,7 +887,7 @@ export function setup_page(callback) {
item.id, item.id,
); );
item.can_join = settings_data.can_join_user_group(item.id); item.can_join = settings_data.can_join_user_group(item.id);
item.can_leave = settings_data.can_manage_user_group(item.id); item.can_leave = settings_data.can_leave_user_group(item.id);
return render_browse_user_groups_list_item(item); return render_browse_user_groups_list_item(item);
}, },
filter: { filter: {

View File

@ -57,6 +57,7 @@ export function add(user_group_raw: UserGroupRaw): UserGroup {
direct_subgroup_ids: new Set(user_group_raw.direct_subgroup_ids), direct_subgroup_ids: new Set(user_group_raw.direct_subgroup_ids),
can_add_members_group: user_group_raw.can_add_members_group, can_add_members_group: user_group_raw.can_add_members_group,
can_join_group: user_group_raw.can_join_group, can_join_group: user_group_raw.can_join_group,
can_leave_group: user_group_raw.can_leave_group,
can_manage_group: user_group_raw.can_manage_group, can_manage_group: user_group_raw.can_manage_group,
can_mention_group: user_group_raw.can_mention_group, can_mention_group: user_group_raw.can_mention_group,
deactivated: user_group_raw.deactivated, deactivated: user_group_raw.deactivated,
@ -126,6 +127,12 @@ export function update(event: UserGroupUpdateEvent): void {
user_group_name_dict.delete(group.name); user_group_name_dict.delete(group.name);
user_group_name_dict.set(group.name, group); user_group_name_dict.set(group.name, group);
} }
if (event.data.can_leave_group !== undefined) {
group.can_leave_group = event.data.can_leave_group;
user_group_name_dict.delete(group.name);
user_group_name_dict.set(group.name, group);
}
} }
export function get_user_group_from_name(name: string): UserGroup | undefined { export function get_user_group_from_name(name: string): UserGroup | undefined {

View File

@ -450,6 +450,7 @@ const hamletcharacters = user_group_item({
direct_subgroup_ids: new Set([]), direct_subgroup_ids: new Set([]),
can_add_members_group: 2, can_add_members_group: 2,
can_join_group: 2, can_join_group: 2,
can_leave_group: 2,
can_manage_group: 2, can_manage_group: 2,
can_mention_group: 2, can_mention_group: 2,
deactivated: false, deactivated: false,
@ -466,6 +467,7 @@ const backend = user_group_item({
direct_subgroup_ids: new Set([1]), direct_subgroup_ids: new Set([1]),
can_add_members_group: 1, can_add_members_group: 1,
can_join_group: 1, can_join_group: 1,
can_leave_group: 2,
can_manage_group: 1, can_manage_group: 1,
can_mention_group: 1, can_mention_group: 1,
deactivated: false, deactivated: false,
@ -482,6 +484,7 @@ const call_center = user_group_item({
direct_subgroup_ids: new Set([]), direct_subgroup_ids: new Set([]),
can_add_members_group: 2, can_add_members_group: 2,
can_join_group: 2, can_join_group: 2,
can_leave_group: 2,
can_manage_group: 2, can_manage_group: 2,
can_mention_group: 2, can_mention_group: 2,
deactivated: false, deactivated: false,

View File

@ -841,6 +841,7 @@ exports.fixtures = {
direct_subgroup_ids: [2], direct_subgroup_ids: [2],
can_add_members_group: 16, can_add_members_group: 16,
can_join_group: 16, can_join_group: 16,
can_leave_group: 15,
can_manage_group: 16, can_manage_group: 16,
can_mention_group: 11, can_mention_group: 11,
deactivated: false, deactivated: false,

View File

@ -587,6 +587,129 @@ run_test("can_join_user_group", ({override}) => {
assert.ok(settings_data.can_join_user_group(students.id)); assert.ok(settings_data.can_join_user_group(students.id));
}); });
run_test("can_leave_user_group", ({override}) => {
const admins = {
description: "Administrators",
name: "role:administrators",
id: 1,
members: new Set([1]),
is_system_group: true,
direct_subgroup_ids: new Set([]),
can_join_group: 4,
can_leave_group: 4,
can_manage_group: 4,
can_mention_group: 1,
};
const moderators = {
description: "Moderators",
name: "role:moderators",
id: 2,
members: new Set([2]),
is_system_group: true,
direct_subgroup_ids: new Set([1]),
can_join_group: 4,
can_leave_group: 4,
can_manage_group: 4,
can_mention_group: 1,
};
const members = {
description: "Members",
name: "role:members",
id: 3,
members: new Set([3, 4]),
is_system_group: true,
direct_subgroup_ids: new Set([1, 2]),
can_join_group: 4,
can_leave_group: 4,
can_manage_group: 4,
can_mention_group: 4,
};
const nobody = {
description: "Nobody",
name: "role:nobody",
id: 4,
members: new Set([]),
is_system_group: true,
direct_subgroup_ids: new Set([]),
can_join_group: 4,
can_leave_group: 4,
can_manage_group: 4,
can_mention_group: 2,
};
const students = {
description: "Students group",
name: "Students",
id: 5,
members: new Set([1, 2]),
is_system_group: false,
direct_subgroup_ids: new Set([4, 5]),
can_join_group: 1,
can_leave_group: 1,
can_manage_group: {
direct_members: [4],
direct_subgroups: [],
},
can_mention_group: 3,
creator_id: 4,
};
user_groups.initialize({
realm_user_groups: [admins, moderators, members, nobody, students],
});
override(realm, "realm_can_manage_all_groups", nobody.id);
page_params.is_spectator = true;
assert.ok(!settings_data.can_leave_user_group(students.id));
page_params.is_spectator = false;
// admin user
override(current_user, "user_id", 1);
assert.ok(settings_data.can_leave_user_group(students.id));
// moderator user
override(current_user, "user_id", 2);
assert.ok(!settings_data.can_leave_user_group(students.id));
let event = {
group_id: students.id,
data: {
can_leave_group: moderators.id,
},
};
user_groups.update(event);
assert.ok(settings_data.can_leave_user_group(students.id));
override(current_user, "user_id", 1);
assert.ok(settings_data.can_leave_user_group(students.id));
// Some other user.
override(current_user, "user_id", 5);
assert.ok(!settings_data.can_leave_user_group(students.id));
event = {
group_id: students.id,
data: {
can_leave_group: {
direct_members: [5],
direct_subgroups: [admins.id],
},
},
};
user_groups.update(event);
assert.ok(settings_data.can_leave_user_group(students.id));
override(current_user, "user_id", 2);
assert.ok(!settings_data.can_leave_user_group(students.id));
// User can leave the group if they can manage the group which
// depends on can_manage_group and realm.can_manage_all_groups settings.
override(current_user, "user_id", 4);
assert.ok(settings_data.can_leave_user_group(students.id));
override(realm, "realm_can_manage_all_groups", moderators.id);
override(current_user, "user_id", 2);
assert.ok(settings_data.can_leave_user_group(students.id));
});
run_test("can_add_members_user_group", () => { run_test("can_add_members_user_group", () => {
const admins = { const admins = {
description: "Administrators", description: "Administrators",

View File

@ -24,6 +24,7 @@ run_test("user_groups", () => {
direct_subgroup_ids: new Set([4, 5]), direct_subgroup_ids: new Set([4, 5]),
can_add_members_group: 1, can_add_members_group: 1,
can_join_group: 1, can_join_group: 1,
can_leave_group: 1,
can_manage_group: 1, can_manage_group: 1,
can_mention_group: 2, can_mention_group: 2,
deactivated: false, deactivated: false,
@ -48,6 +49,7 @@ run_test("user_groups", () => {
direct_subgroup_ids: new Set([]), direct_subgroup_ids: new Set([]),
can_add_members_group: 1, can_add_members_group: 1,
can_join_group: 1, can_join_group: 1,
can_leave_group: 1,
can_manage_group: 1, can_manage_group: 1,
can_mention_group: 2, can_mention_group: 2,
deactivated: false, deactivated: false,
@ -59,6 +61,7 @@ run_test("user_groups", () => {
is_system_group: false, is_system_group: false,
direct_subgroup_ids: new Set([4, 5, 6]), direct_subgroup_ids: new Set([4, 5, 6]),
can_join_group: 1, can_join_group: 1,
can_leave_group: 1,
can_manage_group: 1, can_manage_group: 1,
can_mention_group: 1, can_mention_group: 1,
deactivated: false, deactivated: false,
@ -70,6 +73,7 @@ run_test("user_groups", () => {
is_system_group: false, is_system_group: false,
direct_subgroup_ids: new Set([4, 5, 6]), direct_subgroup_ids: new Set([4, 5, 6]),
can_join_group: 1, can_join_group: 1,
can_leave_group: 1,
can_manage_group: 1, can_manage_group: 1,
can_mention_group: 1, can_mention_group: 1,
deactivated: true, deactivated: true,