mirror of
https://github.com/zulip/zulip.git
synced 2025-11-01 20:44:04 +00:00
Groups: Can perform any join, leave, add, remove for deactivated group.
Fixes #33804. We still do not allow permission settings to be set to deactivated groups.
This commit is contained in:
committed by
Tim Abbott
parent
74b0d8ff61
commit
7eb9c9deef
@@ -20,6 +20,12 @@ format used by the Zulip server that they are interacting with.
|
|||||||
|
|
||||||
## Changes in Zulip 11.0
|
## Changes in Zulip 11.0
|
||||||
|
|
||||||
|
**Feature level 391**
|
||||||
|
|
||||||
|
* [`POST /user_groups/{user_group_id}/members`](/api/update-user-group-members),
|
||||||
|
[`POST /user_groups/{user_group_id}/subgroups`](/api/update-user-group-subgroups):
|
||||||
|
Adding/removing members and subgroups to a deactivated group is now allowed.
|
||||||
|
|
||||||
**Feature level 390**
|
**Feature level 390**
|
||||||
|
|
||||||
* [`GET /events`](/api/get-events): Events with `type: "navigation_view"` are
|
* [`GET /events`](/api/get-events): Events with `type: "navigation_view"` are
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
|
|||||||
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
||||||
# entries in the endpoint's documentation in `zulip.yaml`.
|
# entries in the endpoint's documentation in `zulip.yaml`.
|
||||||
|
|
||||||
API_FEATURE_LEVEL = 390
|
API_FEATURE_LEVEL = 391
|
||||||
|
|
||||||
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
# 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
|
# only when going from an old version of the code to a newer version. Bump
|
||||||
|
|||||||
@@ -176,10 +176,6 @@ export function can_manage_user_group(group_id: number): boolean {
|
|||||||
|
|
||||||
export function can_add_members_to_user_group(group_id: number): boolean {
|
export function can_add_members_to_user_group(group_id: number): boolean {
|
||||||
const group = user_groups.get_user_group_from_id(group_id);
|
const group = user_groups.get_user_group_from_id(group_id);
|
||||||
// We cannot add members if the group is deactivated.
|
|
||||||
if (group.deactivated) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (
|
if (
|
||||||
user_has_permission_for_group_setting(
|
user_has_permission_for_group_setting(
|
||||||
group.can_add_members_group,
|
group.can_add_members_group,
|
||||||
@@ -195,10 +191,6 @@ export function can_add_members_to_user_group(group_id: number): boolean {
|
|||||||
|
|
||||||
export function can_remove_members_from_user_group(group_id: number): boolean {
|
export function can_remove_members_from_user_group(group_id: number): boolean {
|
||||||
const group = user_groups.get_user_group_from_id(group_id);
|
const group = user_groups.get_user_group_from_id(group_id);
|
||||||
// We cannot remove members if the group is deactivated.
|
|
||||||
if (group.deactivated) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (
|
if (
|
||||||
user_has_permission_for_group_setting(
|
user_has_permission_for_group_setting(
|
||||||
group.can_remove_members_group,
|
group.can_remove_members_group,
|
||||||
@@ -214,10 +206,6 @@ export function can_remove_members_from_user_group(group_id: number): boolean {
|
|||||||
|
|
||||||
export function can_join_user_group(group_id: number): boolean {
|
export function can_join_user_group(group_id: number): boolean {
|
||||||
const group = user_groups.get_user_group_from_id(group_id);
|
const group = user_groups.get_user_group_from_id(group_id);
|
||||||
// One cannot join a deactivated group.
|
|
||||||
if (group.deactivated) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (user_has_permission_for_group_setting(group.can_join_group, "can_join_group", "group")) {
|
if (user_has_permission_for_group_setting(group.can_join_group, "can_join_group", "group")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -226,11 +214,7 @@ export function can_join_user_group(group_id: number): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function can_leave_user_group(group_id: number): boolean {
|
export function can_leave_user_group(group_id: number): boolean {
|
||||||
// One cannot leave a deactivated group.
|
|
||||||
const group = user_groups.get_user_group_from_id(group_id);
|
const group = user_groups.get_user_group_from_id(group_id);
|
||||||
if (group.deactivated) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (user_has_permission_for_group_setting(group.can_leave_group, "can_leave_group", "group")) {
|
if (user_has_permission_for_group_setting(group.can_leave_group, "can_leave_group", "group")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,9 +164,9 @@ function update_add_members_elements(group: UserGroup): void {
|
|||||||
$button_element.prop("disabled", true);
|
$button_element.prop("disabled", true);
|
||||||
$add_members_container.addClass("add_members_disabled");
|
$add_members_container.addClass("add_members_disabled");
|
||||||
|
|
||||||
const disable_hint = group.deactivated
|
const disable_hint = $t({
|
||||||
? $t({defaultMessage: "Can't add members to a deactivated group"})
|
defaultMessage: "You are not allowed to add members to this group",
|
||||||
: $t({defaultMessage: "You are not allowed to add members to this group"});
|
});
|
||||||
settings_components.initialize_disable_button_hint_popover(
|
settings_components.initialize_disable_button_hint_popover(
|
||||||
$add_members_container,
|
$add_members_container,
|
||||||
disable_hint,
|
disable_hint,
|
||||||
@@ -309,13 +309,8 @@ function initialize_tooltip_for_membership_button(group_id: number): void {
|
|||||||
".join_leave_button_wrapper",
|
".join_leave_button_wrapper",
|
||||||
);
|
);
|
||||||
const is_member = user_groups.is_user_in_group(group_id, people.my_current_user_id());
|
const is_member = user_groups.is_user_in_group(group_id, people.my_current_user_id());
|
||||||
const is_deactivated = user_groups.get_user_group_from_id(group_id).deactivated;
|
|
||||||
let tooltip_message;
|
let tooltip_message;
|
||||||
if (is_deactivated && is_member) {
|
if (is_member) {
|
||||||
tooltip_message = $t({defaultMessage: "You cannot leave a deactivated user group."});
|
|
||||||
} else if (is_deactivated) {
|
|
||||||
tooltip_message = $t({defaultMessage: "You cannot join a deactivated user group."});
|
|
||||||
} else if (is_member) {
|
|
||||||
tooltip_message = $t({defaultMessage: "You do not have permission to leave this group."});
|
tooltip_message = $t({defaultMessage: "You do not have permission to leave this group."});
|
||||||
} else {
|
} else {
|
||||||
tooltip_message = $t({defaultMessage: "You do not have permission to join this group."});
|
tooltip_message = $t({defaultMessage: "You do not have permission to join this group."});
|
||||||
|
|||||||
@@ -110,6 +110,8 @@ const deactivated_group = {
|
|||||||
members: new Set([1, 2, 3]),
|
members: new Set([1, 2, 3]),
|
||||||
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_add_members_group: 4,
|
||||||
|
can_remove_members_group: 4,
|
||||||
can_join_group: 1,
|
can_join_group: 1,
|
||||||
can_leave_group: 1,
|
can_leave_group: 1,
|
||||||
can_manage_group: 1,
|
can_manage_group: 1,
|
||||||
@@ -436,8 +438,8 @@ function test_user_group_permission_setting(override, setting_name, permission_f
|
|||||||
override(current_user, "user_id", 2);
|
override(current_user, "user_id", 2);
|
||||||
assert.ok(permission_func(students.id));
|
assert.ok(permission_func(students.id));
|
||||||
|
|
||||||
// Cannot perform any join, leave, add, remove if group is deactivated
|
// Can perform any join, leave, add, remove even if the group is deactivated
|
||||||
assert.ok(!permission_func(deactivated_group.id));
|
assert.ok(permission_func(deactivated_group.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
run_test("can_join_user_group", ({override}) => {
|
run_test("can_join_user_group", ({override}) => {
|
||||||
|
|||||||
@@ -326,7 +326,10 @@ def lock_subgroups_with_respect_to_supergroup(
|
|||||||
else:
|
else:
|
||||||
assert permission_setting is not None
|
assert permission_setting is not None
|
||||||
potential_supergroup = access_user_group_for_update(
|
potential_supergroup = access_user_group_for_update(
|
||||||
potential_supergroup_id, acting_user, permission_setting=permission_setting
|
potential_supergroup_id,
|
||||||
|
acting_user,
|
||||||
|
permission_setting=permission_setting,
|
||||||
|
allow_deactivated=True,
|
||||||
)
|
)
|
||||||
# We avoid making a separate query for user_group_ids because the
|
# We avoid making a separate query for user_group_ids because the
|
||||||
# recursive query already returns those user groups.
|
# recursive query already returns those user groups.
|
||||||
|
|||||||
@@ -22518,6 +22518,9 @@ paths:
|
|||||||
Update the members of a [user group](/help/user-groups). The
|
Update the members of a [user group](/help/user-groups). The
|
||||||
user IDs must correspond to non-deactivated users.
|
user IDs must correspond to non-deactivated users.
|
||||||
|
|
||||||
|
**Changes**: Prior to Zulip 11.0 (feature level 391), members
|
||||||
|
could not be added or removed from a deactivated group.
|
||||||
|
|
||||||
**Changes**: Prior to Zulip 10.0 (feature level 303), group memberships of
|
**Changes**: Prior to Zulip 10.0 (feature level 303), group memberships of
|
||||||
deactivated users were visible to the API and could be edited via this endpoint.
|
deactivated users were visible to the API and could be edited via this endpoint.
|
||||||
x-curl-examples-parameters:
|
x-curl-examples-parameters:
|
||||||
@@ -23111,6 +23114,9 @@ paths:
|
|||||||
description: |
|
description: |
|
||||||
Update the subgroups of a [user group](/help/user-groups).
|
Update the subgroups of a [user group](/help/user-groups).
|
||||||
|
|
||||||
|
**Changes**: Prior to Zulip 11.0 (feature level 391), subgroups
|
||||||
|
could not be added or removed from a deactivated group.
|
||||||
|
|
||||||
**Changes**: New in Zulip 6.0 (feature level 127).
|
**Changes**: New in Zulip 6.0 (feature level 127).
|
||||||
x-curl-examples-parameters:
|
x-curl-examples-parameters:
|
||||||
oneOf:
|
oneOf:
|
||||||
|
|||||||
@@ -2122,12 +2122,12 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||||||
|
|
||||||
params = {"delete": orjson.dumps([hamlet.id]).decode()}
|
params = {"delete": orjson.dumps([hamlet.id]).decode()}
|
||||||
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
|
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
|
||||||
self.assert_json_error(result, "User group is deactivated.")
|
self.assert_json_success(result)
|
||||||
self.assert_user_membership(user_group, [hamlet])
|
self.assert_member_not_in_group(user_group, hamlet)
|
||||||
|
|
||||||
params = {"add": orjson.dumps([iago.id]).decode()}
|
params = {"add": orjson.dumps([hamlet.id]).decode()}
|
||||||
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
|
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
|
||||||
self.assert_json_error(result, "User group is deactivated.")
|
self.assert_json_success(result)
|
||||||
self.assert_user_membership(user_group, [hamlet])
|
self.assert_user_membership(user_group, [hamlet])
|
||||||
|
|
||||||
def test_mentions(self) -> None:
|
def test_mentions(self) -> None:
|
||||||
@@ -3317,12 +3317,12 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||||||
|
|
||||||
params = {"delete": orjson.dumps([leadership_group.id]).decode()}
|
params = {"delete": orjson.dumps([leadership_group.id]).decode()}
|
||||||
result = self.client_post(f"/json/user_groups/{support_group.id}/subgroups", info=params)
|
result = self.client_post(f"/json/user_groups/{support_group.id}/subgroups", info=params)
|
||||||
self.assert_json_error(result, "User group is deactivated.")
|
self.assert_json_success(result)
|
||||||
self.assert_subgroup_membership(support_group, [leadership_group])
|
self.assert_subgroup_membership(support_group, [])
|
||||||
|
|
||||||
params = {"add": orjson.dumps([test_group.id]).decode()}
|
params = {"add": orjson.dumps([leadership_group.id]).decode()}
|
||||||
result = self.client_post(f"/json/user_groups/{support_group.id}/subgroups", info=params)
|
result = self.client_post(f"/json/user_groups/{support_group.id}/subgroups", info=params)
|
||||||
self.assert_json_error(result, "User group is deactivated.")
|
self.assert_json_success(result)
|
||||||
self.assert_subgroup_membership(support_group, [leadership_group])
|
self.assert_subgroup_membership(support_group, [leadership_group])
|
||||||
|
|
||||||
# Test that a deactivated group cannot be used as a subgroup.
|
# Test that a deactivated group cannot be used as a subgroup.
|
||||||
|
|||||||
@@ -334,17 +334,26 @@ def add_members_to_group_backend(
|
|||||||
if len(members) == 1 and user_profile.id == members[0]:
|
if len(members) == 1 and user_profile.id == members[0]:
|
||||||
try:
|
try:
|
||||||
user_group = access_user_group_for_update(
|
user_group = access_user_group_for_update(
|
||||||
user_group_id, user_profile, permission_setting="can_join_group"
|
user_group_id,
|
||||||
|
user_profile,
|
||||||
|
permission_setting="can_join_group",
|
||||||
|
allow_deactivated=True,
|
||||||
)
|
)
|
||||||
except JsonableError:
|
except JsonableError:
|
||||||
# User can still join the group if user has permission to add
|
# User can still join the group if user has permission to add
|
||||||
# anyone in the group.
|
# anyone in the group.
|
||||||
user_group = access_user_group_for_update(
|
user_group = access_user_group_for_update(
|
||||||
user_group_id, user_profile, permission_setting="can_add_members_group"
|
user_group_id,
|
||||||
|
user_profile,
|
||||||
|
permission_setting="can_add_members_group",
|
||||||
|
allow_deactivated=True,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
user_group = access_user_group_for_update(
|
user_group = access_user_group_for_update(
|
||||||
user_group_id, user_profile, permission_setting="can_add_members_group"
|
user_group_id,
|
||||||
|
user_profile,
|
||||||
|
permission_setting="can_add_members_group",
|
||||||
|
allow_deactivated=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
member_users = user_ids_to_users(members, user_profile.realm, allow_deactivated=False)
|
member_users = user_ids_to_users(members, user_profile.realm, allow_deactivated=False)
|
||||||
@@ -381,17 +390,26 @@ def remove_members_from_group_backend(
|
|||||||
if len(members) == 1 and user_profile.id == members[0]:
|
if len(members) == 1 and user_profile.id == members[0]:
|
||||||
try:
|
try:
|
||||||
user_group = access_user_group_for_update(
|
user_group = access_user_group_for_update(
|
||||||
user_group_id, user_profile, permission_setting="can_leave_group"
|
user_group_id,
|
||||||
|
user_profile,
|
||||||
|
permission_setting="can_leave_group",
|
||||||
|
allow_deactivated=True,
|
||||||
)
|
)
|
||||||
except JsonableError:
|
except JsonableError:
|
||||||
# User can still leave the group if user has permission to remove
|
# User can still leave the group if user has permission to remove
|
||||||
# anyone from the group.
|
# anyone from the group.
|
||||||
user_group = access_user_group_for_update(
|
user_group = access_user_group_for_update(
|
||||||
user_group_id, user_profile, permission_setting="can_remove_members_group"
|
user_group_id,
|
||||||
|
user_profile,
|
||||||
|
permission_setting="can_remove_members_group",
|
||||||
|
allow_deactivated=True,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
user_group = access_user_group_for_update(
|
user_group = access_user_group_for_update(
|
||||||
user_group_id, user_profile, permission_setting="can_remove_members_group"
|
user_group_id,
|
||||||
|
user_profile,
|
||||||
|
permission_setting="can_remove_members_group",
|
||||||
|
allow_deactivated=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
group_member_ids = get_user_group_direct_member_ids(user_group)
|
group_member_ids = get_user_group_direct_member_ids(user_group)
|
||||||
|
|||||||
Reference in New Issue
Block a user