mirror of https://github.com/zulip/zulip.git
streams: Send user remove events when deactivating streams.
This commit is contained in:
parent
4f58733d82
commit
f75b4f65c1
|
@ -74,6 +74,44 @@ from zerver.models import (
|
||||||
from zerver.tornado.django_api import send_event, send_event_on_commit
|
from zerver.tornado.django_api import send_event, send_event_on_commit
|
||||||
|
|
||||||
|
|
||||||
|
def send_user_remove_events_on_stream_deactivation(
|
||||||
|
stream: Stream, subscribed_users: List[UserProfile]
|
||||||
|
) -> None:
|
||||||
|
guest_subscribed_users = [user for user in subscribed_users if user.is_guest]
|
||||||
|
|
||||||
|
if len(guest_subscribed_users) == 0: # nocoverage
|
||||||
|
# Save a few database queries in the case that the stream
|
||||||
|
# didn't contain any guest users.
|
||||||
|
return
|
||||||
|
|
||||||
|
other_subscriptions_of_subscribed_users = get_subscribers_of_target_user_subscriptions(
|
||||||
|
guest_subscribed_users
|
||||||
|
)
|
||||||
|
users_involved_in_dms_dict = get_users_involved_in_dms_with_target_users(
|
||||||
|
guest_subscribed_users, stream.realm
|
||||||
|
)
|
||||||
|
|
||||||
|
subscriber_ids = {user.id for user in subscribed_users}
|
||||||
|
inaccessible_user_dict: Dict[int, Set[int]] = defaultdict(set)
|
||||||
|
for guest_user in guest_subscribed_users:
|
||||||
|
users_accessible_by_guest = (
|
||||||
|
{guest_user.id}
|
||||||
|
| other_subscriptions_of_subscribed_users[guest_user.id]
|
||||||
|
| users_involved_in_dms_dict[guest_user.id]
|
||||||
|
)
|
||||||
|
users_inaccessible_to_guest = subscriber_ids - users_accessible_by_guest
|
||||||
|
for user_id in users_inaccessible_to_guest:
|
||||||
|
inaccessible_user_dict[user_id].add(guest_user.id)
|
||||||
|
|
||||||
|
for user_id, notify_user_ids in inaccessible_user_dict.items():
|
||||||
|
event_remove_user = dict(
|
||||||
|
type="realm_user",
|
||||||
|
op="remove",
|
||||||
|
person=dict(user_id=user_id, full_name=str(UserProfile.INACCESSIBLE_USER_NAME)),
|
||||||
|
)
|
||||||
|
send_event_on_commit(stream.realm, event_remove_user, list(notify_user_ids))
|
||||||
|
|
||||||
|
|
||||||
@transaction.atomic(savepoint=False)
|
@transaction.atomic(savepoint=False)
|
||||||
def do_deactivate_stream(stream: Stream, *, acting_user: Optional[UserProfile]) -> None:
|
def do_deactivate_stream(stream: Stream, *, acting_user: Optional[UserProfile]) -> None:
|
||||||
# If the stream is already deactivated, this is a no-op
|
# If the stream is already deactivated, this is a no-op
|
||||||
|
@ -94,9 +132,11 @@ def do_deactivate_stream(stream: Stream, *, acting_user: Optional[UserProfile])
|
||||||
# Get the affected user ids *before* we deactivate everybody.
|
# Get the affected user ids *before* we deactivate everybody.
|
||||||
affected_user_ids = can_access_stream_user_ids(stream)
|
affected_user_ids = can_access_stream_user_ids(stream)
|
||||||
|
|
||||||
get_active_subscriptions_for_stream_id(stream.id, include_deactivated_users=True).update(
|
stream_subscribers = get_active_subscriptions_for_stream_id(
|
||||||
active=False
|
stream.id, include_deactivated_users=True
|
||||||
)
|
).select_related("user_profile")
|
||||||
|
subscribed_users = [sub.user_profile for sub in stream_subscribers]
|
||||||
|
stream_subscribers.update(active=False)
|
||||||
|
|
||||||
was_invite_only = stream.invite_only
|
was_invite_only = stream.invite_only
|
||||||
was_public = stream.is_public()
|
was_public = stream.is_public()
|
||||||
|
@ -157,6 +197,9 @@ def do_deactivate_stream(stream: Stream, *, acting_user: Optional[UserProfile])
|
||||||
event = dict(type="stream", op="delete", streams=[stream_dict])
|
event = dict(type="stream", op="delete", streams=[stream_dict])
|
||||||
send_event_on_commit(stream.realm, event, affected_user_ids)
|
send_event_on_commit(stream.realm, event, affected_user_ids)
|
||||||
|
|
||||||
|
if stream.realm.can_access_all_users_group.name != SystemGroups.EVERYONE:
|
||||||
|
send_user_remove_events_on_stream_deactivation(stream, subscribed_users)
|
||||||
|
|
||||||
event_time = timezone_now()
|
event_time = timezone_now()
|
||||||
RealmAuditLog.objects.create(
|
RealmAuditLog.objects.create(
|
||||||
realm=stream.realm,
|
realm=stream.realm,
|
||||||
|
|
|
@ -3075,6 +3075,39 @@ class NormalActionsTest(BaseAction):
|
||||||
check_stream_delete("events[0]", events[0])
|
check_stream_delete("events[0]", events[0])
|
||||||
self.assertIsNone(events[0]["streams"][0]["stream_weekly_traffic"])
|
self.assertIsNone(events[0]["streams"][0]["stream_weekly_traffic"])
|
||||||
|
|
||||||
|
def test_user_losing_access_on_deactivating_stream(self) -> None:
|
||||||
|
self.set_up_db_for_testing_user_access()
|
||||||
|
polonius = self.example_user("polonius")
|
||||||
|
hamlet = self.example_user("hamlet")
|
||||||
|
realm = hamlet.realm
|
||||||
|
self.user_profile = self.example_user("polonius")
|
||||||
|
|
||||||
|
stream = get_stream("test_stream1", realm)
|
||||||
|
self.assertCountEqual(
|
||||||
|
self.users_subscribed_to_stream(stream.name, realm), [hamlet, polonius]
|
||||||
|
)
|
||||||
|
|
||||||
|
action = lambda: do_deactivate_stream(stream, acting_user=None)
|
||||||
|
events = self.verify_action(action, num_events=2)
|
||||||
|
check_stream_delete("events[0]", events[0])
|
||||||
|
check_realm_user_remove("events[1]", events[1])
|
||||||
|
self.assertEqual(events[1]["person"]["user_id"], hamlet.id)
|
||||||
|
|
||||||
|
# Test that if the subscribers of deactivated stream are involved in
|
||||||
|
# DMs with guest, then the guest does not get "remove" event for them.
|
||||||
|
stream = get_stream("test_stream2", self.user_profile.realm)
|
||||||
|
shiva = self.example_user("shiva")
|
||||||
|
iago = self.example_user("iago")
|
||||||
|
self.subscribe(shiva, stream.name)
|
||||||
|
self.assertCountEqual(
|
||||||
|
self.users_subscribed_to_stream(stream.name, realm), [iago, polonius, shiva]
|
||||||
|
)
|
||||||
|
|
||||||
|
events = self.verify_action(action, num_events=2)
|
||||||
|
check_stream_delete("events[0]", events[0])
|
||||||
|
check_realm_user_remove("events[1]", events[1])
|
||||||
|
self.assertEqual(events[1]["person"]["user_id"], iago.id)
|
||||||
|
|
||||||
def test_subscribe_other_user_never_subscribed(self) -> None:
|
def test_subscribe_other_user_never_subscribed(self) -> None:
|
||||||
for i, include_streams in enumerate([True, False]):
|
for i, include_streams in enumerate([True, False]):
|
||||||
action = partial(self.subscribe, self.example_user("othello"), f"test_stream{i}")
|
action = partial(self.subscribe, self.example_user("othello"), f"test_stream{i}")
|
||||||
|
|
Loading…
Reference in New Issue