Repository: zulip/zulip

Issue:
Reactivated users don't appear in "Manage streams" until you reload the browser
If you deactivate a user, reload the browser, and then reactivate them, the "Manage streams" UI will incorrectly not show the user as not subscribed to streams.  This leads to the incorrect impression that Zulip does not preserve one's subscriptions when an account is deactivated.

This needs further debugging; I suspect we need `do_reactivate_user` to call `send_peer_subscriber_events`.

See https://chat.zulip.org/#narrow/stream/6-frontend/topic/Keep.20stream.20subscriptions.20if.20deactivated/near/1287667 for debugging details.


Discussion:
Hello @zulip/server-misc members, this issue was labeled with the "area: real-time sync" label, so you may want to check it out!

<!-- areaLabelAddition -->

@zulipbot claim
@zulipbot claim

Welcome to Zulip, @thecalendar! We just sent you an invite to collaborate on this repository at https://github.com/zulip/zulip/invitations. Please accept this invite in order to claim this issue and begin a fun, rewarding experience contributing to Zulip!

Here's some tips to get you off to a good start:

- Join me on the [Zulip developers' server](https://chat.zulip.org), to get help, chat about this issue, and meet the other developers.
- [Unwatch this repository](https://help.github.com/articles/unwatching-repositories/), so that you don't get 100 emails a day.

As you work on this issue, you'll also want to refer to the [Zulip code contribution guide](https://zulip.readthedocs.io/en/latest/contributing/index.html), as well as the rest of the developer documentation on that site.

See you on the other side (that is, the pull request side)!

Hey @timabbott, I tried reproducing the bug. I logged in as an administrator, deactivated a profile 'Aaron". Checked on Manage Stream -> Subscribers - to ensure the Aaron was deactivated, and rightly so. Reactivated Aaron again and refreshed the page. Went to Subscribers and found his name. I am unsure if there is any bug or was it resolved? Kindly guide me if I have misinterpreted the question in anyway. 

I am attaching screenshots for your reference. 


Post Deactivating :
![deactivated](https://user-images.githubusercontent.com/73422055/147365904-dc5695d7-b355-4fc0-a124-b7c5fd0b0190.PNG)

Post reactivating + refreshing:
![reactivated](https://user-images.githubusercontent.com/73422055/147365945-e10e4965-eb9d-457b-bb99-9cdf3c3d6cb9.PNG)



@thecalendar The bug is that `Aaron` is not present in the list before **refreshing the page**.
@sahil839 Ah, I thought so. Thank you, will look into it. 
Hello @sampriti026, you have been unassigned from this issue because you have not updated this issue or any referenced pull requests for over 14 days.

You can reclaim this issue or claim any other issue by commenting `@zulipbot claim` on that issue.

Thanks for your contributions, and hope to see you again soon!


Resolving patch:
diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py
--- a/zerver/lib/actions.py
+++ b/zerver/lib/actions.py
@@ -813,6 +813,29 @@ def do_reactivate_user(user_profile: UserProfile, *, acting_user: Optional[UserP
     if user_profile.is_bot:
         notify_created_bot(user_profile)
 
+    subscribed_recipient_ids = Subscription.objects.filter(
+        user_profile_id=user_profile.id, active=True, recipient__type=Recipient.STREAM
+    ).values_list("recipient__type_id", flat=True)
+    subscribed_streams = Stream.objects.filter(id__in=subscribed_recipient_ids, deactivated=False)
+    subscriber_peer_info = bulk_get_subscriber_peer_info(
+        realm=user_profile.realm,
+        streams=subscribed_streams,
+    )
+
+    altered_user_dict: Dict[int, Set[int]] = defaultdict(set)
+    for stream in subscribed_streams:
+        altered_user_dict[stream.id] = {user_profile.id}
+
+    stream_dict = {stream.id: stream for stream in subscribed_streams}
+
+    send_peer_subscriber_events(
+        op="peer_add",
+        realm=user_profile.realm,
+        altered_user_dict=altered_user_dict,
+        stream_dict=stream_dict,
+        private_peer_dict=subscriber_peer_info.private_peer_dict,
+    )
+
 
 def active_humans_in_realm(realm: Realm) -> Sequence[UserProfile]:
     return UserProfile.objects.filter(realm=realm, is_active=True, is_bot=False)


Test patch:
diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py
--- a/zerver/tests/test_events.py
+++ b/zerver/tests/test_events.py
@@ -1848,10 +1848,23 @@ def test_do_deactivate_user(self) -> None:
 
     def test_do_reactivate_user(self) -> None:
         bot = self.create_bot("test")
+        self.subscribe(bot, "Denmark")
+        self.make_stream("Test private stream", invite_only=True)
+        self.subscribe(bot, "Test private stream")
         do_deactivate_user(bot, acting_user=None)
         action = lambda: do_reactivate_user(bot, acting_user=None)
-        events = self.verify_action(action, num_events=2)
+        events = self.verify_action(action, num_events=3)
+        check_realm_bot_add("events[1]", events[1])
+        check_subscription_peer_add("events[2]", events[2])
+
+        # Test 'peer_add' event for private stream is received only if user is subscribed to it.
+        do_deactivate_user(bot, acting_user=None)
+        self.subscribe(self.example_user("hamlet"), "Test private stream")
+        action = lambda: do_reactivate_user(bot, acting_user=None)
+        events = self.verify_action(action, num_events=4)
         check_realm_bot_add("events[1]", events[1])
+        check_subscription_peer_add("events[2]", events[2])
+        check_subscription_peer_add("events[3]", events[3])
 
     def test_do_deactivate_realm(self) -> None:
         realm = self.user_profile.realm