mirror of
https://github.com/zulip/zulip.git
synced 2025-11-10 00:46:03 +00:00
user_groups: Add "Nobody" system user group.
This commit adds code to create a "Nobody" system user group to realms which will be used in settings to represent "Nobody" option. We also add a migration to add this group to existing realms.
This commit is contained in:
@@ -237,8 +237,15 @@ def create_system_user_groups_for_realm(realm: Realm) -> Dict[int, UserGroup]:
|
|||||||
realm=realm,
|
realm=realm,
|
||||||
is_system_group=True,
|
is_system_group=True,
|
||||||
)
|
)
|
||||||
|
nobody_system_group = UserGroup(
|
||||||
|
name=UserGroup.NOBODY_GROUP_NAME,
|
||||||
|
description="Nobody",
|
||||||
|
realm=realm,
|
||||||
|
is_system_group=True,
|
||||||
|
)
|
||||||
# Order of this list here is important to create correct GroupGroupMembership objects
|
# Order of this list here is important to create correct GroupGroupMembership objects
|
||||||
system_user_groups_list = [
|
system_user_groups_list = [
|
||||||
|
nobody_system_group,
|
||||||
role_system_groups_dict[UserProfile.ROLE_REALM_OWNER],
|
role_system_groups_dict[UserProfile.ROLE_REALM_OWNER],
|
||||||
role_system_groups_dict[UserProfile.ROLE_REALM_ADMINISTRATOR],
|
role_system_groups_dict[UserProfile.ROLE_REALM_ADMINISTRATOR],
|
||||||
role_system_groups_dict[UserProfile.ROLE_MODERATOR],
|
role_system_groups_dict[UserProfile.ROLE_MODERATOR],
|
||||||
@@ -251,7 +258,8 @@ def create_system_user_groups_for_realm(realm: Realm) -> Dict[int, UserGroup]:
|
|||||||
UserGroup.objects.bulk_create(system_user_groups_list)
|
UserGroup.objects.bulk_create(system_user_groups_list)
|
||||||
|
|
||||||
subgroup_objects = []
|
subgroup_objects = []
|
||||||
subgroup, remaining_groups = system_user_groups_list[0], system_user_groups_list[1:]
|
# "Nobody" system group is not a subgroup of any user group, since it is already empty.
|
||||||
|
subgroup, remaining_groups = system_user_groups_list[1], system_user_groups_list[2:]
|
||||||
for supergroup in remaining_groups:
|
for supergroup in remaining_groups:
|
||||||
subgroup_objects.append(GroupGroupMembership(subgroup=subgroup, supergroup=supergroup))
|
subgroup_objects.append(GroupGroupMembership(subgroup=subgroup, supergroup=supergroup))
|
||||||
subgroup = supergroup
|
subgroup = supergroup
|
||||||
|
|||||||
50
zerver/migrations/0434_create_nobody_system_group.py
Normal file
50
zerver/migrations/0434_create_nobody_system_group.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# Generated by Django 4.1.7 on 2023-03-27 03:00
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||||
|
from django.db.migrations.state import StateApps
|
||||||
|
|
||||||
|
|
||||||
|
def create_nobody_system_user_group_for_existing_realms(
|
||||||
|
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
|
||||||
|
) -> None:
|
||||||
|
Realm = apps.get_model("zerver", "Realm")
|
||||||
|
UserGroup = apps.get_model("zerver", "UserGroup")
|
||||||
|
NOBODY_GROUP_NAME = "@role:nobody"
|
||||||
|
NOBODY_GROUP_DESCRIPTION = "Nobody"
|
||||||
|
|
||||||
|
groups_to_create = []
|
||||||
|
for realm in Realm.objects.all():
|
||||||
|
groups_to_create.append(
|
||||||
|
UserGroup(
|
||||||
|
name=NOBODY_GROUP_NAME,
|
||||||
|
description=NOBODY_GROUP_DESCRIPTION,
|
||||||
|
realm=realm,
|
||||||
|
is_system_group=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
UserGroup.objects.bulk_create(groups_to_create)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_nobody_system_user_groups(
|
||||||
|
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
|
||||||
|
) -> None:
|
||||||
|
UserGroup = apps.get_model("zerver", "UserGroup")
|
||||||
|
NOBODY_GROUP_NAME = "@role:nobody"
|
||||||
|
|
||||||
|
UserGroup.objects.filter(name=NOBODY_GROUP_NAME, is_system_group=True).delete()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("zerver", "0433_preregistrationrealm"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
create_nobody_system_user_group_for_existing_realms,
|
||||||
|
reverse_code=delete_nobody_system_user_groups,
|
||||||
|
elidable=True,
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -2224,6 +2224,7 @@ class UserGroup(models.Model): # type: ignore[django-manager-missing] # django-
|
|||||||
MODERATORS_GROUP_NAME = "@role:moderators"
|
MODERATORS_GROUP_NAME = "@role:moderators"
|
||||||
MEMBERS_GROUP_NAME = "@role:members"
|
MEMBERS_GROUP_NAME = "@role:members"
|
||||||
EVERYONE_GROUP_NAME = "@role:everyone"
|
EVERYONE_GROUP_NAME = "@role:everyone"
|
||||||
|
NOBODY_GROUP_NAME = "@role:nobody"
|
||||||
|
|
||||||
# We do not have "Full members" and "Everyone on the internet"
|
# We do not have "Full members" and "Everyone on the internet"
|
||||||
# group here since there isn't a separate role value for full
|
# group here since there isn't a separate role value for full
|
||||||
|
|||||||
@@ -15293,7 +15293,7 @@ paths:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: integer
|
type: integer
|
||||||
example: [8, 9]
|
example: [9, 10]
|
||||||
required: false
|
required: false
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
@@ -17605,7 +17605,7 @@ components:
|
|||||||
The ID of the target user group.
|
The ID of the target user group.
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
example: 29
|
example: 33
|
||||||
required: true
|
required: true
|
||||||
QueueId:
|
QueueId:
|
||||||
name: queue_id
|
name: queue_id
|
||||||
|
|||||||
@@ -435,10 +435,10 @@ class RealmImportExportTest(ExportFile):
|
|||||||
self.assertEqual(exported_realm_user_default[0]["default_language"], "de")
|
self.assertEqual(exported_realm_user_default[0]["default_language"], "de")
|
||||||
|
|
||||||
exported_usergroups = data["zerver_usergroup"]
|
exported_usergroups = data["zerver_usergroup"]
|
||||||
self.assert_length(exported_usergroups, 8)
|
self.assert_length(exported_usergroups, 9)
|
||||||
self.assertEqual(exported_usergroups[1]["name"], "@role:administrators")
|
self.assertEqual(exported_usergroups[2]["name"], "@role:administrators")
|
||||||
self.assertFalse("direct_members" in exported_usergroups[1])
|
self.assertFalse("direct_members" in exported_usergroups[2])
|
||||||
self.assertFalse("direct_subgroups" in exported_usergroups[1])
|
self.assertFalse("direct_subgroups" in exported_usergroups[2])
|
||||||
|
|
||||||
data = read_json("messages-000001.json")
|
data = read_json("messages-000001.json")
|
||||||
um = UserMessage.objects.all()[0]
|
um = UserMessage.objects.all()[0]
|
||||||
|
|||||||
@@ -977,7 +977,7 @@ class RealmTest(ZulipTestCase):
|
|||||||
realm = do_create_realm("realm_string_id", "realm name")
|
realm = do_create_realm("realm_string_id", "realm name")
|
||||||
system_user_groups = UserGroup.objects.filter(realm=realm, is_system_group=True)
|
system_user_groups = UserGroup.objects.filter(realm=realm, is_system_group=True)
|
||||||
|
|
||||||
self.assert_length(system_user_groups, 7)
|
self.assert_length(system_user_groups, 8)
|
||||||
user_group_names = [group.name for group in system_user_groups]
|
user_group_names = [group.name for group in system_user_groups]
|
||||||
expected_system_group_names = [
|
expected_system_group_names = [
|
||||||
UserGroup.OWNERS_GROUP_NAME,
|
UserGroup.OWNERS_GROUP_NAME,
|
||||||
@@ -987,6 +987,7 @@ class RealmTest(ZulipTestCase):
|
|||||||
UserGroup.MEMBERS_GROUP_NAME,
|
UserGroup.MEMBERS_GROUP_NAME,
|
||||||
UserGroup.EVERYONE_GROUP_NAME,
|
UserGroup.EVERYONE_GROUP_NAME,
|
||||||
UserGroup.EVERYONE_ON_INTERNET_GROUP_NAME,
|
UserGroup.EVERYONE_ON_INTERNET_GROUP_NAME,
|
||||||
|
UserGroup.NOBODY_GROUP_NAME,
|
||||||
]
|
]
|
||||||
self.assertEqual(user_group_names.sort(), expected_system_group_names.sort())
|
self.assertEqual(user_group_names.sort(), expected_system_group_names.sort())
|
||||||
|
|
||||||
|
|||||||
@@ -40,30 +40,37 @@ class UserGroupTestCase(ZulipTestCase):
|
|||||||
realm = get_realm("zulip")
|
realm = get_realm("zulip")
|
||||||
user_group = UserGroup.objects.filter(realm=realm).first()
|
user_group = UserGroup.objects.filter(realm=realm).first()
|
||||||
assert user_group is not None
|
assert user_group is not None
|
||||||
membership = UserGroupMembership.objects.filter(user_group=user_group).values_list(
|
|
||||||
"user_profile_id", flat=True
|
|
||||||
)
|
|
||||||
empty_user_group = check_add_user_group(realm, "newgroup", [], acting_user=None)
|
empty_user_group = check_add_user_group(realm, "newgroup", [], acting_user=None)
|
||||||
|
|
||||||
user_groups = user_groups_in_realm_serialized(realm)
|
user_groups = user_groups_in_realm_serialized(realm)
|
||||||
self.assert_length(user_groups, 9)
|
self.assert_length(user_groups, 10)
|
||||||
self.assertEqual(user_groups[0]["id"], user_group.id)
|
self.assertEqual(user_groups[0]["id"], user_group.id)
|
||||||
self.assertEqual(user_groups[0]["name"], UserGroup.OWNERS_GROUP_NAME)
|
self.assertEqual(user_groups[0]["name"], UserGroup.NOBODY_GROUP_NAME)
|
||||||
self.assertEqual(user_groups[0]["description"], "Owners of this organization")
|
self.assertEqual(user_groups[0]["description"], "Nobody")
|
||||||
self.assertEqual(set(user_groups[0]["members"]), set(membership))
|
self.assertEqual(user_groups[0]["members"], [])
|
||||||
self.assertEqual(user_groups[0]["direct_subgroup_ids"], [])
|
self.assertEqual(user_groups[0]["direct_subgroup_ids"], [])
|
||||||
|
|
||||||
|
owners_system_group = UserGroup.objects.get(name=UserGroup.OWNERS_GROUP_NAME, realm=realm)
|
||||||
|
membership = UserGroupMembership.objects.filter(user_group=owners_system_group).values_list(
|
||||||
|
"user_profile_id", flat=True
|
||||||
|
)
|
||||||
|
self.assertEqual(user_groups[1]["id"], owners_system_group.id)
|
||||||
|
self.assertEqual(user_groups[1]["name"], UserGroup.OWNERS_GROUP_NAME)
|
||||||
|
self.assertEqual(user_groups[1]["description"], "Owners of this organization")
|
||||||
|
self.assertEqual(set(user_groups[1]["members"]), set(membership))
|
||||||
|
self.assertEqual(user_groups[1]["direct_subgroup_ids"], [])
|
||||||
|
|
||||||
admins_system_group = UserGroup.objects.get(
|
admins_system_group = UserGroup.objects.get(
|
||||||
name=UserGroup.ADMINISTRATORS_GROUP_NAME, realm=realm
|
name=UserGroup.ADMINISTRATORS_GROUP_NAME, realm=realm
|
||||||
)
|
)
|
||||||
self.assertEqual(user_groups[1]["id"], admins_system_group.id)
|
self.assertEqual(user_groups[2]["id"], admins_system_group.id)
|
||||||
# Check that owners system group is present in "direct_subgroup_ids"
|
# Check that owners system group is present in "direct_subgroup_ids"
|
||||||
self.assertEqual(user_groups[1]["direct_subgroup_ids"], [user_group.id])
|
self.assertEqual(user_groups[2]["direct_subgroup_ids"], [owners_system_group.id])
|
||||||
|
|
||||||
self.assertEqual(user_groups[8]["id"], empty_user_group.id)
|
self.assertEqual(user_groups[9]["id"], empty_user_group.id)
|
||||||
self.assertEqual(user_groups[8]["name"], "newgroup")
|
self.assertEqual(user_groups[9]["name"], "newgroup")
|
||||||
self.assertEqual(user_groups[8]["description"], "")
|
self.assertEqual(user_groups[9]["description"], "")
|
||||||
self.assertEqual(user_groups[8]["members"], [])
|
self.assertEqual(user_groups[9]["members"], [])
|
||||||
|
|
||||||
def test_get_direct_user_groups(self) -> None:
|
def test_get_direct_user_groups(self) -> None:
|
||||||
othello = self.example_user("othello")
|
othello = self.example_user("othello")
|
||||||
@@ -221,7 +228,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)
|
||||||
self.assert_length(UserGroup.objects.filter(realm=hamlet.realm), 9)
|
self.assert_length(UserGroup.objects.filter(realm=hamlet.realm), 10)
|
||||||
|
|
||||||
# Test invalid member error
|
# Test invalid member error
|
||||||
params = {
|
params = {
|
||||||
@@ -231,7 +238,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_error(result, "Invalid user ID: 1111")
|
self.assert_json_error(result, "Invalid user ID: 1111")
|
||||||
self.assert_length(UserGroup.objects.filter(realm=hamlet.realm), 9)
|
self.assert_length(UserGroup.objects.filter(realm=hamlet.realm), 10)
|
||||||
|
|
||||||
# Test we cannot create group with same name again
|
# Test we cannot create group with same name again
|
||||||
params = {
|
params = {
|
||||||
@@ -241,7 +248,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_error(result, "User group 'support' already exists.")
|
self.assert_json_error(result, "User group 'support' already exists.")
|
||||||
self.assert_length(UserGroup.objects.filter(realm=hamlet.realm), 9)
|
self.assert_length(UserGroup.objects.filter(realm=hamlet.realm), 10)
|
||||||
|
|
||||||
def test_user_group_get(self) -> None:
|
def test_user_group_get(self) -> None:
|
||||||
# Test success
|
# Test success
|
||||||
@@ -323,11 +330,11 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||||||
self.client_post("/json/user_groups/create", info=params)
|
self.client_post("/json/user_groups/create", info=params)
|
||||||
user_group = UserGroup.objects.get(name="support")
|
user_group = UserGroup.objects.get(name="support")
|
||||||
# Test success
|
# Test success
|
||||||
self.assertEqual(UserGroup.objects.filter(realm=hamlet.realm).count(), 9)
|
self.assertEqual(UserGroup.objects.filter(realm=hamlet.realm).count(), 10)
|
||||||
self.assertEqual(UserGroupMembership.objects.count(), 47)
|
self.assertEqual(UserGroupMembership.objects.count(), 47)
|
||||||
result = self.client_delete(f"/json/user_groups/{user_group.id}")
|
result = self.client_delete(f"/json/user_groups/{user_group.id}")
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
self.assertEqual(UserGroup.objects.filter(realm=hamlet.realm).count(), 8)
|
self.assertEqual(UserGroup.objects.filter(realm=hamlet.realm).count(), 9)
|
||||||
self.assertEqual(UserGroupMembership.objects.count(), 46)
|
self.assertEqual(UserGroupMembership.objects.count(), 46)
|
||||||
# Test when invalid user group is supplied
|
# Test when invalid user group is supplied
|
||||||
result = self.client_delete("/json/user_groups/1111")
|
result = self.client_delete("/json/user_groups/1111")
|
||||||
@@ -456,7 +463,7 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||||||
if error_msg is None:
|
if error_msg is None:
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
# One group already exists in the test database.
|
# One group already exists in the test database.
|
||||||
self.assert_length(UserGroup.objects.filter(realm=realm), 9)
|
self.assert_length(UserGroup.objects.filter(realm=realm), 10)
|
||||||
else:
|
else:
|
||||||
self.assert_json_error(result, error_msg)
|
self.assert_json_error(result, error_msg)
|
||||||
|
|
||||||
@@ -466,7 +473,7 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
|||||||
result = self.client_delete(f"/json/user_groups/{user_group.id}")
|
result = self.client_delete(f"/json/user_groups/{user_group.id}")
|
||||||
if error_msg is None:
|
if error_msg is None:
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
self.assert_length(UserGroup.objects.filter(realm=realm), 8)
|
self.assert_length(UserGroup.objects.filter(realm=realm), 9)
|
||||||
else:
|
else:
|
||||||
self.assert_json_error(result, error_msg)
|
self.assert_json_error(result, error_msg)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user