mirror of https://github.com/zulip/zulip.git
actions: Add function to add and remove subgroups from a user group.
This commit is contained in:
parent
da0b087962
commit
b4a9311ef2
|
@ -26,6 +26,9 @@ format used by the Zulip server that they are interacting with.
|
||||||
/register`](/api/register-queue): Added `subgroups` field,
|
/register`](/api/register-queue): Added `subgroups` field,
|
||||||
which is a list of IDs of all the subgroups of the user group, to
|
which is a list of IDs of all the subgroups of the user group, to
|
||||||
user group objects.
|
user group objects.
|
||||||
|
* [`GET /events`](/api/get-events): Added new `user_group` events
|
||||||
|
operations for live updates to subgroups (`add_subgroups` and
|
||||||
|
`remove_subgroups`).
|
||||||
|
|
||||||
**Feature level 126**
|
**Feature level 126**
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,14 @@ from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from zerver.lib.exceptions import JsonableError
|
from zerver.lib.exceptions import JsonableError
|
||||||
from zerver.lib.user_groups import access_user_group_by_id, create_user_group
|
from zerver.lib.user_groups import access_user_group_by_id, create_user_group
|
||||||
from zerver.models import Realm, UserGroup, UserGroupMembership, UserProfile, active_user_ids
|
from zerver.models import (
|
||||||
|
GroupGroupMembership,
|
||||||
|
Realm,
|
||||||
|
UserGroup,
|
||||||
|
UserGroupMembership,
|
||||||
|
UserProfile,
|
||||||
|
active_user_ids,
|
||||||
|
)
|
||||||
from zerver.tornado.django_api import send_event
|
from zerver.tornado.django_api import send_event
|
||||||
|
|
||||||
|
|
||||||
|
@ -158,6 +165,36 @@ def remove_members_from_user_group(user_group: UserGroup, user_profile_ids: List
|
||||||
do_send_user_group_members_update_event("remove_members", user_group, user_profile_ids)
|
do_send_user_group_members_update_event("remove_members", user_group, user_profile_ids)
|
||||||
|
|
||||||
|
|
||||||
|
def do_send_subgroups_update_event(
|
||||||
|
event_name: str, user_group: UserGroup, subgroup_ids: List[int]
|
||||||
|
) -> None:
|
||||||
|
event = dict(
|
||||||
|
type="user_group", op=event_name, group_id=user_group.id, subgroup_ids=subgroup_ids
|
||||||
|
)
|
||||||
|
transaction.on_commit(
|
||||||
|
lambda: send_event(user_group.realm, event, active_user_ids(user_group.realm_id))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def add_subgroups_to_user_group(user_group: UserGroup, subgroups: List[UserGroup]) -> None:
|
||||||
|
group_memberships = [
|
||||||
|
GroupGroupMembership(supergroup=user_group, subgroup=subgroup) for subgroup in subgroups
|
||||||
|
]
|
||||||
|
GroupGroupMembership.objects.bulk_create(group_memberships)
|
||||||
|
|
||||||
|
subgroup_ids = [subgroup.id for subgroup in subgroups]
|
||||||
|
do_send_subgroups_update_event("add_subgroups", user_group, subgroup_ids)
|
||||||
|
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def remove_subgroups_from_user_group(user_group: UserGroup, subgroups: List[UserGroup]) -> None:
|
||||||
|
GroupGroupMembership.objects.filter(supergroup=user_group, subgroup__in=subgroups).delete()
|
||||||
|
|
||||||
|
subgroup_ids = [subgroup.id for subgroup in subgroups]
|
||||||
|
do_send_subgroups_update_event("remove_subgroups", user_group, subgroup_ids)
|
||||||
|
|
||||||
|
|
||||||
def do_send_delete_user_group_event(realm: Realm, user_group_id: int, realm_id: int) -> None:
|
def do_send_delete_user_group_event(realm: Realm, user_group_id: int, realm_id: int) -> None:
|
||||||
event = dict(type="user_group", op="remove", group_id=user_group_id)
|
event = dict(type="user_group", op="remove", group_id=user_group_id)
|
||||||
send_event(realm, event, active_user_ids(realm_id))
|
send_event(realm, event, active_user_ids(realm_id))
|
||||||
|
|
|
@ -1748,6 +1748,28 @@ def check_user_group_update(var_name: str, event: Dict[str, object], field: str)
|
||||||
assert set(event["data"].keys()) == {field}
|
assert set(event["data"].keys()) == {field}
|
||||||
|
|
||||||
|
|
||||||
|
user_group_add_subgroups_event = event_dict_type(
|
||||||
|
required_keys=[
|
||||||
|
("type", Equals("user_group")),
|
||||||
|
("op", Equals("add_subgroups")),
|
||||||
|
("group_id", int),
|
||||||
|
("subgroup_ids", ListType(int)),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
check_user_group_add_subgroups = make_checker(user_group_add_subgroups_event)
|
||||||
|
|
||||||
|
|
||||||
|
user_group_remove_subgroups_event = event_dict_type(
|
||||||
|
required_keys=[
|
||||||
|
("type", Equals("user_group")),
|
||||||
|
("op", Equals("remove_subgroups")),
|
||||||
|
("group_id", int),
|
||||||
|
("subgroup_ids", ListType(int)),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
check_user_group_remove_subgroups = make_checker(user_group_remove_subgroups_event)
|
||||||
|
|
||||||
|
|
||||||
user_status_event = event_dict_type(
|
user_status_event = event_dict_type(
|
||||||
required_keys=[
|
required_keys=[
|
||||||
# force vertical
|
# force vertical
|
||||||
|
|
|
@ -1245,6 +1245,17 @@ def apply_event(
|
||||||
members = set(user_group["members"])
|
members = set(user_group["members"])
|
||||||
user_group["members"] = list(members - set(event["user_ids"]))
|
user_group["members"] = list(members - set(event["user_ids"]))
|
||||||
user_group["members"].sort()
|
user_group["members"].sort()
|
||||||
|
elif event["op"] == "add_subgroups":
|
||||||
|
for user_group in state["realm_user_groups"]:
|
||||||
|
if user_group["id"] == event["group_id"]:
|
||||||
|
user_group["subgroups"].extend(event["subgroup_ids"])
|
||||||
|
user_group["subgroups"].sort()
|
||||||
|
elif event["op"] == "remove_subgroups":
|
||||||
|
for user_group in state["realm_user_groups"]:
|
||||||
|
if user_group["id"] == event["group_id"]:
|
||||||
|
subgroups = set(user_group["subgroups"])
|
||||||
|
user_group["subgroups"] = list(subgroups - set(event["subgroup_ids"]))
|
||||||
|
user_group["subgroups"].sort()
|
||||||
elif event["op"] == "remove":
|
elif event["op"] == "remove":
|
||||||
state["realm_user_groups"] = [
|
state["realm_user_groups"] = [
|
||||||
ug for ug in state["realm_user_groups"] if ug["id"] != event["group_id"]
|
ug for ug in state["realm_user_groups"] if ug["id"] != event["group_id"]
|
||||||
|
|
|
@ -2830,6 +2830,82 @@ paths:
|
||||||
"user_ids": [10],
|
"user_ids": [10],
|
||||||
"id": 0,
|
"id": 0,
|
||||||
}
|
}
|
||||||
|
- type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: |
|
||||||
|
Event sent to all users when subgroups have been added to
|
||||||
|
a user group.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 6.0 (feature level 127).
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
$ref: "#/components/schemas/EventIdSchema"
|
||||||
|
type:
|
||||||
|
allOf:
|
||||||
|
- $ref: "#/components/schemas/EventTypeSchema"
|
||||||
|
- enum:
|
||||||
|
- user_group
|
||||||
|
op:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- add_subgroups
|
||||||
|
group_id:
|
||||||
|
type: integer
|
||||||
|
description: |
|
||||||
|
The ID of the user group whose details have changed.
|
||||||
|
subgroup_ids:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
description: |
|
||||||
|
Array containing the IDs of the subgroups that have been added
|
||||||
|
to the user group.
|
||||||
|
example:
|
||||||
|
{
|
||||||
|
"type": "user_group",
|
||||||
|
"op": "add_subgroups",
|
||||||
|
"group_id": 2,
|
||||||
|
"subgroup_ids": [10],
|
||||||
|
"id": 0,
|
||||||
|
}
|
||||||
|
- type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: |
|
||||||
|
Event sent to all users when subgroups have been removed from
|
||||||
|
a user group.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 6.0 (feature level 127).
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
$ref: "#/components/schemas/EventIdSchema"
|
||||||
|
type:
|
||||||
|
allOf:
|
||||||
|
- $ref: "#/components/schemas/EventTypeSchema"
|
||||||
|
- enum:
|
||||||
|
- user_group
|
||||||
|
op:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- remove_subgroups
|
||||||
|
group_id:
|
||||||
|
type: integer
|
||||||
|
description: |
|
||||||
|
The ID of the user group whose details have changed.
|
||||||
|
subgroup_ids:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
description: |
|
||||||
|
Array containing the IDs of the subgroups that have been
|
||||||
|
removed from the user group.
|
||||||
|
example:
|
||||||
|
{
|
||||||
|
"type": "user_group",
|
||||||
|
"op": "remove_subgroups",
|
||||||
|
"group_id": 2,
|
||||||
|
"subgroup_ids": [10],
|
||||||
|
"id": 0,
|
||||||
|
}
|
||||||
- type: object
|
- type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
description: |
|
description: |
|
||||||
|
|
|
@ -92,12 +92,14 @@ from zerver.actions.streams import (
|
||||||
from zerver.actions.submessage import do_add_submessage
|
from zerver.actions.submessage import do_add_submessage
|
||||||
from zerver.actions.typing import check_send_typing_notification, do_send_stream_typing_notification
|
from zerver.actions.typing import check_send_typing_notification, do_send_stream_typing_notification
|
||||||
from zerver.actions.user_groups import (
|
from zerver.actions.user_groups import (
|
||||||
|
add_subgroups_to_user_group,
|
||||||
bulk_add_members_to_user_group,
|
bulk_add_members_to_user_group,
|
||||||
check_add_user_group,
|
check_add_user_group,
|
||||||
check_delete_user_group,
|
check_delete_user_group,
|
||||||
do_update_user_group_description,
|
do_update_user_group_description,
|
||||||
do_update_user_group_name,
|
do_update_user_group_name,
|
||||||
remove_members_from_user_group,
|
remove_members_from_user_group,
|
||||||
|
remove_subgroups_from_user_group,
|
||||||
)
|
)
|
||||||
from zerver.actions.user_settings import (
|
from zerver.actions.user_settings import (
|
||||||
do_change_avatar_fields,
|
do_change_avatar_fields,
|
||||||
|
@ -171,8 +173,10 @@ from zerver.lib.event_schema import (
|
||||||
check_update_message_flags_remove,
|
check_update_message_flags_remove,
|
||||||
check_user_group_add,
|
check_user_group_add,
|
||||||
check_user_group_add_members,
|
check_user_group_add_members,
|
||||||
|
check_user_group_add_subgroups,
|
||||||
check_user_group_remove,
|
check_user_group_remove,
|
||||||
check_user_group_remove_members,
|
check_user_group_remove_members,
|
||||||
|
check_user_group_remove_subgroups,
|
||||||
check_user_group_update,
|
check_user_group_update,
|
||||||
check_user_settings_update,
|
check_user_settings_update,
|
||||||
check_user_status,
|
check_user_status,
|
||||||
|
@ -194,6 +198,7 @@ from zerver.lib.test_helpers import (
|
||||||
stdout_suppressed,
|
stdout_suppressed,
|
||||||
)
|
)
|
||||||
from zerver.lib.topic import TOPIC_NAME
|
from zerver.lib.topic import TOPIC_NAME
|
||||||
|
from zerver.lib.user_groups import create_user_group
|
||||||
from zerver.lib.user_mutes import get_mute_object
|
from zerver.lib.user_mutes import get_mute_object
|
||||||
from zerver.models import (
|
from zerver.models import (
|
||||||
Attachment,
|
Attachment,
|
||||||
|
@ -1225,6 +1230,18 @@ class NormalActionsTest(BaseAction):
|
||||||
events = self.verify_action(lambda: remove_members_from_user_group(backend, [hamlet.id]))
|
events = self.verify_action(lambda: remove_members_from_user_group(backend, [hamlet.id]))
|
||||||
check_user_group_remove_members("events[0]", events[0])
|
check_user_group_remove_members("events[0]", events[0])
|
||||||
|
|
||||||
|
api_design = create_user_group(
|
||||||
|
"api-design", [hamlet], hamlet.realm, description="API design team"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test add subgroups
|
||||||
|
events = self.verify_action(lambda: add_subgroups_to_user_group(backend, [api_design]))
|
||||||
|
check_user_group_add_subgroups("events[0]", events[0])
|
||||||
|
|
||||||
|
# Test remove subgroups
|
||||||
|
events = self.verify_action(lambda: remove_subgroups_from_user_group(backend, [api_design]))
|
||||||
|
check_user_group_remove_subgroups("events[0]", events[0])
|
||||||
|
|
||||||
# Test remove event
|
# Test remove event
|
||||||
events = self.verify_action(lambda: check_delete_user_group(backend.id, othello))
|
events = self.verify_action(lambda: check_delete_user_group(backend.id, othello))
|
||||||
check_user_group_remove("events[0]", events[0])
|
check_user_group_remove("events[0]", events[0])
|
||||||
|
|
Loading…
Reference in New Issue