mirror of https://github.com/zulip/zulip.git
user_groups: Create NamedUserGroup objects when creating new groups.
This commit is contained in:
parent
71b601cf5a
commit
86f73fcb3d
|
@ -13,6 +13,7 @@ from zerver.lib.user_groups import (
|
||||||
)
|
)
|
||||||
from zerver.models import (
|
from zerver.models import (
|
||||||
GroupGroupMembership,
|
GroupGroupMembership,
|
||||||
|
NamedUserGroup,
|
||||||
Realm,
|
Realm,
|
||||||
RealmAuditLog,
|
RealmAuditLog,
|
||||||
UserGroup,
|
UserGroup,
|
||||||
|
@ -40,13 +41,22 @@ def create_user_group_in_database(
|
||||||
description: str = "",
|
description: str = "",
|
||||||
group_settings_map: Mapping[str, UserGroup] = {},
|
group_settings_map: Mapping[str, UserGroup] = {},
|
||||||
is_system_group: bool = False,
|
is_system_group: bool = False,
|
||||||
) -> UserGroup:
|
) -> NamedUserGroup:
|
||||||
user_group = UserGroup(
|
user_group = NamedUserGroup(
|
||||||
name=name, realm=realm, description=description, is_system_group=is_system_group
|
name=name,
|
||||||
|
realm=realm,
|
||||||
|
description=description,
|
||||||
|
is_system_group=is_system_group,
|
||||||
|
named_group_name=name,
|
||||||
|
named_group_description=description,
|
||||||
|
named_group_is_system_group=is_system_group,
|
||||||
|
realm_for_sharding=realm,
|
||||||
)
|
)
|
||||||
|
|
||||||
for setting_name, setting_value in group_settings_map.items():
|
for setting_name, setting_value in group_settings_map.items():
|
||||||
setattr(user_group, setting_name, setting_value)
|
setattr(user_group, setting_name, setting_value)
|
||||||
|
named_group_setting_name = "named_group_" + setting_name
|
||||||
|
setattr(user_group, named_group_setting_name, setting_value)
|
||||||
|
|
||||||
system_groups_name_dict = get_role_based_system_groups_dict(realm)
|
system_groups_name_dict = get_role_based_system_groups_dict(realm)
|
||||||
user_group = set_defaults_for_group_settings(
|
user_group = set_defaults_for_group_settings(
|
||||||
|
@ -156,7 +166,9 @@ def promote_new_full_members() -> None:
|
||||||
|
|
||||||
|
|
||||||
def do_send_create_user_group_event(
|
def do_send_create_user_group_event(
|
||||||
user_group: UserGroup, members: List[UserProfile], direct_subgroups: Sequence[UserGroup] = []
|
user_group: NamedUserGroup,
|
||||||
|
members: List[UserProfile],
|
||||||
|
direct_subgroups: Sequence[UserGroup] = [],
|
||||||
) -> None:
|
) -> None:
|
||||||
event = dict(
|
event = dict(
|
||||||
type="user_group",
|
type="user_group",
|
||||||
|
@ -182,7 +194,7 @@ def check_add_user_group(
|
||||||
group_settings_map: Mapping[str, UserGroup] = {},
|
group_settings_map: Mapping[str, UserGroup] = {},
|
||||||
*,
|
*,
|
||||||
acting_user: Optional[UserProfile],
|
acting_user: Optional[UserProfile],
|
||||||
) -> UserGroup:
|
) -> NamedUserGroup:
|
||||||
try:
|
try:
|
||||||
user_group = create_user_group_in_database(
|
user_group = create_user_group_in_database(
|
||||||
name,
|
name,
|
||||||
|
|
|
@ -52,6 +52,7 @@ from zerver.models import (
|
||||||
Huddle,
|
Huddle,
|
||||||
Message,
|
Message,
|
||||||
MutedUser,
|
MutedUser,
|
||||||
|
NamedUserGroup,
|
||||||
OnboardingStep,
|
OnboardingStep,
|
||||||
Reaction,
|
Reaction,
|
||||||
Realm,
|
Realm,
|
||||||
|
@ -1040,7 +1041,7 @@ def do_import_realm(import_dir: Path, subdomain: str, processes: int = 1) -> Rea
|
||||||
|
|
||||||
# We expect Zulip server exports to contain these system groups,
|
# We expect Zulip server exports to contain these system groups,
|
||||||
# this logic here is needed to handle the imports from other services.
|
# this logic here is needed to handle the imports from other services.
|
||||||
role_system_groups_dict: Optional[Dict[int, UserGroup]] = None
|
role_system_groups_dict: Optional[Dict[int, NamedUserGroup]] = None
|
||||||
if "zerver_usergroup" not in data:
|
if "zerver_usergroup" not in data:
|
||||||
role_system_groups_dict = create_system_user_groups_for_realm(realm)
|
role_system_groups_dict = create_system_user_groups_for_realm(realm)
|
||||||
|
|
||||||
|
@ -1736,7 +1737,9 @@ def import_analytics_data(realm: Realm, import_dir: Path, crossrealm_user_ids: S
|
||||||
|
|
||||||
|
|
||||||
def add_users_to_system_user_groups(
|
def add_users_to_system_user_groups(
|
||||||
realm: Realm, user_profiles: List[UserProfile], role_system_groups_dict: Dict[int, UserGroup]
|
realm: Realm,
|
||||||
|
user_profiles: List[UserProfile],
|
||||||
|
role_system_groups_dict: Dict[int, NamedUserGroup],
|
||||||
) -> None:
|
) -> None:
|
||||||
full_members_system_group = UserGroup.objects.get(
|
full_members_system_group = UserGroup.objects.get(
|
||||||
name=SystemGroups.FULL_MEMBERS,
|
name=SystemGroups.FULL_MEMBERS,
|
||||||
|
|
|
@ -2,17 +2,19 @@ from contextlib import contextmanager
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Collection, Dict, Iterable, Iterator, List, Mapping, TypedDict
|
from typing import Collection, Dict, Iterable, Iterator, List, Mapping, TypedDict
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import connection, transaction
|
||||||
from django.db.models import F, QuerySet
|
from django.db.models import F, QuerySet
|
||||||
from django.utils.timezone import now as timezone_now
|
from django.utils.timezone import now as timezone_now
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django_cte import With
|
from django_cte import With
|
||||||
from django_stubs_ext import ValuesQuerySet
|
from django_stubs_ext import ValuesQuerySet
|
||||||
|
from psycopg2.sql import SQL, Literal
|
||||||
|
|
||||||
from zerver.lib.exceptions import JsonableError
|
from zerver.lib.exceptions import JsonableError
|
||||||
from zerver.lib.types import GroupPermissionSetting, ServerSupportedPermissionSettings
|
from zerver.lib.types import GroupPermissionSetting, ServerSupportedPermissionSettings
|
||||||
from zerver.models import (
|
from zerver.models import (
|
||||||
GroupGroupMembership,
|
GroupGroupMembership,
|
||||||
|
NamedUserGroup,
|
||||||
Realm,
|
Realm,
|
||||||
RealmAuditLog,
|
RealmAuditLog,
|
||||||
Stream,
|
Stream,
|
||||||
|
@ -394,8 +396,8 @@ def get_recursive_subgroups_for_groups(
|
||||||
return recursive_subgroups
|
return recursive_subgroups
|
||||||
|
|
||||||
|
|
||||||
def get_role_based_system_groups_dict(realm: Realm) -> Dict[str, UserGroup]:
|
def get_role_based_system_groups_dict(realm: Realm) -> Dict[str, NamedUserGroup]:
|
||||||
system_groups = UserGroup.objects.filter(realm=realm, is_system_group=True)
|
system_groups = NamedUserGroup.objects.filter(realm=realm, is_system_group=True)
|
||||||
system_groups_name_dict = {}
|
system_groups_name_dict = {}
|
||||||
for group in system_groups:
|
for group in system_groups:
|
||||||
system_groups_name_dict[group.name] = group
|
system_groups_name_dict[group.name] = group
|
||||||
|
@ -404,10 +406,10 @@ def get_role_based_system_groups_dict(realm: Realm) -> Dict[str, UserGroup]:
|
||||||
|
|
||||||
|
|
||||||
def set_defaults_for_group_settings(
|
def set_defaults_for_group_settings(
|
||||||
user_group: UserGroup,
|
user_group: NamedUserGroup,
|
||||||
group_settings_map: Mapping[str, UserGroup],
|
group_settings_map: Mapping[str, UserGroup],
|
||||||
system_groups_name_dict: Dict[str, UserGroup],
|
system_groups_name_dict: Dict[str, NamedUserGroup],
|
||||||
) -> UserGroup:
|
) -> NamedUserGroup:
|
||||||
for setting_name, permission_config in UserGroup.GROUP_PERMISSION_SETTINGS.items():
|
for setting_name, permission_config in UserGroup.GROUP_PERMISSION_SETTINGS.items():
|
||||||
if setting_name in group_settings_map:
|
if setting_name in group_settings_map:
|
||||||
# We skip the settings for which a value is passed
|
# We skip the settings for which a value is passed
|
||||||
|
@ -419,73 +421,121 @@ def set_defaults_for_group_settings(
|
||||||
else:
|
else:
|
||||||
default_group_name = permission_config.default_group_name
|
default_group_name = permission_config.default_group_name
|
||||||
|
|
||||||
default_group = system_groups_name_dict[default_group_name]
|
default_group = system_groups_name_dict[default_group_name].usergroup_ptr
|
||||||
setattr(user_group, setting_name, default_group)
|
setattr(user_group, setting_name, default_group)
|
||||||
|
|
||||||
|
setting_name_for_named_object = "named_group_" + setting_name
|
||||||
|
setattr(user_group, setting_name_for_named_object, default_group)
|
||||||
|
|
||||||
return user_group
|
return user_group
|
||||||
|
|
||||||
|
|
||||||
@transaction.atomic(savepoint=False)
|
def bulk_create_system_user_groups(groups: List[Dict[str, str]], realm: Realm) -> None:
|
||||||
def create_system_user_groups_for_realm(realm: Realm) -> Dict[int, UserGroup]:
|
|
||||||
"""Any changes to this function likely require a migration to adjust
|
|
||||||
existing realms. See e.g. migration 0382_create_role_based_system_groups.py,
|
|
||||||
which is a copy of this function from when we introduced system groups.
|
|
||||||
"""
|
|
||||||
role_system_groups_dict: Dict[int, UserGroup] = {}
|
|
||||||
|
|
||||||
# This value will be used to set the temporary initial value for different
|
# This value will be used to set the temporary initial value for different
|
||||||
# settings since we can only set them to the correct values after the groups
|
# settings since we can only set them to the correct values after the groups
|
||||||
# are created.
|
# are created.
|
||||||
initial_group_setting_value = -1
|
initial_group_setting_value = -1
|
||||||
|
rows = [
|
||||||
for role in UserGroup.SYSTEM_USER_GROUP_ROLE_MAP:
|
SQL("({},{},{},{},{})").format(
|
||||||
user_group_params = UserGroup.SYSTEM_USER_GROUP_ROLE_MAP[role]
|
Literal(realm.id),
|
||||||
user_group = UserGroup(
|
Literal(group["name"]),
|
||||||
name=user_group_params["name"],
|
Literal(group["description"]),
|
||||||
description=user_group_params["description"],
|
Literal(True),
|
||||||
realm=realm,
|
Literal(initial_group_setting_value),
|
||||||
is_system_group=True,
|
|
||||||
can_mention_group_id=initial_group_setting_value,
|
|
||||||
)
|
)
|
||||||
role_system_groups_dict[role] = user_group
|
for group in groups
|
||||||
|
]
|
||||||
|
|
||||||
|
query = SQL(
|
||||||
|
"""
|
||||||
|
INSERT INTO zerver_usergroup (realm_id, name, description, is_system_group, can_mention_group_id)
|
||||||
|
VALUES {rows}
|
||||||
|
RETURNING id
|
||||||
|
"""
|
||||||
|
).format(rows=SQL(", ").join(rows))
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute(query)
|
||||||
|
user_group_ids = [id for (id,) in cursor.fetchall()]
|
||||||
|
|
||||||
|
rows = [
|
||||||
|
SQL("({},{},{},{},{},{})").format(
|
||||||
|
Literal(user_group_ids[idx]),
|
||||||
|
Literal(realm.id),
|
||||||
|
Literal(group["name"]),
|
||||||
|
Literal(group["description"]),
|
||||||
|
Literal(True),
|
||||||
|
Literal(initial_group_setting_value),
|
||||||
|
)
|
||||||
|
for idx, group in enumerate(groups)
|
||||||
|
]
|
||||||
|
query = SQL(
|
||||||
|
"""
|
||||||
|
INSERT INTO zerver_namedusergroup (usergroup_ptr_id, realm_id, name, description, is_system_group, can_mention_group_id)
|
||||||
|
VALUES {rows}
|
||||||
|
"""
|
||||||
|
).format(rows=SQL(", ").join(rows))
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute(query)
|
||||||
|
|
||||||
|
|
||||||
|
@transaction.atomic(savepoint=False)
|
||||||
|
def create_system_user_groups_for_realm(realm: Realm) -> Dict[int, NamedUserGroup]:
|
||||||
|
"""Any changes to this function likely require a migration to adjust
|
||||||
|
existing realms. See e.g. migration 0382_create_role_based_system_groups.py,
|
||||||
|
which is a copy of this function from when we introduced system groups.
|
||||||
|
"""
|
||||||
|
role_system_groups_dict: Dict[int, NamedUserGroup] = {}
|
||||||
|
|
||||||
|
system_groups_info_list: List[Dict[str, str]] = []
|
||||||
|
|
||||||
|
nobody_group_info = {
|
||||||
|
"name": SystemGroups.NOBODY,
|
||||||
|
"description": "Nobody",
|
||||||
|
}
|
||||||
|
|
||||||
|
full_members_group_info = {
|
||||||
|
"name": SystemGroups.FULL_MEMBERS,
|
||||||
|
"description": "Members of this organization, not including new accounts and guests",
|
||||||
|
}
|
||||||
|
|
||||||
|
everyone_on_internet_group_info = {
|
||||||
|
"name": SystemGroups.EVERYONE_ON_INTERNET,
|
||||||
|
"description": "Everyone on the Internet",
|
||||||
|
}
|
||||||
|
|
||||||
|
system_groups_info_list = [
|
||||||
|
nobody_group_info,
|
||||||
|
UserGroup.SYSTEM_USER_GROUP_ROLE_MAP[UserProfile.ROLE_REALM_OWNER],
|
||||||
|
UserGroup.SYSTEM_USER_GROUP_ROLE_MAP[UserProfile.ROLE_REALM_ADMINISTRATOR],
|
||||||
|
UserGroup.SYSTEM_USER_GROUP_ROLE_MAP[UserProfile.ROLE_MODERATOR],
|
||||||
|
full_members_group_info,
|
||||||
|
UserGroup.SYSTEM_USER_GROUP_ROLE_MAP[UserProfile.ROLE_MEMBER],
|
||||||
|
UserGroup.SYSTEM_USER_GROUP_ROLE_MAP[UserProfile.ROLE_GUEST],
|
||||||
|
everyone_on_internet_group_info,
|
||||||
|
]
|
||||||
|
|
||||||
|
bulk_create_system_user_groups(system_groups_info_list, realm)
|
||||||
|
|
||||||
|
system_groups_name_dict: Dict[str, NamedUserGroup] = get_role_based_system_groups_dict(realm)
|
||||||
|
for role in UserGroup.SYSTEM_USER_GROUP_ROLE_MAP:
|
||||||
|
group_name = UserGroup.SYSTEM_USER_GROUP_ROLE_MAP[role]["name"]
|
||||||
|
role_system_groups_dict[role] = system_groups_name_dict[group_name]
|
||||||
|
|
||||||
full_members_system_group = UserGroup(
|
|
||||||
name=SystemGroups.FULL_MEMBERS,
|
|
||||||
description="Members of this organization, not including new accounts and guests",
|
|
||||||
realm=realm,
|
|
||||||
is_system_group=True,
|
|
||||||
can_mention_group_id=initial_group_setting_value,
|
|
||||||
)
|
|
||||||
everyone_on_internet_system_group = UserGroup(
|
|
||||||
name=SystemGroups.EVERYONE_ON_INTERNET,
|
|
||||||
description="Everyone on the Internet",
|
|
||||||
realm=realm,
|
|
||||||
is_system_group=True,
|
|
||||||
can_mention_group_id=initial_group_setting_value,
|
|
||||||
)
|
|
||||||
nobody_system_group = UserGroup(
|
|
||||||
name=SystemGroups.NOBODY,
|
|
||||||
description="Nobody",
|
|
||||||
realm=realm,
|
|
||||||
is_system_group=True,
|
|
||||||
can_mention_group_id=initial_group_setting_value,
|
|
||||||
)
|
|
||||||
# Order of this list here is important to create correct GroupGroupMembership objects
|
# Order of this list here is important to create correct GroupGroupMembership objects
|
||||||
# Note that because we do not create user memberships here, no audit log entries for
|
# Note that because we do not create user memberships here, no audit log entries for
|
||||||
# user memberships are populated either.
|
# user memberships are populated either.
|
||||||
system_user_groups_list = [
|
system_user_groups_list = [
|
||||||
nobody_system_group,
|
system_groups_name_dict[SystemGroups.NOBODY],
|
||||||
role_system_groups_dict[UserProfile.ROLE_REALM_OWNER],
|
system_groups_name_dict[SystemGroups.OWNERS],
|
||||||
role_system_groups_dict[UserProfile.ROLE_REALM_ADMINISTRATOR],
|
system_groups_name_dict[SystemGroups.ADMINISTRATORS],
|
||||||
role_system_groups_dict[UserProfile.ROLE_MODERATOR],
|
system_groups_name_dict[SystemGroups.MODERATORS],
|
||||||
full_members_system_group,
|
system_groups_name_dict[SystemGroups.FULL_MEMBERS],
|
||||||
role_system_groups_dict[UserProfile.ROLE_MEMBER],
|
system_groups_name_dict[SystemGroups.MEMBERS],
|
||||||
role_system_groups_dict[UserProfile.ROLE_GUEST],
|
system_groups_name_dict[SystemGroups.EVERYONE],
|
||||||
everyone_on_internet_system_group,
|
system_groups_name_dict[SystemGroups.EVERYONE_ON_INTERNET],
|
||||||
]
|
]
|
||||||
|
|
||||||
creation_time = timezone_now()
|
creation_time = timezone_now()
|
||||||
UserGroup.objects.bulk_create(system_user_groups_list)
|
|
||||||
realmauditlog_objects = [
|
realmauditlog_objects = [
|
||||||
RealmAuditLog(
|
RealmAuditLog(
|
||||||
realm=realm,
|
realm=realm,
|
||||||
|
@ -498,11 +548,12 @@ def create_system_user_groups_for_realm(realm: Realm) -> Dict[int, UserGroup]:
|
||||||
]
|
]
|
||||||
|
|
||||||
groups_with_updated_settings = []
|
groups_with_updated_settings = []
|
||||||
system_groups_name_dict = get_role_based_system_groups_dict(realm)
|
|
||||||
for group in system_user_groups_list:
|
for group in system_user_groups_list:
|
||||||
user_group = set_defaults_for_group_settings(group, {}, system_groups_name_dict)
|
user_group = set_defaults_for_group_settings(group, {}, system_groups_name_dict)
|
||||||
groups_with_updated_settings.append(user_group)
|
groups_with_updated_settings.append(user_group)
|
||||||
UserGroup.objects.bulk_update(groups_with_updated_settings, ["can_mention_group"])
|
NamedUserGroup.objects.bulk_update(
|
||||||
|
groups_with_updated_settings, ["can_mention_group", "named_group_can_mention_group"]
|
||||||
|
)
|
||||||
|
|
||||||
subgroup_objects: List[GroupGroupMembership] = []
|
subgroup_objects: List[GroupGroupMembership] = []
|
||||||
# "Nobody" system group is not a subgroup of any user group, since it is already empty.
|
# "Nobody" system group is not a subgroup of any user group, since it is already empty.
|
||||||
|
|
|
@ -8,6 +8,7 @@ from zerver.models.custom_profile_fields import CustomProfileField as CustomProf
|
||||||
from zerver.models.custom_profile_fields import CustomProfileFieldValue as CustomProfileFieldValue
|
from zerver.models.custom_profile_fields import CustomProfileFieldValue as CustomProfileFieldValue
|
||||||
from zerver.models.drafts import Draft as Draft
|
from zerver.models.drafts import Draft as Draft
|
||||||
from zerver.models.groups import GroupGroupMembership as GroupGroupMembership
|
from zerver.models.groups import GroupGroupMembership as GroupGroupMembership
|
||||||
|
from zerver.models.groups import NamedUserGroup as NamedUserGroup
|
||||||
from zerver.models.groups import UserGroup as UserGroup
|
from zerver.models.groups import UserGroup as UserGroup
|
||||||
from zerver.models.groups import UserGroupMembership as UserGroupMembership
|
from zerver.models.groups import UserGroupMembership as UserGroupMembership
|
||||||
from zerver.models.linkifiers import RealmFilter as RealmFilter
|
from zerver.models.linkifiers import RealmFilter as RealmFilter
|
||||||
|
|
|
@ -1167,7 +1167,7 @@ class TestRealmAuditLog(ZulipTestCase):
|
||||||
)
|
)
|
||||||
self.assert_length(audit_log_entries, 1)
|
self.assert_length(audit_log_entries, 1)
|
||||||
self.assertIsNone(audit_log_entries[0].modified_user)
|
self.assertIsNone(audit_log_entries[0].modified_user)
|
||||||
self.assertEqual(audit_log_entries[0].modified_user_group, user_group)
|
self.assertEqual(audit_log_entries[0].modified_user_group, user_group.usergroup_ptr)
|
||||||
|
|
||||||
audit_log_entries = RealmAuditLog.objects.filter(
|
audit_log_entries = RealmAuditLog.objects.filter(
|
||||||
acting_user=hamlet,
|
acting_user=hamlet,
|
||||||
|
@ -1212,19 +1212,21 @@ class TestRealmAuditLog(ZulipTestCase):
|
||||||
hamlet = self.example_user("hamlet")
|
hamlet = self.example_user("hamlet")
|
||||||
user_group = check_add_user_group(hamlet.realm, "main", [], acting_user=None)
|
user_group = check_add_user_group(hamlet.realm, "main", [], acting_user=None)
|
||||||
subgroups = [
|
subgroups = [
|
||||||
check_add_user_group(hamlet.realm, f"subgroup{num}", [], acting_user=hamlet)
|
check_add_user_group(
|
||||||
|
hamlet.realm, f"subgroup{num}", [], acting_user=hamlet
|
||||||
|
).usergroup_ptr
|
||||||
for num in range(3)
|
for num in range(3)
|
||||||
]
|
]
|
||||||
|
|
||||||
now = timezone_now()
|
now = timezone_now()
|
||||||
add_subgroups_to_user_group(user_group, subgroups, acting_user=hamlet)
|
add_subgroups_to_user_group(user_group.usergroup_ptr, subgroups, acting_user=hamlet)
|
||||||
# Only one audit log entry for the subgroup membership is expected.
|
# Only one audit log entry for the subgroup membership is expected.
|
||||||
audit_log_entry = RealmAuditLog.objects.get(
|
audit_log_entry = RealmAuditLog.objects.get(
|
||||||
realm=hamlet.realm,
|
realm=hamlet.realm,
|
||||||
event_time__gte=now,
|
event_time__gte=now,
|
||||||
event_type=RealmAuditLog.USER_GROUP_DIRECT_SUBGROUP_MEMBERSHIP_ADDED,
|
event_type=RealmAuditLog.USER_GROUP_DIRECT_SUBGROUP_MEMBERSHIP_ADDED,
|
||||||
)
|
)
|
||||||
self.assertEqual(audit_log_entry.modified_user_group, user_group)
|
self.assertEqual(audit_log_entry.modified_user_group, user_group.usergroup_ptr)
|
||||||
self.assertEqual(audit_log_entry.acting_user, hamlet)
|
self.assertEqual(audit_log_entry.acting_user, hamlet)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
audit_log_entry.extra_data,
|
audit_log_entry.extra_data,
|
||||||
|
@ -1244,13 +1246,15 @@ class TestRealmAuditLog(ZulipTestCase):
|
||||||
{"supergroup_ids": [user_group.id]},
|
{"supergroup_ids": [user_group.id]},
|
||||||
)
|
)
|
||||||
|
|
||||||
remove_subgroups_from_user_group(user_group, subgroups[:2], acting_user=hamlet)
|
remove_subgroups_from_user_group(
|
||||||
|
user_group.usergroup_ptr, subgroups[:2], acting_user=hamlet
|
||||||
|
)
|
||||||
audit_log_entry = RealmAuditLog.objects.get(
|
audit_log_entry = RealmAuditLog.objects.get(
|
||||||
realm=hamlet.realm,
|
realm=hamlet.realm,
|
||||||
event_time__gte=now,
|
event_time__gte=now,
|
||||||
event_type=RealmAuditLog.USER_GROUP_DIRECT_SUBGROUP_MEMBERSHIP_REMOVED,
|
event_type=RealmAuditLog.USER_GROUP_DIRECT_SUBGROUP_MEMBERSHIP_REMOVED,
|
||||||
)
|
)
|
||||||
self.assertEqual(audit_log_entry.modified_user_group, user_group)
|
self.assertEqual(audit_log_entry.modified_user_group, user_group.usergroup_ptr)
|
||||||
self.assertEqual(audit_log_entry.acting_user, hamlet)
|
self.assertEqual(audit_log_entry.acting_user, hamlet)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
audit_log_entry.extra_data,
|
audit_log_entry.extra_data,
|
||||||
|
|
|
@ -113,20 +113,29 @@ class UserGroupTestCase(ZulipTestCase):
|
||||||
everyone_group = check_add_user_group(realm, "Everyone", [shiva], acting_user=None)
|
everyone_group = check_add_user_group(realm, "Everyone", [shiva], acting_user=None)
|
||||||
GroupGroupMembership.objects.create(supergroup=everyone_group, subgroup=staff_group)
|
GroupGroupMembership.objects.create(supergroup=everyone_group, subgroup=staff_group)
|
||||||
|
|
||||||
self.assertCountEqual(list(get_recursive_subgroups(leadership_group)), [leadership_group])
|
|
||||||
self.assertCountEqual(
|
self.assertCountEqual(
|
||||||
list(get_recursive_subgroups(staff_group)), [leadership_group, staff_group]
|
list(get_recursive_subgroups(leadership_group)), [leadership_group.usergroup_ptr]
|
||||||
|
)
|
||||||
|
self.assertCountEqual(
|
||||||
|
list(get_recursive_subgroups(staff_group)),
|
||||||
|
[leadership_group.usergroup_ptr, staff_group.usergroup_ptr],
|
||||||
)
|
)
|
||||||
self.assertCountEqual(
|
self.assertCountEqual(
|
||||||
list(get_recursive_subgroups(everyone_group)),
|
list(get_recursive_subgroups(everyone_group)),
|
||||||
[leadership_group, staff_group, everyone_group],
|
[
|
||||||
|
leadership_group.usergroup_ptr,
|
||||||
|
staff_group.usergroup_ptr,
|
||||||
|
everyone_group.usergroup_ptr,
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertCountEqual(list(get_recursive_strict_subgroups(leadership_group)), [])
|
self.assertCountEqual(list(get_recursive_strict_subgroups(leadership_group)), [])
|
||||||
self.assertCountEqual(list(get_recursive_strict_subgroups(staff_group)), [leadership_group])
|
self.assertCountEqual(
|
||||||
|
list(get_recursive_strict_subgroups(staff_group)), [leadership_group.usergroup_ptr]
|
||||||
|
)
|
||||||
self.assertCountEqual(
|
self.assertCountEqual(
|
||||||
list(get_recursive_strict_subgroups(everyone_group)),
|
list(get_recursive_strict_subgroups(everyone_group)),
|
||||||
[leadership_group, staff_group],
|
[leadership_group.usergroup_ptr, staff_group.usergroup_ptr],
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertCountEqual(list(get_recursive_group_members(leadership_group)), [desdemona])
|
self.assertCountEqual(list(get_recursive_group_members(leadership_group)), [desdemona])
|
||||||
|
@ -135,14 +144,14 @@ class UserGroupTestCase(ZulipTestCase):
|
||||||
list(get_recursive_group_members(everyone_group)), [desdemona, iago, shiva]
|
list(get_recursive_group_members(everyone_group)), [desdemona, iago, shiva]
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertIn(leadership_group, get_recursive_membership_groups(desdemona))
|
self.assertIn(leadership_group.usergroup_ptr, get_recursive_membership_groups(desdemona))
|
||||||
self.assertIn(staff_group, get_recursive_membership_groups(desdemona))
|
self.assertIn(staff_group.usergroup_ptr, get_recursive_membership_groups(desdemona))
|
||||||
self.assertIn(everyone_group, get_recursive_membership_groups(desdemona))
|
self.assertIn(everyone_group.usergroup_ptr, get_recursive_membership_groups(desdemona))
|
||||||
|
|
||||||
self.assertIn(staff_group, get_recursive_membership_groups(iago))
|
self.assertIn(staff_group.usergroup_ptr, get_recursive_membership_groups(iago))
|
||||||
self.assertIn(everyone_group, get_recursive_membership_groups(iago))
|
self.assertIn(everyone_group.usergroup_ptr, get_recursive_membership_groups(iago))
|
||||||
|
|
||||||
self.assertIn(everyone_group, get_recursive_membership_groups(shiva))
|
self.assertIn(everyone_group.usergroup_ptr, get_recursive_membership_groups(shiva))
|
||||||
|
|
||||||
def test_subgroups_of_role_based_system_groups(self) -> None:
|
def test_subgroups_of_role_based_system_groups(self) -> None:
|
||||||
realm = get_realm("zulip")
|
realm = get_realm("zulip")
|
||||||
|
@ -368,7 +377,7 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
result = self.client_post("/json/user_groups/create", info=params)
|
result = self.client_post("/json/user_groups/create", info=params)
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
test_group = UserGroup.objects.get(name="test", realm=hamlet.realm)
|
test_group = UserGroup.objects.get(name="test", realm=hamlet.realm)
|
||||||
self.assertEqual(test_group.can_mention_group, leadership_group)
|
self.assertEqual(test_group.can_mention_group, leadership_group.usergroup_ptr)
|
||||||
|
|
||||||
nobody_group = UserGroup.objects.get(
|
nobody_group = UserGroup.objects.get(
|
||||||
name="role:nobody", realm=hamlet.realm, is_system_group=True
|
name="role:nobody", realm=hamlet.realm, is_system_group=True
|
||||||
|
@ -538,7 +547,7 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
result = self.client_patch(f"/json/user_groups/{support_group.id}", info=params)
|
result = self.client_patch(f"/json/user_groups/{support_group.id}", info=params)
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
support_group = UserGroup.objects.get(name="support", realm=hamlet.realm)
|
support_group = UserGroup.objects.get(name="support", realm=hamlet.realm)
|
||||||
self.assertEqual(support_group.can_mention_group, marketing_group)
|
self.assertEqual(support_group.can_mention_group, marketing_group.usergroup_ptr)
|
||||||
|
|
||||||
nobody_group = UserGroup.objects.get(
|
nobody_group = UserGroup.objects.get(
|
||||||
name="role:nobody", realm=hamlet.realm, is_system_group=True
|
name="role:nobody", realm=hamlet.realm, is_system_group=True
|
||||||
|
@ -640,7 +649,7 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
for i in range(50)
|
for i in range(50)
|
||||||
]
|
]
|
||||||
|
|
||||||
with self.assert_database_query_count(4):
|
with self.assert_database_query_count(5):
|
||||||
user_group = create_user_group_in_database(
|
user_group = create_user_group_in_database(
|
||||||
name="support",
|
name="support",
|
||||||
members=[hamlet, cordelia, *original_users],
|
members=[hamlet, cordelia, *original_users],
|
||||||
|
|
|
@ -12,7 +12,7 @@ from zerver.lib.exceptions import JsonableError
|
||||||
from zerver.lib.test_classes import ZulipTransactionTestCase
|
from zerver.lib.test_classes import ZulipTransactionTestCase
|
||||||
from zerver.lib.test_helpers import HostRequestMock
|
from zerver.lib.test_helpers import HostRequestMock
|
||||||
from zerver.lib.user_groups import access_user_group_by_id
|
from zerver.lib.user_groups import access_user_group_by_id
|
||||||
from zerver.models import Realm, UserGroup, UserProfile
|
from zerver.models import NamedUserGroup, Realm, UserGroup, UserProfile
|
||||||
from zerver.models.realms import get_realm
|
from zerver.models.realms import get_realm
|
||||||
from zerver.views.user_groups import update_subgroups_of_user_group
|
from zerver.views.user_groups import update_subgroups_of_user_group
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class UserGroupRaceConditionTestCase(ZulipTransactionTestCase):
|
||||||
|
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
||||||
def create_user_group_chain(self, realm: Realm) -> List[UserGroup]:
|
def create_user_group_chain(self, realm: Realm) -> List[NamedUserGroup]:
|
||||||
"""Build a user groups forming a chain through group-group memberships
|
"""Build a user groups forming a chain through group-group memberships
|
||||||
returning a list where each group is the supergroup of its subsequent group.
|
returning a list where each group is the supergroup of its subsequent group.
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue