mirror of https://github.com/zulip/zulip.git
user_groups: Set can_manage_all_groups to administrator group.
Earlier we use to restrict admins, moderators or members of a group to manage that group if they were part of the realm wide `can_manage_all_groups`. We will not do that anymore and even non-members of a group regardless of role can manage a group if they are part of `can_manage_all_groups`. See https://chat.zulip.org/#narrow/stream/101-design/topic/Group.20add.20members.20dropdown/near/1952902 to check more about the migration plan for which this is the last step.
This commit is contained in:
parent
9bbd6a7316
commit
c9d5276031
|
@ -142,12 +142,7 @@ By default, [owners](/help/roles-and-permissions) in a Zulip
|
|||
organization can manage user groups. However, you can expand that
|
||||
ability to specific [roles](/help/roles-and-permissions).
|
||||
|
||||
<!-- TODO: Remove this after #25942 is resolved and we've removed
|
||||
the condition that only members can manage the group if they are
|
||||
not admins or moderators. -->
|
||||
Note that administrators and moderators can modify any user group,
|
||||
while other organization members can only modify user groups to which
|
||||
they belong. Guests cannot modify user groups.
|
||||
Guests cannot modify user groups.
|
||||
|
||||
{start_tabs}
|
||||
|
||||
|
|
|
@ -192,19 +192,9 @@ export function can_manage_user_group(group_id: number): boolean {
|
|||
return false;
|
||||
}
|
||||
|
||||
let can_manage_all_groups = user_can_manage_all_groups();
|
||||
|
||||
const group = user_groups.get_user_group_from_id(group_id);
|
||||
|
||||
if (
|
||||
!current_user.is_admin &&
|
||||
!current_user.is_moderator &&
|
||||
!user_groups.is_direct_member_of(current_user.user_id, group_id)
|
||||
) {
|
||||
can_manage_all_groups = false;
|
||||
}
|
||||
|
||||
if (can_manage_all_groups) {
|
||||
if (user_can_manage_all_groups()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -443,10 +443,12 @@ run_test("can_manage_user_group", ({override}) => {
|
|||
override(current_user, "user_id", 2);
|
||||
assert.ok(!settings_data.can_manage_user_group(students.id));
|
||||
|
||||
// User with role member and not part of the group.
|
||||
override(realm, "realm_can_manage_all_groups", members.id);
|
||||
override(current_user, "user_id", 3);
|
||||
assert.ok(!settings_data.can_manage_user_group(students.id));
|
||||
assert.ok(settings_data.can_manage_user_group(students.id));
|
||||
|
||||
// User with role member and part of the group.
|
||||
override(current_user, "user_id", 2);
|
||||
assert.ok(settings_data.can_manage_user_group(students.id));
|
||||
|
||||
|
|
|
@ -132,24 +132,6 @@ def access_user_group_to_read_membership(user_group_id: int, realm: Realm) -> Na
|
|||
return get_user_group_by_id_in_realm(user_group_id, realm, for_read=True)
|
||||
|
||||
|
||||
def check_permission_for_managing_all_groups(
|
||||
user_group: UserGroup, user_profile: UserProfile
|
||||
) -> bool:
|
||||
"""
|
||||
Given a user and a group in the same realm, checks if the user
|
||||
can manage the group through the legacy can_manage_all_groups
|
||||
permission, which is a permission that requires either certain roles
|
||||
or membership in the group itself to be used.
|
||||
"""
|
||||
can_manage_all_groups = user_profile.can_manage_all_groups()
|
||||
if can_manage_all_groups:
|
||||
if user_profile.is_realm_admin or user_profile.is_moderator:
|
||||
return True
|
||||
|
||||
return is_user_in_group(user_group, user_profile)
|
||||
return False
|
||||
|
||||
|
||||
def access_user_group_for_update(
|
||||
user_group_id: int,
|
||||
user_profile: UserProfile,
|
||||
|
@ -173,10 +155,14 @@ def access_user_group_for_update(
|
|||
raise JsonableError(_("Insufficient permission"))
|
||||
|
||||
assert permission_setting in NamedUserGroup.GROUP_PERMISSION_SETTINGS
|
||||
if permission_setting in [
|
||||
if (
|
||||
permission_setting
|
||||
in [
|
||||
"can_manage_group",
|
||||
"can_add_members_group",
|
||||
] and check_permission_for_managing_all_groups(user_group, user_profile):
|
||||
]
|
||||
and user_profile.can_manage_all_groups()
|
||||
):
|
||||
return user_group
|
||||
|
||||
user_has_permission = user_has_permission_for_group_setting(
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
# Generated by Django 5.0.9 on 2024-10-10 10:41
|
||||
|
||||
from django.db import migrations, transaction
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
from django.db.migrations.state import StateApps
|
||||
from django.db.models import Max, Min, OuterRef
|
||||
|
||||
|
||||
def remap_can_manage_all_groups_for_existing_realms(
|
||||
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
|
||||
) -> None:
|
||||
Realm = apps.get_model("zerver", "Realm")
|
||||
NamedUserGroup = apps.get_model("zerver", "NamedUserGroup")
|
||||
BATCH_SIZE = 1000
|
||||
max_id = NamedUserGroup.objects.aggregate(Max("id"))["id__max"]
|
||||
|
||||
if max_id is None:
|
||||
# Do nothing if there are no user groups on the server.
|
||||
return
|
||||
|
||||
lower_bound = NamedUserGroup.objects.aggregate(Min("id"))["id__min"]
|
||||
|
||||
while lower_bound <= max_id:
|
||||
upper_bound = lower_bound + BATCH_SIZE - 1
|
||||
print(f"Processing batch {lower_bound} to {upper_bound} for NamedUserGroup")
|
||||
|
||||
with transaction.atomic():
|
||||
# Since can_manage_group, can_add_members_group, etc. have
|
||||
# migrated to the nearest possible value from
|
||||
# user_group_edit_policy, we want to set
|
||||
# can_manage_all_groups to the most restrictive setting
|
||||
# previously possible. We've chosen administrators as the
|
||||
# value here since the highest possible
|
||||
# user_group_edit_policy was with role administrators.
|
||||
Realm.objects.update(
|
||||
can_manage_all_groups=NamedUserGroup.objects.filter(
|
||||
name="role:administrators", realm=OuterRef("id"), is_system_group=True
|
||||
).values("pk")
|
||||
)
|
||||
|
||||
lower_bound += BATCH_SIZE
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
atomic = False
|
||||
dependencies = [
|
||||
("zerver", "0601_alter_namedusergroup_can_add_members_group"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
remap_can_manage_all_groups_for_existing_realms,
|
||||
elidable=True,
|
||||
reverse_code=migrations.RunPython.noop,
|
||||
)
|
||||
]
|
|
@ -1291,10 +1291,6 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||
acting_user=None,
|
||||
)
|
||||
|
||||
self.login("hamlet")
|
||||
result = self.client_post(f"/json/user_groups/{support_group.id}/deactivate")
|
||||
self.assert_json_error(result, "Insufficient permission")
|
||||
|
||||
self.login("othello")
|
||||
result = self.client_post(f"/json/user_groups/{support_group.id}/deactivate")
|
||||
self.assert_json_success(result)
|
||||
|
@ -1997,8 +1993,7 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||
check_update_user_group("support1", "Support team - test", "iago")
|
||||
check_update_user_group("support", "Support team", "othello")
|
||||
|
||||
# Check only members are allowed to update the user group and only if belong to the
|
||||
# user group.
|
||||
# Check only members are allowed to update the user group.
|
||||
members_group = NamedUserGroup.objects.get(name=SystemGroups.MEMBERS, realm=realm)
|
||||
do_change_realm_permission_group_setting(
|
||||
realm,
|
||||
|
@ -2009,13 +2004,7 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||
check_update_user_group(
|
||||
"help", "Troubleshooting team", "polonius", "Not allowed for guest users"
|
||||
)
|
||||
check_update_user_group(
|
||||
"help",
|
||||
"Troubleshooting team",
|
||||
"cordelia",
|
||||
"Insufficient permission",
|
||||
)
|
||||
check_update_user_group("help", "Troubleshooting team", "othello")
|
||||
check_update_user_group("help", "Troubleshooting team", "cordelia")
|
||||
|
||||
# Check user who is member of a subgroup of the group being updated
|
||||
# can also update the group.
|
||||
|
@ -2181,8 +2170,7 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||
self.assert_json_error(result, error_msg)
|
||||
|
||||
realm = get_realm("zulip")
|
||||
# Check only admins are allowed to add/remove users from the group. Admins are allowed even if
|
||||
# they are not a member of the group.
|
||||
# Check only admins are allowed to add/remove users from the group.
|
||||
admins_group = NamedUserGroup.objects.get(name=SystemGroups.ADMINISTRATORS, realm=realm)
|
||||
do_change_realm_permission_group_setting(
|
||||
realm,
|
||||
|
@ -2196,8 +2184,7 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||
check_removing_members_from_group("shiva", "Insufficient permission")
|
||||
check_removing_members_from_group("iago")
|
||||
|
||||
# Check moderators are allowed to add/remove users from the group but not members. Moderators are
|
||||
# allowed even if they are not a member of the group.
|
||||
# Check moderators are allowed to add/remove users from the group but not members.
|
||||
moderators_group = NamedUserGroup.objects.get(name=SystemGroups.MODERATORS, realm=realm)
|
||||
do_change_realm_permission_group_setting(
|
||||
realm,
|
||||
|
@ -2258,15 +2245,18 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||
acting_user=None,
|
||||
)
|
||||
check_adding_members_to_group("polonius", "Not allowed for guest users")
|
||||
check_adding_members_to_group("cordelia", "Insufficient permission")
|
||||
check_adding_members_to_group("othello")
|
||||
|
||||
# User with role member but not part of the target group should
|
||||
# be allowed to add members to the group if they are part of
|
||||
# `can_manage_all_groups`.
|
||||
check_adding_members_to_group("cordelia")
|
||||
check_removing_members_from_group("cordelia")
|
||||
|
||||
check_adding_members_to_group("othello")
|
||||
check_removing_members_from_group("polonius", "Not allowed for guest users")
|
||||
check_removing_members_from_group("cordelia", "Insufficient permission")
|
||||
check_removing_members_from_group("othello")
|
||||
|
||||
# Check only full members are allowed to add/remove users in the group and only if belong to the
|
||||
# user group.
|
||||
# Check only full members are allowed to add/remove users in the group.
|
||||
full_members_group = NamedUserGroup.objects.get(name=SystemGroups.FULL_MEMBERS, realm=realm)
|
||||
do_change_realm_permission_group_setting(
|
||||
realm,
|
||||
|
@ -2284,7 +2274,12 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||
cordelia.date_joined = timezone_now() - timedelta(days=11)
|
||||
cordelia.save()
|
||||
promote_new_full_members()
|
||||
check_adding_members_to_group("cordelia", "Insufficient permission")
|
||||
|
||||
# Full members who are not part of the target group should
|
||||
# be allowed to add members to the group if they are part of
|
||||
# `can_manage_all_groups`.
|
||||
check_adding_members_to_group("cordelia")
|
||||
check_removing_members_from_group("cordelia")
|
||||
|
||||
othello.date_joined = timezone_now() - timedelta(days=11)
|
||||
othello.save()
|
||||
|
@ -2295,7 +2290,6 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||
othello.save()
|
||||
promote_new_full_members()
|
||||
|
||||
check_removing_members_from_group("cordelia", "Insufficient permission")
|
||||
check_removing_members_from_group("othello", "Insufficient permission")
|
||||
|
||||
othello.date_joined = timezone_now() - timedelta(days=11)
|
||||
|
|
Loading…
Reference in New Issue