mirror of
https://github.com/zulip/zulip.git
synced 2025-11-13 18:36:36 +00:00
subs: Send create event to new subscribers of invite-only streams.
This fixes a regression introduced by our migration to track subscribers for all public streams, where now users who are added to an invite-only stream were receiving a mark_subscribed event for a stream their browser didn't know existed, causing an exception. To fix this, we now send a stream create event to the browser just before the user receives the notification that it was added to the invite-only stream.
This commit is contained in:
@@ -1669,12 +1669,31 @@ def bulk_add_subscriptions(streams, users):
|
||||
sub_tuples_by_user[sub.user_profile.id].append((sub, stream))
|
||||
new_streams.add((sub.user_profile.id, stream.id))
|
||||
|
||||
# We now send several types of events to notify browsers. The
|
||||
# first batch is notifications to users on invite-only streams
|
||||
# that the stream exists.
|
||||
for stream in streams:
|
||||
new_users = [user for user in users if (user.id, stream.id) in new_streams]
|
||||
|
||||
# Users newly added to invite-only streams need a `create`
|
||||
# notification, since they didn't have the invite-only stream
|
||||
# in their browser yet.
|
||||
if stream.invite_only:
|
||||
event = dict(type="stream", op="create",
|
||||
streams=[stream.to_dict()])
|
||||
send_event(event, [user.id for user in new_users])
|
||||
|
||||
# The second batch is events for the users themselves that they
|
||||
# were subscribed to the new streams.
|
||||
for user_profile in users:
|
||||
if len(sub_tuples_by_user[user_profile.id]) == 0:
|
||||
continue
|
||||
sub_pairs = sub_tuples_by_user[user_profile.id]
|
||||
notify_subscriptions_added(user_profile, sub_pairs, fetch_stream_subscriber_emails)
|
||||
|
||||
# The second batch is events for other users who are tracking the
|
||||
# subscribers lists of streams in their browser; everyone for
|
||||
# public streams and only existing subscribers for private streams.
|
||||
for stream in streams:
|
||||
if stream.realm.is_zephyr_mirror_realm and not stream.invite_only:
|
||||
continue
|
||||
|
||||
@@ -40,7 +40,7 @@ from zerver.lib.actions import (
|
||||
gather_subscriptions_helper, bulk_add_subscriptions, bulk_remove_subscriptions,
|
||||
gather_subscriptions, get_default_streams_for_realm, get_realm, get_stream,
|
||||
get_user_profile_by_email, set_default_streams, get_subscription,
|
||||
create_streams_if_needed, active_user_ids
|
||||
create_stream_if_needed, create_streams_if_needed, active_user_ids
|
||||
)
|
||||
|
||||
from zerver.views.streams import (
|
||||
@@ -1548,6 +1548,49 @@ class SubscriptionAPITest(ZulipTestCase):
|
||||
self.assertEqual(add_peer_event['event']['op'], 'peer_add')
|
||||
self.assertEqual(add_peer_event['event']['user_id'], user_profile.id)
|
||||
|
||||
def test_private_stream_subscription(self):
|
||||
# type: () -> None
|
||||
realm = get_realm("zulip")
|
||||
|
||||
# Create a private stream with Hamlet subscribed
|
||||
stream_name = "private"
|
||||
(stream, _) = create_stream_if_needed(realm, stream_name, invite_only=True)
|
||||
|
||||
existing_email = "hamlet@zulip.com"
|
||||
existing_user_profile = get_user_profile_by_email(existing_email)
|
||||
bulk_add_subscriptions([stream], [existing_user_profile])
|
||||
|
||||
# Now subscribe Cordelia to the stream, capturing events
|
||||
email = 'cordelia@zulip.com'
|
||||
user_profile = get_user_profile_by_email(email)
|
||||
|
||||
events = []
|
||||
with tornado_redirected_to_list(events):
|
||||
bulk_add_subscriptions([stream], [user_profile])
|
||||
|
||||
self.assert_length(events, 3)
|
||||
create_event, add_event, add_peer_event = events
|
||||
|
||||
self.assertEqual(create_event['event']['type'], 'stream')
|
||||
self.assertEqual(create_event['event']['op'], 'create')
|
||||
self.assertEqual(create_event['users'], [user_profile.id])
|
||||
self.assertEqual(create_event['event']['streams'][0]['name'], stream_name)
|
||||
|
||||
self.assertEqual(add_event['event']['type'], 'subscription')
|
||||
self.assertEqual(add_event['event']['op'], 'add')
|
||||
self.assertEqual(add_event['users'], [user_profile.id])
|
||||
self.assertEqual(
|
||||
set(add_event['event']['subscriptions'][0]['subscribers']),
|
||||
set([user_profile.email, existing_user_profile.email])
|
||||
)
|
||||
|
||||
# We don't send a peer_add event to othello
|
||||
self.assertNotIn(user_profile.id, add_peer_event['users'])
|
||||
self.assertEqual(len(add_peer_event['users']), 1)
|
||||
self.assertEqual(add_peer_event['event']['type'], 'subscription')
|
||||
self.assertEqual(add_peer_event['event']['op'], 'peer_add')
|
||||
self.assertEqual(add_peer_event['event']['user_id'], user_profile.id)
|
||||
|
||||
def test_users_getting_add_peer_event(self):
|
||||
# type: () -> None
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user