mirror of https://github.com/zulip/zulip.git
user_groups: Add support to set can_mention_group during creation.
This commit adds API support to set can_mention_group while creating a user group. Fixes a part of #25927.
This commit is contained in:
parent
e6accb0ad9
commit
4bea6ffaa8
|
@ -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_mention_group_id` to
|
[`GET /user_groups`](/api/get-user-groups): Add `can_mention_group_id` to
|
||||||
user group objects.
|
user group objects.
|
||||||
|
* [`POST /user_groups/create`](/api/create-user-group): Added `can_mention_group_id`
|
||||||
|
parameter to support setting the user group whose members can mention the new user
|
||||||
|
group.
|
||||||
|
|
||||||
**Feature level 190**
|
**Feature level 190**
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import datetime
|
import datetime
|
||||||
from typing import Dict, List, Optional, Sequence, TypedDict
|
from typing import Dict, List, Mapping, Optional, Sequence, TypedDict
|
||||||
|
|
||||||
import django.db.utils
|
import django.db.utils
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
@ -37,14 +37,20 @@ def create_user_group_in_database(
|
||||||
*,
|
*,
|
||||||
acting_user: Optional[UserProfile],
|
acting_user: Optional[UserProfile],
|
||||||
description: str = "",
|
description: str = "",
|
||||||
|
group_settings_map: Mapping[str, UserGroup] = {},
|
||||||
is_system_group: bool = False,
|
is_system_group: bool = False,
|
||||||
) -> UserGroup:
|
) -> UserGroup:
|
||||||
user_group = UserGroup(
|
user_group = UserGroup(
|
||||||
name=name, realm=realm, description=description, is_system_group=is_system_group
|
name=name, realm=realm, description=description, is_system_group=is_system_group
|
||||||
)
|
)
|
||||||
system_groups_name_dict = get_role_based_system_groups_dict(realm)
|
|
||||||
user_group = set_defaults_for_group_settings(user_group, system_groups_name_dict)
|
|
||||||
|
|
||||||
|
for setting_name, setting_value in group_settings_map.items():
|
||||||
|
setattr(user_group, setting_name, setting_value)
|
||||||
|
|
||||||
|
system_groups_name_dict = get_role_based_system_groups_dict(realm)
|
||||||
|
user_group = set_defaults_for_group_settings(
|
||||||
|
user_group, group_settings_map, system_groups_name_dict
|
||||||
|
)
|
||||||
user_group.save()
|
user_group.save()
|
||||||
|
|
||||||
UserGroupMembership.objects.bulk_create(
|
UserGroupMembership.objects.bulk_create(
|
||||||
|
@ -150,12 +156,18 @@ def check_add_user_group(
|
||||||
name: str,
|
name: str,
|
||||||
initial_members: List[UserProfile],
|
initial_members: List[UserProfile],
|
||||||
description: str = "",
|
description: str = "",
|
||||||
|
group_settings_map: Mapping[str, UserGroup] = {},
|
||||||
*,
|
*,
|
||||||
acting_user: Optional[UserProfile],
|
acting_user: Optional[UserProfile],
|
||||||
) -> UserGroup:
|
) -> UserGroup:
|
||||||
try:
|
try:
|
||||||
user_group = create_user_group_in_database(
|
user_group = create_user_group_in_database(
|
||||||
name, initial_members, realm, description=description, acting_user=acting_user
|
name,
|
||||||
|
initial_members,
|
||||||
|
realm,
|
||||||
|
description=description,
|
||||||
|
group_settings_map=group_settings_map,
|
||||||
|
acting_user=acting_user,
|
||||||
)
|
)
|
||||||
do_send_create_user_group_event(user_group, initial_members)
|
do_send_create_user_group_event(user_group, initial_members)
|
||||||
return user_group
|
return user_group
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Dict, Iterable, List, Sequence, TypedDict
|
from typing import Dict, Iterable, List, Mapping, Sequence, TypedDict
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import F, QuerySet
|
from django.db.models import F, QuerySet
|
||||||
|
@ -239,9 +239,15 @@ 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: UserGroup,
|
||||||
|
group_settings_map: Mapping[str, UserGroup],
|
||||||
system_groups_name_dict: Dict[str, UserGroup],
|
system_groups_name_dict: Dict[str, UserGroup],
|
||||||
) -> UserGroup:
|
) -> UserGroup:
|
||||||
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:
|
||||||
|
# We skip the settings for which a value is passed
|
||||||
|
# in user group creation API request.
|
||||||
|
continue
|
||||||
|
|
||||||
if user_group.is_system_group and permission_config.default_for_system_groups is not None:
|
if user_group.is_system_group and permission_config.default_for_system_groups is not None:
|
||||||
default_group_name = permission_config.default_for_system_groups
|
default_group_name = permission_config.default_for_system_groups
|
||||||
else:
|
else:
|
||||||
|
@ -315,7 +321,7 @@ 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)
|
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(group)
|
groups_with_updated_settings.append(group)
|
||||||
UserGroup.objects.bulk_update(groups_with_updated_settings, ["can_mention_group"])
|
UserGroup.objects.bulk_update(groups_with_updated_settings, ["can_mention_group"])
|
||||||
|
|
||||||
|
|
|
@ -16164,6 +16164,21 @@ paths:
|
||||||
type: integer
|
type: integer
|
||||||
example: [1, 2, 3, 4]
|
example: [1, 2, 3, 4]
|
||||||
required: true
|
required: true
|
||||||
|
- name: can_mention_group_id
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
ID of the user group whose members are allowed to mention the new
|
||||||
|
user group.
|
||||||
|
|
||||||
|
This setting cannot be set to `"@role:internet"` and `"@role:owners"`
|
||||||
|
system groups.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 8.0 (feature level 191). Previously, groups
|
||||||
|
could be mentioned if and only if they were not system groups.
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
example: 11
|
||||||
|
required: false
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
$ref: "#/components/responses/SimpleSuccess"
|
$ref: "#/components/responses/SimpleSuccess"
|
||||||
|
|
|
@ -267,6 +267,88 @@ class UserGroupAPITestCase(UserGroupTestCase):
|
||||||
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), 10)
|
self.assert_length(UserGroup.objects.filter(realm=hamlet.realm), 10)
|
||||||
|
|
||||||
|
def test_can_mention_group_setting_during_user_group_creation(self) -> None:
|
||||||
|
self.login("hamlet")
|
||||||
|
hamlet = self.example_user("hamlet")
|
||||||
|
leadership_group = check_add_user_group(
|
||||||
|
hamlet.realm, "leadership", [hamlet], acting_user=None
|
||||||
|
)
|
||||||
|
moderators_group = UserGroup.objects.get(
|
||||||
|
name="@role:moderators", realm=hamlet.realm, is_system_group=True
|
||||||
|
)
|
||||||
|
params = {
|
||||||
|
"name": "support",
|
||||||
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
|
"description": "Support team",
|
||||||
|
"can_mention_group_id": orjson.dumps(moderators_group.id).decode(),
|
||||||
|
}
|
||||||
|
result = self.client_post("/json/user_groups/create", info=params)
|
||||||
|
self.assert_json_success(result)
|
||||||
|
support_group = UserGroup.objects.get(name="support", realm=hamlet.realm)
|
||||||
|
self.assertEqual(support_group.can_mention_group, moderators_group)
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"name": "test",
|
||||||
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
|
"description": "Test group",
|
||||||
|
"can_mention_group_id": orjson.dumps(leadership_group.id).decode(),
|
||||||
|
}
|
||||||
|
result = self.client_post("/json/user_groups/create", info=params)
|
||||||
|
self.assert_json_success(result)
|
||||||
|
test_group = UserGroup.objects.get(name="test", realm=hamlet.realm)
|
||||||
|
self.assertEqual(test_group.can_mention_group, leadership_group)
|
||||||
|
|
||||||
|
nobody_group = UserGroup.objects.get(
|
||||||
|
name="@role:nobody", realm=hamlet.realm, is_system_group=True
|
||||||
|
)
|
||||||
|
params = {
|
||||||
|
"name": "marketing",
|
||||||
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
|
"description": "Marketing team",
|
||||||
|
"can_mention_group_id": orjson.dumps(nobody_group.id).decode(),
|
||||||
|
}
|
||||||
|
result = self.client_post("/json/user_groups/create", info=params)
|
||||||
|
self.assert_json_success(result)
|
||||||
|
marketing_group = UserGroup.objects.get(name="marketing", realm=hamlet.realm)
|
||||||
|
self.assertEqual(marketing_group.can_mention_group, nobody_group)
|
||||||
|
|
||||||
|
internet_group = UserGroup.objects.get(
|
||||||
|
name="@role:internet", realm=hamlet.realm, is_system_group=True
|
||||||
|
)
|
||||||
|
params = {
|
||||||
|
"name": "frontend",
|
||||||
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
|
"description": "Frontend team",
|
||||||
|
"can_mention_group_id": orjson.dumps(internet_group.id).decode(),
|
||||||
|
}
|
||||||
|
result = self.client_post("/json/user_groups/create", info=params)
|
||||||
|
self.assert_json_error(
|
||||||
|
result, "'can_mention_group' setting cannot be set to '@role:internet' group."
|
||||||
|
)
|
||||||
|
|
||||||
|
owners_group = UserGroup.objects.get(
|
||||||
|
name="@role:owners", realm=hamlet.realm, is_system_group=True
|
||||||
|
)
|
||||||
|
params = {
|
||||||
|
"name": "frontend",
|
||||||
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
|
"description": "Frontend team",
|
||||||
|
"can_mention_group_id": orjson.dumps(owners_group.id).decode(),
|
||||||
|
}
|
||||||
|
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."
|
||||||
|
)
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"name": "frontend",
|
||||||
|
"members": orjson.dumps([hamlet.id]).decode(),
|
||||||
|
"description": "Frontend team",
|
||||||
|
"can_mention_group_id": orjson.dumps(1111).decode(),
|
||||||
|
}
|
||||||
|
result = self.client_post("/json/user_groups/create", info=params)
|
||||||
|
self.assert_json_error(result, "Invalid user group")
|
||||||
|
|
||||||
def test_user_group_get(self) -> None:
|
def test_user_group_get(self) -> None:
|
||||||
# Test success
|
# Test success
|
||||||
user_profile = self.example_user("hamlet")
|
user_profile = self.example_user("hamlet")
|
||||||
|
|
|
@ -23,6 +23,7 @@ from zerver.lib.request import REQ, has_request_variables
|
||||||
from zerver.lib.response import json_success
|
from zerver.lib.response import json_success
|
||||||
from zerver.lib.user_groups import (
|
from zerver.lib.user_groups import (
|
||||||
access_user_group_by_id,
|
access_user_group_by_id,
|
||||||
|
access_user_group_for_setting,
|
||||||
access_user_groups_as_potential_subgroups,
|
access_user_groups_as_potential_subgroups,
|
||||||
get_direct_memberships_of_users,
|
get_direct_memberships_of_users,
|
||||||
get_recursive_subgroups_for_groups,
|
get_recursive_subgroups_for_groups,
|
||||||
|
@ -46,10 +47,38 @@ def add_user_group(
|
||||||
name: str = REQ(),
|
name: str = REQ(),
|
||||||
members: Sequence[int] = REQ(json_validator=check_list(check_int), default=[]),
|
members: Sequence[int] = REQ(json_validator=check_list(check_int), default=[]),
|
||||||
description: str = REQ(),
|
description: str = REQ(),
|
||||||
|
can_mention_group_id: Optional[int] = REQ(json_validator=check_int, default=None),
|
||||||
) -> HttpResponse:
|
) -> HttpResponse:
|
||||||
user_profiles = user_ids_to_users(members, user_profile.realm)
|
user_profiles = user_ids_to_users(members, user_profile.realm)
|
||||||
|
|
||||||
|
group_settings_map = {}
|
||||||
|
request_settings_dict = locals()
|
||||||
|
for setting_name, permission_config in UserGroup.GROUP_PERMISSION_SETTINGS.items():
|
||||||
|
setting_group_id_name = setting_name + "_id"
|
||||||
|
|
||||||
|
if setting_group_id_name not in request_settings_dict: # nocoverage
|
||||||
|
continue
|
||||||
|
|
||||||
|
if request_settings_dict[setting_group_id_name] is not None:
|
||||||
|
setting_value_group_id = request_settings_dict[setting_group_id_name]
|
||||||
|
setting_value_group = access_user_group_for_setting(
|
||||||
|
setting_value_group_id,
|
||||||
|
user_profile,
|
||||||
|
setting_name=setting_name,
|
||||||
|
require_system_group=permission_config.require_system_group,
|
||||||
|
allow_internet_group=permission_config.allow_internet_group,
|
||||||
|
allow_owners_group=permission_config.allow_owners_group,
|
||||||
|
allow_nobody_group=permission_config.allow_nobody_group,
|
||||||
|
)
|
||||||
|
group_settings_map[setting_name] = setting_value_group
|
||||||
|
|
||||||
check_add_user_group(
|
check_add_user_group(
|
||||||
user_profile.realm, name, user_profiles, description, acting_user=user_profile
|
user_profile.realm,
|
||||||
|
name,
|
||||||
|
user_profiles,
|
||||||
|
description,
|
||||||
|
group_settings_map=group_settings_map,
|
||||||
|
acting_user=user_profile,
|
||||||
)
|
)
|
||||||
return json_success(request)
|
return json_success(request)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue