From f4fcedd072b0c6faa5fc691828891b8d91bd16cb Mon Sep 17 00:00:00 2001 From: Sahil Batra Date: Tue, 7 Jun 2022 19:52:28 +0530 Subject: [PATCH] streams: Send stream creation event when changing stream to public. This commit adds code to send stream creation and peer add events when stream is changed from private to public. These events are only sent to users who are not susbcribed to the stream and are not realm admins as subscribers and realm admins already have the stream data. This will update the stream data with clients and will remove the need to reload to view the modified stream. Fixes #22194. --- zerver/actions/streams.py | 42 ++++++++++++++++++++++++++++++++++++- zerver/tests/test_events.py | 34 ++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/zerver/actions/streams.py b/zerver/actions/streams.py index c4d632ea9d..ef1df7efec 100644 --- a/zerver/actions/streams.py +++ b/zerver/actions/streams.py @@ -944,6 +944,43 @@ def do_change_stream_permission( ).decode(), ) + notify_stream_creation_ids = set() + if old_invite_only_value and not stream.invite_only: + # We need to send stream creation event to users who can access the + # stream now but were not able to do so previously. So, we can exclude + # subscribers, users who were previously subscribed to the stream and + # realm admins from the non-guest user list. + previously_subscribed_user_ids = Subscription.objects.filter( + recipient_id=stream.recipient_id, active=False, is_user_active=True + ).values_list("user_profile_id", flat=True) + stream_subscriber_user_ids = get_active_subscriptions_for_stream_id( + stream.id, include_deactivated_users=False + ).values_list("user_profile_id", flat=True) + + old_can_access_stream_user_ids = ( + set(stream_subscriber_user_ids) + | set(previously_subscribed_user_ids) + | {user.id for user in stream.realm.get_admin_users_and_bots()} + ) + non_guest_user_ids = set(active_non_guest_user_ids(stream.realm_id)) + notify_stream_creation_ids = non_guest_user_ids - old_can_access_stream_user_ids + send_stream_creation_event(stream, list(notify_stream_creation_ids)) + + # Add subscribers info to the stream object. We need to send peer_add + # events to users who were previously subscribed to the streams as + # they did not had subscribers data. + old_subscribers_access_user_ids = set(stream_subscriber_user_ids) | { + user.id for user in stream.realm.get_admin_users_and_bots() + } + peer_notify_user_ids = non_guest_user_ids - old_subscribers_access_user_ids + peer_add_event = dict( + type="subscription", + op="peer_add", + stream_ids=[stream.id], + user_ids=sorted(stream_subscriber_user_ids), + ) + send_event(stream.realm, peer_add_event, peer_notify_user_ids) + event = dict( op="update", type="stream", @@ -954,7 +991,10 @@ def do_change_stream_permission( stream_id=stream.id, name=stream.name, ) - send_event(stream.realm, event, can_access_stream_user_ids(stream)) + # we do not need to send update events to the users who received creation event + # since they already have the updated stream info. + notify_stream_update_ids = can_access_stream_user_ids(stream) - notify_stream_creation_ids + send_event(stream.realm, event, notify_stream_update_ids) old_policy_name = get_stream_permission_policy_name( invite_only=old_invite_only_value, diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index 325966104a..9ae0cfcdf4 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -2744,6 +2744,40 @@ class SubscribeActionTest(BaseAction): check_stream_update("events[0]", events[0]) check_message("events[1]", events[1]) + # Update stream privacy - make stream public + self.user_profile = self.example_user("cordelia") + action = lambda: do_change_stream_permission( + stream, + invite_only=False, + history_public_to_subscribers=True, + is_web_public=False, + acting_user=self.example_user("hamlet"), + ) + events = self.verify_action(action, include_subscribers=include_subscribers, num_events=2) + check_stream_create("events[0]", events[0]) + check_subscription_peer_add("events[1]", events[1]) + + do_change_stream_permission( + stream, + invite_only=True, + history_public_to_subscribers=True, + is_web_public=False, + acting_user=self.example_user("hamlet"), + ) + self.subscribe(self.example_user("cordelia"), stream.name) + self.unsubscribe(self.example_user("cordelia"), stream.name) + action = lambda: do_change_stream_permission( + stream, + invite_only=False, + history_public_to_subscribers=True, + is_web_public=False, + acting_user=self.example_user("hamlet"), + ) + events = self.verify_action( + action, include_subscribers=include_subscribers, num_events=2, include_streams=False + ) + + self.user_profile = self.example_user("hamlet") # Update stream stream_post_policy property action = lambda: do_change_stream_post_policy( stream, Stream.STREAM_POST_POLICY_ADMINS, acting_user=self.example_user("hamlet")