mirror of https://github.com/zulip/zulip.git
user_groups: Add support to set can_manage_group during creation.
This commit adds API support to set can_manage_group while creating a user group.
This commit is contained in:
parent
2505813359
commit
b0b36e884c
|
@ -25,6 +25,9 @@ format used by the Zulip server that they are interacting with.
|
||||||
* [`GET /events`](/api/get-events), [`POST /register`](/api/register-queue),
|
* [`GET /events`](/api/get-events), [`POST /register`](/api/register-queue),
|
||||||
[`GET /user_groups`](/api/get-user-groups): Add `can_manage_group` to
|
[`GET /user_groups`](/api/get-user-groups): Add `can_manage_group` to
|
||||||
user group objects.
|
user group objects.
|
||||||
|
* [`POST /user_groups/create`](/api/create-user-group): Added `can_manage_group`
|
||||||
|
parameter to support setting the user group whose members can manage the user
|
||||||
|
group.
|
||||||
|
|
||||||
**Feature level 282**
|
**Feature level 282**
|
||||||
|
|
||||||
|
|
|
@ -19544,6 +19544,22 @@ paths:
|
||||||
items:
|
items:
|
||||||
type: integer
|
type: integer
|
||||||
example: [1, 2, 3, 4]
|
example: [1, 2, 3, 4]
|
||||||
|
can_manage_group:
|
||||||
|
allOf:
|
||||||
|
- description: |
|
||||||
|
A [group-setting value][setting-values] defining the set of users who
|
||||||
|
have permission to [manage this user group][manage-user-groups].
|
||||||
|
|
||||||
|
This setting cannot be set to `"role:internet"` and `"role:everyone"`
|
||||||
|
[system groups][system-groups].
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 10.0 (feature level 283).
|
||||||
|
|
||||||
|
[setting-values]: /api/group-setting-values
|
||||||
|
[system-groups]: /api/group-setting-values#system-groups
|
||||||
|
[manage-user-groups]: /help/manage-user-groups
|
||||||
|
- $ref: "#/components/schemas/GroupSettingValue"
|
||||||
|
example: 11
|
||||||
can_mention_group:
|
can_mention_group:
|
||||||
allOf:
|
allOf:
|
||||||
- description: |
|
- description: |
|
||||||
|
@ -19574,6 +19590,8 @@ paths:
|
||||||
encoding:
|
encoding:
|
||||||
members:
|
members:
|
||||||
contentType: application/json
|
contentType: application/json
|
||||||
|
can_manage_group:
|
||||||
|
contentType: application/json
|
||||||
can_mention_group:
|
can_mention_group:
|
||||||
contentType: application/json
|
contentType: application/json
|
||||||
responses:
|
responses:
|
||||||
|
|
|
@ -443,9 +443,15 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
self.assert_json_error(result, "User group name cannot start with 'channel:'.")
|
self.assert_json_error(result, "User group name cannot start with 'channel:'.")
|
||||||
self.assert_length(NamedUserGroup.objects.filter(realm=hamlet.realm), 10)
|
self.assert_length(NamedUserGroup.objects.filter(realm=hamlet.realm), 10)
|
||||||
|
|
||||||
def test_can_mention_group_setting_during_user_group_creation(self) -> None:
|
def do_test_set_group_setting_during_user_group_creation(self, setting_name: str) -> None:
|
||||||
self.login("hamlet")
|
self.login("hamlet")
|
||||||
hamlet = self.example_user("hamlet")
|
hamlet = self.example_user("hamlet")
|
||||||
|
# Delete all existing user groups except the hamletcharacters group
|
||||||
|
NamedUserGroup.objects.exclude(name="hamletcharacters").filter(
|
||||||
|
is_system_group=False
|
||||||
|
).delete()
|
||||||
|
|
||||||
|
permission_configuration = NamedUserGroup.GROUP_PERMISSION_SETTINGS[setting_name]
|
||||||
leadership_group = check_add_user_group(
|
leadership_group = check_add_user_group(
|
||||||
hamlet.realm, "leadership", [hamlet], acting_user=None
|
hamlet.realm, "leadership", [hamlet], acting_user=None
|
||||||
)
|
)
|
||||||
|
@ -456,23 +462,23 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
"name": "support",
|
"name": "support",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Support team",
|
"description": "Support team",
|
||||||
"can_mention_group": orjson.dumps(moderators_group.id).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(moderators_group.id).decode()
|
||||||
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)
|
||||||
support_group = NamedUserGroup.objects.get(name="support", realm=hamlet.realm)
|
support_group = NamedUserGroup.objects.get(name="support", realm=hamlet.realm)
|
||||||
self.assertEqual(support_group.can_mention_group, moderators_group.usergroup_ptr)
|
self.assertEqual(getattr(support_group, setting_name), moderators_group.usergroup_ptr)
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
"name": "test",
|
"name": "test",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Test group",
|
"description": "Test group",
|
||||||
"can_mention_group": orjson.dumps(leadership_group.id).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(leadership_group.id).decode()
|
||||||
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 = NamedUserGroup.objects.get(name="test", realm=hamlet.realm)
|
test_group = NamedUserGroup.objects.get(name="test", realm=hamlet.realm)
|
||||||
self.assertEqual(test_group.can_mention_group, leadership_group.usergroup_ptr)
|
self.assertEqual(getattr(test_group, setting_name), leadership_group.usergroup_ptr)
|
||||||
|
|
||||||
nobody_group = NamedUserGroup.objects.get(
|
nobody_group = NamedUserGroup.objects.get(
|
||||||
name="role:nobody", realm=hamlet.realm, is_system_group=True
|
name="role:nobody", realm=hamlet.realm, is_system_group=True
|
||||||
|
@ -481,34 +487,34 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
"name": "marketing",
|
"name": "marketing",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Marketing team",
|
"description": "Marketing team",
|
||||||
"can_mention_group": orjson.dumps(nobody_group.id).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(nobody_group.id).decode()
|
||||||
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)
|
||||||
marketing_group = NamedUserGroup.objects.get(name="marketing", realm=hamlet.realm)
|
marketing_group = NamedUserGroup.objects.get(name="marketing", realm=hamlet.realm)
|
||||||
self.assertEqual(marketing_group.can_mention_group, nobody_group.usergroup_ptr)
|
self.assertEqual(getattr(marketing_group, setting_name), nobody_group.usergroup_ptr)
|
||||||
|
|
||||||
othello = self.example_user("othello")
|
othello = self.example_user("othello")
|
||||||
params = {
|
params = {
|
||||||
"name": "backend",
|
"name": "backend",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Backend team",
|
"description": "Backend team",
|
||||||
"can_mention_group": orjson.dumps(
|
|
||||||
{
|
|
||||||
"direct_members": [othello.id],
|
|
||||||
"direct_subgroups": [leadership_group.id, moderators_group.id],
|
|
||||||
}
|
|
||||||
).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(
|
||||||
|
{
|
||||||
|
"direct_members": [othello.id],
|
||||||
|
"direct_subgroups": [leadership_group.id, moderators_group.id],
|
||||||
|
}
|
||||||
|
).decode()
|
||||||
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)
|
||||||
backend_group = NamedUserGroup.objects.get(name="backend", realm=hamlet.realm)
|
backend_group = NamedUserGroup.objects.get(name="backend", realm=hamlet.realm)
|
||||||
self.assertCountEqual(
|
self.assertCountEqual(
|
||||||
list(backend_group.can_mention_group.direct_members.all()),
|
list(getattr(backend_group, setting_name).direct_members.all()),
|
||||||
[othello],
|
[othello],
|
||||||
)
|
)
|
||||||
self.assertCountEqual(
|
self.assertCountEqual(
|
||||||
list(backend_group.can_mention_group.direct_subgroups.all()),
|
list(getattr(backend_group, setting_name).direct_subgroups.all()),
|
||||||
[leadership_group, moderators_group],
|
[leadership_group, moderators_group],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -516,18 +522,18 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
"name": "help",
|
"name": "help",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Troubleshooting team",
|
"description": "Troubleshooting team",
|
||||||
"can_mention_group": orjson.dumps(
|
|
||||||
{
|
|
||||||
"direct_members": [],
|
|
||||||
"direct_subgroups": [moderators_group.id],
|
|
||||||
}
|
|
||||||
).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(
|
||||||
|
{
|
||||||
|
"direct_members": [],
|
||||||
|
"direct_subgroups": [moderators_group.id],
|
||||||
|
}
|
||||||
|
).decode()
|
||||||
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)
|
||||||
help_group = NamedUserGroup.objects.get(name="help", realm=hamlet.realm)
|
help_group = NamedUserGroup.objects.get(name="help", realm=hamlet.realm)
|
||||||
# We do not create a new UserGroup object in such case.
|
# We do not create a new UserGroup object in such case.
|
||||||
self.assertEqual(help_group.can_mention_group_id, moderators_group.id)
|
self.assertEqual(getattr(help_group, setting_name).id, moderators_group.id)
|
||||||
|
|
||||||
internet_group = NamedUserGroup.objects.get(
|
internet_group = NamedUserGroup.objects.get(
|
||||||
name="role:internet", realm=hamlet.realm, is_system_group=True
|
name="role:internet", realm=hamlet.realm, is_system_group=True
|
||||||
|
@ -536,33 +542,39 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Frontend team",
|
"description": "Frontend team",
|
||||||
"can_mention_group": orjson.dumps(internet_group.id).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(internet_group.id).decode()
|
||||||
result = self.client_post("/json/user_groups/create", info=params)
|
result = self.client_post("/json/user_groups/create", info=params)
|
||||||
self.assert_json_error(
|
self.assert_json_error(
|
||||||
result, "'can_mention_group' setting cannot be set to 'role:internet' group."
|
result, f"'{setting_name}' setting cannot be set to 'role:internet' group."
|
||||||
)
|
)
|
||||||
|
|
||||||
owners_group = NamedUserGroup.objects.get(
|
owners_group = NamedUserGroup.objects.get(
|
||||||
name="role:owners", realm=hamlet.realm, is_system_group=True
|
name="role:owners", realm=hamlet.realm, is_system_group=True
|
||||||
)
|
)
|
||||||
params = {
|
params = {
|
||||||
"name": "frontend",
|
"name": "frontend-team",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Frontend team",
|
"description": "Frontend team",
|
||||||
"can_mention_group": orjson.dumps(owners_group.id).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(owners_group.id).decode()
|
||||||
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, "'can_mention_group' setting cannot be set to 'role:owners' group."
|
if not permission_configuration.allow_owners_group:
|
||||||
)
|
self.assert_json_error(
|
||||||
|
result, f"'{setting_name}' setting cannot be set to 'role:owners' group."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.assert_json_success(result)
|
||||||
|
frontend_group = NamedUserGroup.objects.get(name="frontend-team", realm=hamlet.realm)
|
||||||
|
self.assertEqual(getattr(frontend_group, setting_name), owners_group.usergroup_ptr)
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Frontend team",
|
"description": "Frontend team",
|
||||||
"can_mention_group": orjson.dumps(1111).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(1111).decode()
|
||||||
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 group")
|
self.assert_json_error(result, "Invalid user group")
|
||||||
|
|
||||||
|
@ -570,13 +582,13 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Frontend team",
|
"description": "Frontend team",
|
||||||
"can_mention_group": orjson.dumps(
|
|
||||||
{
|
|
||||||
"direct_members": [1111],
|
|
||||||
"direct_subgroups": [leadership_group.id, moderators_group.id],
|
|
||||||
}
|
|
||||||
).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(
|
||||||
|
{
|
||||||
|
"direct_members": [1111],
|
||||||
|
"direct_subgroups": [leadership_group.id, moderators_group.id],
|
||||||
|
}
|
||||||
|
).decode()
|
||||||
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")
|
||||||
|
|
||||||
|
@ -584,13 +596,13 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Frontend team",
|
"description": "Frontend team",
|
||||||
"can_mention_group": orjson.dumps(
|
|
||||||
{
|
|
||||||
"direct_members": [othello.id],
|
|
||||||
"direct_subgroups": [1111, moderators_group.id],
|
|
||||||
}
|
|
||||||
).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(
|
||||||
|
{
|
||||||
|
"direct_members": [othello.id],
|
||||||
|
"direct_subgroups": [1111, moderators_group.id],
|
||||||
|
}
|
||||||
|
).decode()
|
||||||
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 group ID: 1111")
|
self.assert_json_error(result, "Invalid user group ID: 1111")
|
||||||
|
|
||||||
|
@ -599,42 +611,49 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Frontend team",
|
"description": "Frontend team",
|
||||||
"can_mention_group": orjson.dumps(
|
|
||||||
{
|
|
||||||
"direct_members": [othello.id],
|
|
||||||
"direct_subgroups": [moderators_group.id],
|
|
||||||
}
|
|
||||||
).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(
|
||||||
|
{
|
||||||
|
"direct_members": [othello.id],
|
||||||
|
"direct_subgroups": [moderators_group.id],
|
||||||
|
}
|
||||||
|
).decode()
|
||||||
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, "'can_mention_group' must be a system user group.")
|
self.assert_json_error(result, f"'{setting_name}' must be a system user group.")
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Frontend team",
|
"description": "Frontend team",
|
||||||
"can_mention_group": orjson.dumps(
|
|
||||||
{
|
|
||||||
"direct_members": [],
|
|
||||||
"direct_subgroups": [moderators_group.id],
|
|
||||||
}
|
|
||||||
).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(
|
||||||
|
{
|
||||||
|
"direct_members": [],
|
||||||
|
"direct_subgroups": [moderators_group.id],
|
||||||
|
}
|
||||||
|
).decode()
|
||||||
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)
|
||||||
frontend_group = NamedUserGroup.objects.get(name="frontend", realm=hamlet.realm)
|
frontend_group = NamedUserGroup.objects.get(name="frontend", realm=hamlet.realm)
|
||||||
self.assertEqual(frontend_group.can_mention_group_id, moderators_group.id)
|
self.assertEqual(getattr(frontend_group, setting_name).id, moderators_group.id)
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
"name": "devops",
|
"name": "devops",
|
||||||
"members": orjson.dumps([hamlet.id]).decode(),
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
"description": "Devops team",
|
"description": "Devops team",
|
||||||
"can_mention_group": orjson.dumps(leadership_group.id).decode(),
|
|
||||||
}
|
}
|
||||||
|
params[setting_name] = orjson.dumps(leadership_group.id).decode()
|
||||||
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)
|
if setting_name == "can_mention_group":
|
||||||
devops_group = NamedUserGroup.objects.get(name="devops", realm=hamlet.realm)
|
self.assert_json_success(result)
|
||||||
self.assertEqual(devops_group.can_mention_group_id, leadership_group.id)
|
devops_group = NamedUserGroup.objects.get(name="devops", realm=hamlet.realm)
|
||||||
|
self.assertEqual(getattr(devops_group, setting_name).id, leadership_group.id)
|
||||||
|
else:
|
||||||
|
self.assert_json_error(result, f"'{setting_name}' must be a system user group.")
|
||||||
|
|
||||||
|
def test_set_group_settings_during_user_group_creation(self) -> None:
|
||||||
|
for setting_name in NamedUserGroup.GROUP_PERMISSION_SETTINGS:
|
||||||
|
self.do_test_set_group_setting_during_user_group_creation(setting_name)
|
||||||
|
|
||||||
def test_user_group_get(self) -> None:
|
def test_user_group_get(self) -> None:
|
||||||
# Test success
|
# Test success
|
||||||
|
|
|
@ -55,6 +55,7 @@ def add_user_group(
|
||||||
name: str,
|
name: str,
|
||||||
members: Json[list[int]],
|
members: Json[list[int]],
|
||||||
description: str,
|
description: str,
|
||||||
|
can_manage_group: Json[int | AnonymousSettingGroupDict] | None = None,
|
||||||
can_mention_group: Json[int | AnonymousSettingGroupDict] | None = None,
|
can_mention_group: Json[int | AnonymousSettingGroupDict] | None = None,
|
||||||
) -> HttpResponse:
|
) -> HttpResponse:
|
||||||
user_profiles = user_ids_to_users(members, user_profile.realm)
|
user_profiles = user_ids_to_users(members, user_profile.realm)
|
||||||
|
|
Loading…
Reference in New Issue