streams: Handle guest user ids for stream settings changes' events.

This commit is contained in:
Shubham Dhama
2018-06-03 22:41:52 +05:30
committed by Tim Abbott
parent a42492d0ac
commit 01555e8772
4 changed files with 42 additions and 12 deletions

View File

@@ -73,7 +73,7 @@ from zerver.models import Realm, RealmEmoji, Stream, UserProfile, UserActivity,
get_user_profile_by_id, PreregistrationUser, get_display_recipient, \ get_user_profile_by_id, PreregistrationUser, get_display_recipient, \
get_realm, bulk_get_recipients, get_stream_recipient, get_stream_recipients, \ get_realm, bulk_get_recipients, get_stream_recipient, get_stream_recipients, \
email_allowed_for_realm, email_to_username, display_recipient_cache_key, \ email_allowed_for_realm, email_to_username, display_recipient_cache_key, \
get_user, get_stream_cache_key, \ get_user, get_stream_cache_key, active_non_guest_user_ids, \
UserActivityInterval, active_user_ids, get_active_streams, \ UserActivityInterval, active_user_ids, get_active_streams, \
realm_filters_for_realm, RealmFilter, stream_name_in_use, \ realm_filters_for_realm, RealmFilter, stream_name_in_use, \
get_old_unclaimed_attachments, is_cross_realm_bot_email, \ get_old_unclaimed_attachments, is_cross_realm_bot_email, \
@@ -179,7 +179,8 @@ def can_access_stream_user_ids(stream: Stream) -> Set[int]:
# a stream, such as its name/description. # a stream, such as its name/description.
if stream.is_public(): if stream.is_public():
# For a public stream, this is everyone in the realm # For a public stream, this is everyone in the realm
return set(active_user_ids(stream.realm_id)) # except unsubscribed guest users
return public_stream_user_ids(stream)
else: else:
# for a private stream, it's subscribers plus realm admins. # for a private stream, it's subscribers plus realm admins.
return private_stream_user_ids(stream.id) | {user.id for user in stream.realm.get_admin_users()} return private_stream_user_ids(stream.id) | {user.id for user in stream.realm.get_admin_users()}
@@ -189,6 +190,12 @@ def private_stream_user_ids(stream_id: int) -> Set[int]:
subscriptions = get_active_subscriptions_for_stream_id(stream_id) subscriptions = get_active_subscriptions_for_stream_id(stream_id)
return {sub['user_profile_id'] for sub in subscriptions.values('user_profile_id')} return {sub['user_profile_id'] for sub in subscriptions.values('user_profile_id')}
def public_stream_user_ids(stream: Stream) -> Set[int]:
guest_subscriptions = get_active_subscriptions_for_stream_id(
stream.id).filter(user_profile__is_guest=True)
guest_subscriptions = {sub['user_profile_id'] for sub in guest_subscriptions.values('user_profile_id')}
return set(active_non_guest_user_ids(stream.realm_id)) | guest_subscriptions
def bot_owner_user_ids(user_profile: UserProfile) -> Set[int]: def bot_owner_user_ids(user_profile: UserProfile) -> Set[int]:
is_private_bot = ( is_private_bot = (
user_profile.default_sending_stream and user_profile.default_sending_stream and
@@ -1644,7 +1651,7 @@ def create_stream_if_needed(realm: Realm,
if created: if created:
Recipient.objects.create(type_id=stream.id, type=Recipient.STREAM) Recipient.objects.create(type_id=stream.id, type=Recipient.STREAM)
if stream.is_public(): if stream.is_public():
send_stream_creation_event(stream, active_user_ids(stream.realm_id)) send_stream_creation_event(stream, active_non_guest_user_ids(stream.realm_id))
else: else:
realm_admin_ids = [user.id for user in stream.realm.get_admin_users()] realm_admin_ids = [user.id for user in stream.realm.get_admin_users()]
send_stream_creation_event(stream, realm_admin_ids) send_stream_creation_event(stream, realm_admin_ids)
@@ -2403,7 +2410,7 @@ def get_peer_user_ids_for_stream_change(stream: Stream,
# We now do "peer_add" or "peer_remove" events even for streams # We now do "peer_add" or "peer_remove" events even for streams
# users were never subscribed to, in order for the neversubscribed # users were never subscribed to, in order for the neversubscribed
# structure to stay up-to-date. # structure to stay up-to-date.
return set(active_user_ids(stream.realm_id)) - set(altered_user_ids) return set(active_non_guest_user_ids(stream.realm_id)) - set(altered_user_ids)
def get_user_ids_for_streams(streams: Iterable[Stream]) -> Dict[int, List[int]]: def get_user_ids_for_streams(streams: Iterable[Stream]) -> Dict[int, List[int]]:
stream_ids = [stream.id for stream in streams] stream_ids = [stream.id for stream in streams]

View File

@@ -331,6 +331,9 @@ def realm_user_dicts_cache_key(realm_id: int) -> str:
def active_user_ids_cache_key(realm_id: int) -> str: def active_user_ids_cache_key(realm_id: int) -> str:
return "active_user_ids:%s" % (realm_id,) return "active_user_ids:%s" % (realm_id,)
def active_non_guest_user_ids_cache_key(realm_id: int) -> str:
return "active_non_guest_user_ids:%s" % (realm_id,)
bot_dict_fields = ['id', 'full_name', 'short_name', 'bot_type', 'email', bot_dict_fields = ['id', 'full_name', 'short_name', 'bot_type', 'email',
'is_active', 'default_sending_stream__name', 'is_active', 'default_sending_stream__name',
'realm_id', 'realm_id',
@@ -388,6 +391,10 @@ def flush_user_profile(sender: Any, **kwargs: Any) -> None:
if changed(['is_active']): if changed(['is_active']):
cache_delete(active_user_ids_cache_key(user_profile.realm_id)) cache_delete(active_user_ids_cache_key(user_profile.realm_id))
cache_delete(active_non_guest_user_ids_cache_key(user_profile.realm_id))
if changed(['is_guest']):
cache_delete(active_non_guest_user_ids_cache_key(user_profile.realm_id))
if changed(['email', 'full_name', 'short_name', 'id', 'is_mirror_dummy']): if changed(['email', 'full_name', 'short_name', 'id', 'is_mirror_dummy']):
delete_display_recipient_cache(user_profile) delete_display_recipient_cache(user_profile)
@@ -420,6 +427,7 @@ def flush_realm(sender: Any, **kwargs: Any) -> None:
cache_delete(active_user_ids_cache_key(realm.id)) cache_delete(active_user_ids_cache_key(realm.id))
cache_delete(bot_dicts_in_realm_cache_key(realm)) cache_delete(bot_dicts_in_realm_cache_key(realm))
cache_delete(realm_alert_words_cache_key(realm)) cache_delete(realm_alert_words_cache_key(realm))
cache_delete(active_non_guest_user_ids_cache_key(realm.id))
def realm_alert_words_cache_key(realm: 'Realm') -> str: def realm_alert_words_cache_key(realm: 'Realm') -> str:
return "realm_alert_words:%s" % (realm.string_id,) return "realm_alert_words:%s" % (realm.string_id,)

View File

@@ -16,7 +16,7 @@ from django.core.validators import URLValidator, MinLengthValidator, \
RegexValidator RegexValidator
from django.dispatch import receiver from django.dispatch import receiver
from zerver.lib.cache import cache_with_key, flush_user_profile, flush_realm, \ from zerver.lib.cache import cache_with_key, flush_user_profile, flush_realm, \
user_profile_by_api_key_cache_key, \ user_profile_by_api_key_cache_key, active_non_guest_user_ids_cache_key, \
user_profile_by_id_cache_key, user_profile_by_email_cache_key, \ user_profile_by_id_cache_key, user_profile_by_email_cache_key, \
user_profile_cache_key, generic_bulk_cached_fetch, cache_set, flush_stream, \ user_profile_cache_key, generic_bulk_cached_fetch, cache_set, flush_stream, \
display_recipient_cache_key, cache_delete, active_user_ids_cache_key, \ display_recipient_cache_key, cache_delete, active_user_ids_cache_key, \
@@ -1561,6 +1561,15 @@ def active_user_ids(realm_id: int) -> List[int]:
).values_list('id', flat=True) ).values_list('id', flat=True)
return list(query) return list(query)
@cache_with_key(active_non_guest_user_ids_cache_key, timeout=3600*24*7)
def active_non_guest_user_ids(realm_id: int) -> List[int]:
query = UserProfile.objects.filter(
realm_id=realm_id,
is_active=True,
is_guest=False,
).values_list('id', flat=True)
return list(query)
def get_membership_realms(email: str) -> List[Realm]: def get_membership_realms(email: str) -> List[Realm]:
if settings.PRODUCTION: # nocoverage if settings.PRODUCTION: # nocoverage
return [] return []

View File

@@ -42,8 +42,8 @@ from zerver.lib.test_runner import (
from zerver.models import ( from zerver.models import (
get_display_recipient, Message, Realm, Recipient, Stream, Subscription, get_display_recipient, Message, Realm, Recipient, Stream, Subscription,
DefaultStream, UserProfile, get_user_profile_by_id, active_user_ids, DefaultStream, UserProfile, get_user_profile_by_id, active_non_guest_user_ids,
get_default_stream_groups, flush_per_request_caches, DefaultStreamGroup get_default_stream_groups, flush_per_request_caches, DefaultStreamGroup,
) )
from zerver.lib.actions import ( from zerver.lib.actions import (
@@ -97,7 +97,7 @@ class TestCreateStreams(ZulipTestCase):
self.assertEqual(events[0]['event']['type'], 'stream') self.assertEqual(events[0]['event']['type'], 'stream')
self.assertEqual(events[0]['event']['op'], 'create') self.assertEqual(events[0]['event']['op'], 'create')
# Send public stream creation event to all active users. # Send public stream creation event to all active users.
self.assertEqual(events[0]['users'], active_user_ids(realm.id)) self.assertEqual(events[0]['users'], active_non_guest_user_ids(realm.id))
self.assertEqual(events[0]['event']['streams'][0]['name'], "Public stream") self.assertEqual(events[0]['event']['streams'][0]['name'], "Public stream")
events = [] events = []
@@ -488,11 +488,13 @@ class StreamAdminTest(ZulipTestCase):
stream_name2_exists = get_stream('stream_name2', realm) stream_name2_exists = get_stream('stream_name2', realm)
self.assertTrue(stream_name2_exists) self.assertTrue(stream_name2_exists)
self.assertEqual(notified_user_ids, set(active_user_ids(realm.id))) self.assertEqual(notified_user_ids, set(active_non_guest_user_ids(realm.id)))
self.assertIn(user_profile.id, self.assertIn(user_profile.id,
notified_user_ids) notified_user_ids)
self.assertIn(self.example_user('prospero').id, self.assertIn(self.example_user('prospero').id,
notified_user_ids) notified_user_ids)
self.assertNotIn(self.example_user('polonius').id,
notified_user_ids)
# Test case to handle unicode stream name change # Test case to handle unicode stream name change
# *NOTE: Here Encoding is needed when Unicode string is passed as an argument* # *NOTE: Here Encoding is needed when Unicode string is passed as an argument*
@@ -616,11 +618,13 @@ class StreamAdminTest(ZulipTestCase):
notified_user_ids = set(events[0]['users']) notified_user_ids = set(events[0]['users'])
stream = get_stream('stream_name1', realm) stream = get_stream('stream_name1', realm)
self.assertEqual(notified_user_ids, set(active_user_ids(realm.id))) self.assertEqual(notified_user_ids, set(active_non_guest_user_ids(realm.id)))
self.assertIn(user_profile.id, self.assertIn(user_profile.id,
notified_user_ids) notified_user_ids)
self.assertIn(self.example_user('prospero').id, self.assertIn(self.example_user('prospero').id,
notified_user_ids) notified_user_ids)
self.assertNotIn(self.example_user('polonius').id,
notified_user_ids)
self.assertEqual('Test description', stream.description) self.assertEqual('Test description', stream.description)
@@ -2014,7 +2018,8 @@ class SubscriptionAPITest(ZulipTestCase):
set([user1.id, user2.id, self.test_user.id]) set([user1.id, user2.id, self.test_user.id])
) )
self.assertEqual(len(add_peer_event['users']), 19) self.assertNotIn(self.example_user('polonius').id, add_peer_event['users'])
self.assertEqual(len(add_peer_event['users']), 18)
self.assertEqual(add_peer_event['event']['type'], 'subscription') self.assertEqual(add_peer_event['event']['type'], 'subscription')
self.assertEqual(add_peer_event['event']['op'], 'peer_add') self.assertEqual(add_peer_event['event']['op'], 'peer_add')
self.assertEqual(add_peer_event['event']['user_id'], self.user_profile.id) self.assertEqual(add_peer_event['event']['user_id'], self.user_profile.id)
@@ -2045,7 +2050,8 @@ class SubscriptionAPITest(ZulipTestCase):
# We don't send a peer_add event to othello # We don't send a peer_add event to othello
self.assertNotIn(user_profile.id, add_peer_event['users']) self.assertNotIn(user_profile.id, add_peer_event['users'])
self.assertEqual(len(add_peer_event['users']), 19) self.assertNotIn(self.example_user('polonius').id, add_peer_event['users'])
self.assertEqual(len(add_peer_event['users']), 18)
self.assertEqual(add_peer_event['event']['type'], 'subscription') self.assertEqual(add_peer_event['event']['type'], 'subscription')
self.assertEqual(add_peer_event['event']['op'], 'peer_add') self.assertEqual(add_peer_event['event']['op'], 'peer_add')
self.assertEqual(add_peer_event['event']['user_id'], user_profile.id) self.assertEqual(add_peer_event['event']['user_id'], user_profile.id)