streams: Backend changes to support anonymous groups.

can_remove_subscribers_group setting can now be set to
anonymous user groups.

Co-authored-by: Sahil Batra <sahil@zulip.com>
This commit is contained in:
Shubham Padia
2024-10-24 19:50:49 +00:00
committed by Tim Abbott
parent 005a27a9cf
commit b6ebf143cc
14 changed files with 458 additions and 133 deletions

View File

@@ -21,10 +21,14 @@ from zerver.lib.stream_subscription import (
from zerver.lib.stream_traffic import get_average_weekly_stream_traffic, get_streams_traffic
from zerver.lib.string_validation import check_stream_name
from zerver.lib.timestamp import datetime_to_timestamp
from zerver.lib.types import APIStreamDict
from zerver.lib.user_groups import user_has_permission_for_group_setting
from zerver.lib.types import AnonymousSettingGroupDict, APIStreamDict
from zerver.lib.user_groups import (
get_group_setting_value_for_api,
user_has_permission_for_group_setting,
)
from zerver.models import (
DefaultStreamGroup,
GroupGroupMembership,
NamedUserGroup,
Realm,
RealmAuditLog,
@@ -32,6 +36,7 @@ from zerver.models import (
Stream,
Subscription,
UserGroup,
UserGroupMembership,
UserProfile,
)
from zerver.models.groups import SystemGroups
@@ -123,8 +128,13 @@ def send_stream_creation_event(
stream: Stream,
user_ids: list[int],
recent_traffic: dict[int, int] | None = None,
setting_groups_dict: dict[int, int | AnonymousSettingGroupDict] | None = None,
) -> None:
event = dict(type="stream", op="create", streams=[stream_to_dict(stream, recent_traffic)])
event = dict(
type="stream",
op="create",
streams=[stream_to_dict(stream, recent_traffic, setting_groups_dict)],
)
send_event_on_commit(realm, event, user_ids)
@@ -870,7 +880,11 @@ def get_occupied_streams(realm: Realm) -> QuerySet[Stream]:
return occupied_streams
def stream_to_dict(stream: Stream, recent_traffic: dict[int, int] | None = None) -> APIStreamDict:
def stream_to_dict(
stream: Stream,
recent_traffic: dict[int, int] | None = None,
setting_groups_dict: dict[int, int | AnonymousSettingGroupDict] | None = None,
) -> APIStreamDict:
if recent_traffic is not None:
stream_weekly_traffic = get_average_weekly_stream_traffic(
stream.id, stream.date_created, recent_traffic
@@ -884,9 +898,16 @@ def stream_to_dict(stream: Stream, recent_traffic: dict[int, int] | None = None)
# passing stream data to spectators.
stream_weekly_traffic = None
if setting_groups_dict is not None:
can_remove_subscribers_group = setting_groups_dict[stream.can_remove_subscribers_group_id]
else:
can_remove_subscribers_group = get_group_setting_value_for_api(
stream.can_remove_subscribers_group
)
return APIStreamDict(
is_archived=stream.deactivated,
can_remove_subscribers_group=stream.can_remove_subscribers_group_id,
can_remove_subscribers_group=can_remove_subscribers_group,
creator_id=stream.creator_id,
date_created=datetime_to_timestamp(stream.date_created),
description=stream.description,
@@ -978,6 +999,38 @@ def get_streams_for_user(
return list(streams)
def get_setting_values_for_group_settings(
group_ids: list[int],
) -> dict[int, int | AnonymousSettingGroupDict]:
setting_value_dict = {}
setting_groups = UserGroup.objects.filter(id__in=group_ids).select_related("named_user_group")
anonymous_groups = []
for group in setting_groups:
if hasattr(group, "named_user_group"):
setting_value_dict[group.id] = group.id
else:
setting_value_dict[group.id] = AnonymousSettingGroupDict(
direct_members=[],
direct_subgroups=[],
)
anonymous_groups.append(group.id)
group_members = (
UserGroupMembership.objects.filter(user_group_id__in=anonymous_groups)
.exclude(user_profile__is_active=False)
.values_list("user_group_id", "user_profile_id")
)
group_subgroups = GroupGroupMembership.objects.filter(
supergroup_id__in=anonymous_groups
).values_list("supergroup_id", "subgroup_id")
for user_group_id, user_profile_id in group_members:
setting_value_dict[user_group_id].direct_members.append(user_profile_id)
for supergroup_id, subgroup_id in group_subgroups:
setting_value_dict[supergroup_id].direct_subgroups.append(subgroup_id)
return setting_value_dict
def do_get_streams(
user_profile: UserProfile,
include_public: bool = True,
@@ -1003,14 +1056,22 @@ def do_get_streams(
stream_ids = {stream.id for stream in streams}
recent_traffic = get_streams_traffic(stream_ids, user_profile.realm)
setting_group_ids = set()
for stream in streams:
for setting_name in Stream.stream_permission_group_settings:
setting_group_ids.add(getattr(stream, setting_name + "_id"))
setting_groups_dict = get_setting_values_for_group_settings(list(setting_group_ids))
stream_dicts = sorted(
(stream_to_dict(stream, recent_traffic) for stream in streams), key=lambda elt: elt["name"]
(stream_to_dict(stream, recent_traffic, setting_groups_dict) for stream in streams),
key=lambda elt: elt["name"],
)
if include_default:
default_stream_ids = get_default_stream_ids_for_realm(user_profile.realm_id)
for stream in stream_dicts:
stream["is_default"] = stream["stream_id"] in default_stream_ids
for stream_dict in stream_dicts:
stream_dict["is_default"] = stream_dict["stream_id"] in default_stream_ids
return stream_dicts