def by_pm_with(self, query, operand, maybe_negate): # type: (Query, str, ConditionTransform) -> Query if ',' in operand: # Huddle try: emails = [e.strip() for e in operand.split(',')] recipient = recipient_for_emails(emails, False, self.user_profile, self.user_profile) except ValidationError: raise BadNarrowOperator('unknown recipient ' + operand) cond = column("recipient_id") == recipient.id return query.where(maybe_negate(cond)) else: # Personal message self_recipient = get_recipient(Recipient.PERSONAL, type_id=self.user_profile.id) if operand == self.user_profile.email: # Personals with self cond = and_(column("sender_id") == self.user_profile.id, column("recipient_id") == self_recipient.id) return query.where(maybe_negate(cond)) # Personals with other user; include both directions. try: narrow_profile = get_user_profile_by_email(operand) except UserProfile.DoesNotExist: raise BadNarrowOperator('unknown user ' + operand) narrow_recipient = get_recipient(Recipient.PERSONAL, narrow_profile.id) cond = or_(and_(column("sender_id") == narrow_profile.id, column("recipient_id") == self_recipient.id), and_(column("sender_id") == self.user_profile.id, column("recipient_id") == narrow_recipient.id)) return query.where(maybe_negate(cond))
def create_missed_message_address(user_profile, message): # type: (UserProfile, Message) -> text_type if message.recipient.type == Recipient.PERSONAL: # We need to reply to the sender so look up their personal recipient_id recipient_id = get_recipient(Recipient.PERSONAL, message.sender_id).id else: recipient_id = message.recipient_id data = { 'user_profile_id': user_profile.id, 'recipient_id': recipient_id, 'subject': message.subject, } while True: token = generate_random_token(32) key = missed_message_redis_key(token) if redis_client.hsetnx(key, 'uses_left', 1): break with redis_client.pipeline() as pipeline: pipeline.hmset(key, data) pipeline.expire(key, 60 * 60 * 24 * 5) pipeline.execute() address = u'mm' + token return settings.EMAIL_GATEWAY_PATTERN % (address,)
def by_stream(self, query, operand, maybe_negate): # type: (Query, str, ConditionTransform) -> Query stream = get_stream(operand, self.user_profile.realm) if stream is None: raise BadNarrowOperator('unknown stream ' + operand) if self.user_profile.realm.is_zephyr_mirror_realm: # MIT users expect narrowing to "social" to also show messages to /^(un)*social(.d)*$/ # (unsocial, ununsocial, social.d, etc) m = re.search(r'^(?:un)*(.+?)(?:\.d)*$', stream.name, re.IGNORECASE) # Since the regex has a `.+` in it and "" is invalid as a # stream name, this will always match assert(m is not None) base_stream_name = m.group(1) matching_streams = get_active_streams(self.user_profile.realm).filter( name__iregex=r'^(un)*%s(\.d)*$' % (self._pg_re_escape(base_stream_name),)) matching_stream_ids = [matching_stream.id for matching_stream in matching_streams] recipients_map = bulk_get_recipients(Recipient.STREAM, matching_stream_ids) cond = column("recipient_id").in_([recipient.id for recipient in recipients_map.values()]) return query.where(maybe_negate(cond)) recipient = get_recipient(Recipient.STREAM, type_id=stream.id) cond = column("recipient_id") == recipient.id return query.where(maybe_negate(cond))
def create_missed_message_address(user_profile, message): # type: (UserProfile, Message) -> text_type if settings.EMAIL_GATEWAY_PATTERN == "": logging.warning("EMAIL_GATEWAY_PATTERN is an empty string, using " "NOREPLY_EMAIL_ADDRESS in the 'from' field.") return settings.NOREPLY_EMAIL_ADDRESS if message.recipient.type == Recipient.PERSONAL: # We need to reply to the sender so look up their personal recipient_id recipient_id = get_recipient(Recipient.PERSONAL, message.sender_id).id else: recipient_id = message.recipient_id data = {"user_profile_id": user_profile.id, "recipient_id": recipient_id, "subject": message.subject} while True: token = generate_random_token(32) key = missed_message_redis_key(token) if redis_client.hsetnx(key, "uses_left", 1): break with redis_client.pipeline() as pipeline: pipeline.hmset(key, data) pipeline.expire(key, 60 * 60 * 24 * 5) pipeline.execute() address = u"mm" + token return settings.EMAIL_GATEWAY_PATTERN % (address,)
def access_stream_common(user_profile, stream, error): # type: (UserProfile, Stream, Text) -> Tuple[Recipient, Subscription] """Common function for backend code where the target use attempts to access the target stream, returning all the data fetched along the way. If that user does not have permission to access that stream, we throw an exception. A design goal is that the error message is the same for streams you can't access and streams that don't exist.""" # First, we don't allow any access to streams in other realms. if stream.realm_id != user_profile.realm_id: raise JsonableError(error) recipient = get_recipient(Recipient.STREAM, stream.id) try: sub = Subscription.objects.get(user_profile=user_profile, recipient=recipient, active=True) except Subscription.DoesNotExist: sub = None # If the stream is in your realm and public, you can access it. if stream.is_public(): return (recipient, sub) # Or if you are subscribed to the stream, you can access it. if sub is not None: return (recipient, sub) # Otherwise it is a private stream and you're not on it, so throw # an error. raise JsonableError(error)
def get_topics_backend(request, user_profile, stream_id=REQ(converter=to_non_negative_int)): # type: (HttpRequest, UserProfile, int) -> HttpResponse try: stream = Stream.objects.get(pk=stream_id) except Stream.DoesNotExist: return json_error(_("Invalid stream id")) if stream.realm_id != user_profile.realm_id: return json_error(_("Invalid stream id")) recipient = get_recipient(Recipient.STREAM, stream.id) if not stream.is_public(): if not is_active_subscriber(user_profile=user_profile, recipient=recipient): return json_error(_("Invalid stream id")) result = get_topic_history_for_stream( user_profile=user_profile, recipient=recipient, ) # Our data structure here is a list of tuples of # (topic name, unread count), and it's reverse chronological, # so the most recent topic is the first element of the list. return json_success(dict(topics=result))
def handle(self, *args, **options): # type: (*Any, **str) -> None realm = self.get_realm(options) stream_to_keep = get_stream(options["stream_to_keep"], realm) stream_to_destroy = get_stream(options["stream_to_destroy"], realm) recipient_to_destroy = get_recipient(Recipient.STREAM, stream_to_destroy.id) recipient_to_keep = get_recipient(Recipient.STREAM, stream_to_keep.id) # The high-level approach here is to move all the messages to # the surviving stream, deactivate all the subscriptions on # the stream to be removed and deactivate the stream, and add # new subscriptions to the stream to keep for any users who # were only on the now-deactivated stream. # Move the messages, and delete the old copies from caches. message_ids_to_clear = list(Message.objects.filter( recipient=recipient_to_destroy).values_list("id", flat=True)) count = Message.objects.filter(recipient=recipient_to_destroy).update(recipient=recipient_to_keep) print("Moved %s messages" % (count,)) bulk_delete_cache_keys(message_ids_to_clear) # Move the Subscription objects. This algorithm doesn't # preserve any stream settings/colors/etc. from the stream # being destroyed, but it's convenient. existing_subs = Subscription.objects.filter(recipient=recipient_to_keep) users_already_subscribed = dict((sub.user_profile_id, sub.active) for sub in existing_subs) subs_to_deactivate = Subscription.objects.filter(recipient=recipient_to_destroy, active=True) users_to_activate = [ sub.user_profile for sub in subs_to_deactivate if not users_already_subscribed.get(sub.user_profile_id, False) ] if len(subs_to_deactivate) > 0: print("Deactivating %s subscriptions" % (len(subs_to_deactivate),)) bulk_remove_subscriptions([sub.user_profile for sub in subs_to_deactivate], [stream_to_destroy]) do_deactivate_stream(stream_to_destroy) if len(users_to_activate) > 0: print("Adding %s subscriptions" % (len(users_to_activate),)) bulk_add_subscriptions([stream_to_keep], users_to_activate)
def get_subscription_or_die(stream_name, user_profile): stream = get_stream(stream_name, user_profile.realm) if not stream: raise JsonableError("Invalid stream %s" % (stream.name,)) recipient = get_recipient(Recipient.STREAM, stream.id) subscription = Subscription.objects.filter(user_profile=user_profile, recipient=recipient, active=True) if not subscription.exists(): raise JsonableError("Not subscribed to stream %s" % (stream_name,)) return subscription
def stream_exists_backend(request, user_profile, stream_name, autosubscribe): if not valid_stream_name(stream_name): return json_error("Invalid characters in stream name") stream = get_stream(stream_name, user_profile.realm) result = {"exists": bool(stream)} if stream is not None: recipient = get_recipient(Recipient.STREAM, stream.id) if autosubscribe: bulk_add_subscriptions([stream], [user_profile]) result["subscribed"] = Subscription.objects.filter(user_profile=user_profile, recipient=recipient, active=True).exists() return json_success(result) # results are ignored for HEAD requests return json_response(data=result, status=404)
def stream_exists_backend(request, user_profile, stream_name, autosubscribe): # type: (HttpRequest, UserProfile, text_type, bool) -> HttpResponse if not valid_stream_name(stream_name): return json_error(_("Invalid characters in stream name")) stream = get_stream(stream_name, user_profile.realm) result = {"exists": bool(stream)} if stream is not None: recipient = get_recipient(Recipient.STREAM, stream.id) if autosubscribe: bulk_add_subscriptions([stream], [user_profile]) result["subscribed"] = is_active_subscriber( user_profile=user_profile, recipient=recipient) return json_success(result) # results are ignored for HEAD requests return json_response(data=result, status=404)
def stream_exists_backend(request, user_profile, stream_id, autosubscribe): # type: (HttpRequest, UserProfile, int, bool) -> HttpResponse try: stream = get_and_validate_stream_by_id(stream_id, user_profile.realm) except JsonableError: stream = None result = {"exists": bool(stream)} if stream is not None: recipient = get_recipient(Recipient.STREAM, stream.id) if autosubscribe: bulk_add_subscriptions([stream], [user_profile]) result["subscribed"] = is_active_subscriber( user_profile=user_profile, recipient=recipient) return json_success(result) # results are ignored for HEAD requests return json_response(data=result, status=404)
def by_stream(self, query, operand, maybe_negate): stream = get_stream(operand, self.user_profile.realm) if stream is None: raise BadNarrowOperator('unknown stream ' + operand) if self.user_profile.realm.domain == "mit.edu": # MIT users expect narrowing to "social" to also show messages to /^(un)*social(.d)*$/ # (unsocial, ununsocial, social.d, etc) m = re.search(r'^(?:un)*(.+?)(?:\.d)*$', stream.name, re.IGNORECASE) if m: base_stream_name = m.group(1) else: base_stream_name = stream.name matching_streams = get_active_streams(self.user_profile.realm).filter( name__iregex=r'^(un)*%s(\.d)*$' % (self._pg_re_escape(base_stream_name),)) matching_stream_ids = [matching_stream.id for matching_stream in matching_streams] recipients_map = bulk_get_recipients(Recipient.STREAM, matching_stream_ids) cond = column("recipient_id").in_([recipient.id for recipient in recipients_map.values()]) return query.where(maybe_negate(cond)) recipient = get_recipient(Recipient.STREAM, type_id=stream.id) cond = column("recipient_id") == recipient.id return query.where(maybe_negate(cond))
def get_subscription(stream_name, user_profile): # type: (Text, UserProfile) -> Subscription stream = get_stream(stream_name, user_profile.realm) recipient = get_recipient(Recipient.STREAM, stream.id) return Subscription.objects.get(user_profile=user_profile, recipient=recipient, active=True)
def home(request): # type: (HttpRequest) -> HttpResponse # We need to modify the session object every two weeks or it will expire. # This line makes reloading the page a sufficient action to keep the # session alive. request.session.modified = True user_profile = request.user request._email = request.user.email request.client = get_client("website") # If a user hasn't signed the current Terms of Service, send them there if settings.TERMS_OF_SERVICE is not None and settings.TOS_VERSION is not None and \ int(settings.TOS_VERSION.split('.')[0]) > user_profile.major_tos_version(): return accounts_accept_terms(request) narrow = [] # type: List[List[text_type]] narrow_stream = None narrow_topic = request.GET.get("topic") if request.GET.get("stream"): try: narrow_stream = get_stream(request.GET.get("stream"), user_profile.realm) assert(narrow_stream is not None) assert(narrow_stream.is_public()) narrow = [["stream", narrow_stream.name]] except Exception: logging.exception("Narrow parsing") if narrow_topic is not None: narrow.append(["topic", narrow_topic]) register_ret = do_events_register(user_profile, request.client, apply_markdown=True, narrow=narrow) user_has_messages = (register_ret['max_message_id'] != -1) # Reset our don't-spam-users-with-email counter since the # user has since logged in if not user_profile.last_reminder is None: user_profile.last_reminder = None user_profile.save(update_fields=["last_reminder"]) # Brand new users get the tutorial needs_tutorial = settings.TUTORIAL_ENABLED and \ user_profile.tutorial_status != UserProfile.TUTORIAL_FINISHED first_in_realm = realm_user_count(user_profile.realm) == 1 # If you are the only person in the realm and you didn't invite # anyone, we'll continue to encourage you to do so on the frontend. prompt_for_invites = first_in_realm and \ not PreregistrationUser.objects.filter(referred_by=user_profile).count() if user_profile.pointer == -1 and user_has_messages: # Put the new user's pointer at the bottom # # This improves performance, because we limit backfilling of messages # before the pointer. It's also likely that someone joining an # organization is interested in recent messages more than the very # first messages on the system. register_ret['pointer'] = register_ret['max_message_id'] user_profile.last_pointer_updater = request.session.session_key if user_profile.pointer == -1: latest_read = None else: try: latest_read = UserMessage.objects.get(user_profile=user_profile, message__id=user_profile.pointer) except UserMessage.DoesNotExist: # Don't completely fail if your saved pointer ID is invalid logging.warning("%s has invalid pointer %s" % (user_profile.email, user_profile.pointer)) latest_read = None desktop_notifications_enabled = user_profile.enable_desktop_notifications if narrow_stream is not None: desktop_notifications_enabled = False if user_profile.realm.notifications_stream: notifications_stream = user_profile.realm.notifications_stream.name else: notifications_stream = "" # Set default language and make it persist default_language = register_ret['default_language'] url_lang = '/{}'.format(request.LANGUAGE_CODE) if not request.path.startswith(url_lang): translation.activate(default_language) request.session[translation.LANGUAGE_SESSION_KEY] = default_language # Pass parameters to the client-side JavaScript code. # These end up in a global JavaScript Object named 'page_params'. page_params = dict( zulip_version = ZULIP_VERSION, share_the_love = settings.SHARE_THE_LOVE, development_environment = settings.DEVELOPMENT, debug_mode = settings.DEBUG, test_suite = settings.TEST_SUITE, poll_timeout = settings.POLL_TIMEOUT, login_page = settings.HOME_NOT_LOGGED_IN, server_uri = settings.SERVER_URI, realm_uri = user_profile.realm.uri, maxfilesize = settings.MAX_FILE_UPLOAD_SIZE, server_generation = settings.SERVER_GENERATION, password_auth_enabled = password_auth_enabled(user_profile.realm), have_initial_messages = user_has_messages, subbed_info = register_ret['subscriptions'], unsubbed_info = register_ret['unsubscribed'], neversubbed_info = register_ret['never_subscribed'], email_dict = register_ret['email_dict'], people_list = register_ret['realm_users'], bot_list = register_ret['realm_bots'], initial_pointer = register_ret['pointer'], initial_presences = register_ret['presences'], initial_servertime = time.time(), # Used for calculating relative presence age fullname = user_profile.full_name, email = user_profile.email, domain = user_profile.realm.domain, domains = list_of_domains_for_realm(user_profile.realm), realm_name = register_ret['realm_name'], realm_invite_required = register_ret['realm_invite_required'], realm_invite_by_admins_only = register_ret['realm_invite_by_admins_only'], realm_create_stream_by_admins_only = register_ret['realm_create_stream_by_admins_only'], realm_allow_message_editing = register_ret['realm_allow_message_editing'], realm_message_content_edit_limit_seconds = register_ret['realm_message_content_edit_limit_seconds'], realm_restricted_to_domain = register_ret['realm_restricted_to_domain'], realm_default_language = register_ret['realm_default_language'], enter_sends = user_profile.enter_sends, user_id = user_profile.id, left_side_userlist = register_ret['left_side_userlist'], default_language = register_ret['default_language'], default_language_name = get_language_name(register_ret['default_language']), language_list_dbl_col = get_language_list_for_templates(register_ret['default_language']), language_list = get_language_list(), referrals = register_ret['referrals'], realm_emoji = register_ret['realm_emoji'], needs_tutorial = needs_tutorial, first_in_realm = first_in_realm, prompt_for_invites = prompt_for_invites, notifications_stream = notifications_stream, cross_realm_user_emails = list(get_cross_realm_users()), # Stream message notification settings: stream_desktop_notifications_enabled = user_profile.enable_stream_desktop_notifications, stream_sounds_enabled = user_profile.enable_stream_sounds, # Private message and @-mention notification settings: desktop_notifications_enabled = desktop_notifications_enabled, sounds_enabled = user_profile.enable_sounds, enable_offline_email_notifications = user_profile.enable_offline_email_notifications, enable_offline_push_notifications = user_profile.enable_offline_push_notifications, enable_online_push_notifications = user_profile.enable_online_push_notifications, twenty_four_hour_time = register_ret['twenty_four_hour_time'], enable_digest_emails = user_profile.enable_digest_emails, event_queue_id = register_ret['queue_id'], last_event_id = register_ret['last_event_id'], max_message_id = register_ret['max_message_id'], unread_count = approximate_unread_count(user_profile), furthest_read_time = sent_time_in_epoch_seconds(latest_read), save_stacktraces = settings.SAVE_FRONTEND_STACKTRACES, alert_words = register_ret['alert_words'], muted_topics = register_ret['muted_topics'], realm_filters = register_ret['realm_filters'], realm_default_streams = register_ret['realm_default_streams'], is_admin = user_profile.is_realm_admin, can_create_streams = user_profile.can_create_streams(), name_changes_disabled = name_changes_disabled(user_profile.realm), has_mobile_devices = num_push_devices_for_user(user_profile) > 0, autoscroll_forever = user_profile.autoscroll_forever, default_desktop_notifications = user_profile.default_desktop_notifications, avatar_url = avatar_url(user_profile), avatar_url_medium = avatar_url(user_profile, medium=True), mandatory_topics = user_profile.realm.mandatory_topics, show_digest_email = user_profile.realm.show_digest_email, presence_disabled = user_profile.realm.presence_disabled, is_zephyr_mirror_realm = user_profile.realm.is_zephyr_mirror_realm, ) if narrow_stream is not None: # In narrow_stream context, initial pointer is just latest message recipient = get_recipient(Recipient.STREAM, narrow_stream.id) try: initial_pointer = Message.objects.filter(recipient=recipient).order_by('id').reverse()[0].id except IndexError: initial_pointer = -1 page_params["narrow_stream"] = narrow_stream.name if narrow_topic is not None: page_params["narrow_topic"] = narrow_topic page_params["narrow"] = [dict(operator=term[0], operand=term[1]) for term in narrow] page_params["max_message_id"] = initial_pointer page_params["initial_pointer"] = initial_pointer page_params["have_initial_messages"] = (initial_pointer != -1) statsd.incr('views.home') show_invites = True # Some realms only allow admins to invite users if user_profile.realm.invite_by_admins_only and not user_profile.is_realm_admin: show_invites = False product_name = "Zulip" page_params['product_name'] = product_name request._log_data['extra'] = "[%s]" % (register_ret["queue_id"],) response = render_to_response('zerver/index.html', {'user_profile': user_profile, 'page_params' : simplejson.encoder.JSONEncoderForHTML().encode(page_params), 'nofontface': is_buggy_ua(request.META.get("HTTP_USER_AGENT", "Unspecified")), 'avatar_url': avatar_url(user_profile), 'show_debug': settings.DEBUG and ('show_debug' in request.GET), 'pipeline': settings.PIPELINE_ENABLED, 'show_invites': show_invites, 'is_admin': user_profile.is_realm_admin, 'show_webathena': user_profile.realm.webathena_enabled, 'enable_feedback': settings.ENABLE_FEEDBACK, 'embedded': narrow_stream is not None, 'product_name': product_name }, request=request) patch_cache_control(response, no_cache=True, no_store=True, must_revalidate=True) return response
def home_real(request): # type: (HttpRequest) -> HttpResponse # We need to modify the session object every two weeks or it will expire. # This line makes reloading the page a sufficient action to keep the # session alive. request.session.modified = True user_profile = request.user # If a user hasn't signed the current Terms of Service, send them there if settings.TERMS_OF_SERVICE is not None and settings.TOS_VERSION is not None and \ int(settings.TOS_VERSION.split('.')[0]) > user_profile.major_tos_version(): return accounts_accept_terms(request) narrow = [] # type: List[List[Text]] narrow_stream = None narrow_topic = request.GET.get("topic") if request.GET.get("stream"): try: narrow_stream_name = request.GET.get("stream") (narrow_stream, ignored_rec, ignored_sub) = access_stream_by_name( user_profile, narrow_stream_name) narrow = [["stream", narrow_stream.name]] except Exception: logging.exception("Narrow parsing") if narrow_stream is not None and narrow_topic is not None: narrow.append(["topic", narrow_topic]) register_ret = do_events_register(user_profile, request.client, apply_markdown=True, narrow=narrow) user_has_messages = (register_ret['max_message_id'] != -1) # Reset our don't-spam-users-with-email counter since the # user has since logged in if user_profile.last_reminder is not None: user_profile.last_reminder = None user_profile.save(update_fields=["last_reminder"]) # Brand new users get the tutorial needs_tutorial = settings.TUTORIAL_ENABLED and \ user_profile.tutorial_status != UserProfile.TUTORIAL_FINISHED first_in_realm = realm_user_count(user_profile.realm) == 1 # If you are the only person in the realm and you didn't invite # anyone, we'll continue to encourage you to do so on the frontend. prompt_for_invites = first_in_realm and \ not PreregistrationUser.objects.filter(referred_by=user_profile).count() if user_profile.pointer == -1 and user_has_messages: # Put the new user's pointer at the bottom # # This improves performance, because we limit backfilling of messages # before the pointer. It's also likely that someone joining an # organization is interested in recent messages more than the very # first messages on the system. register_ret['pointer'] = register_ret['max_message_id'] user_profile.last_pointer_updater = request.session.session_key if user_profile.pointer == -1: latest_read = None else: try: latest_read = UserMessage.objects.get(user_profile=user_profile, message__id=user_profile.pointer) except UserMessage.DoesNotExist: # Don't completely fail if your saved pointer ID is invalid logging.warning("%s has invalid pointer %s" % (user_profile.email, user_profile.pointer)) latest_read = None # Set default language and make it persist default_language = register_ret['default_language'] url_lang = '/{}'.format(request.LANGUAGE_CODE) if not request.path.startswith(url_lang): translation.activate(default_language) request.session[translation.LANGUAGE_SESSION_KEY] = default_language # Pass parameters to the client-side JavaScript code. # These end up in a global JavaScript Object named 'page_params'. page_params = dict( # Server settings. share_the_love = settings.SHARE_THE_LOVE, development_environment = settings.DEVELOPMENT, debug_mode = settings.DEBUG, test_suite = settings.TEST_SUITE, poll_timeout = settings.POLL_TIMEOUT, login_page = settings.HOME_NOT_LOGGED_IN, server_uri = settings.SERVER_URI, maxfilesize = settings.MAX_FILE_UPLOAD_SIZE, max_avatar_file_size = settings.MAX_AVATAR_FILE_SIZE, server_generation = settings.SERVER_GENERATION, use_websockets = settings.USE_WEBSOCKETS, save_stacktraces = settings.SAVE_FRONTEND_STACKTRACES, server_inline_image_preview = settings.INLINE_IMAGE_PREVIEW, server_inline_url_embed_preview = settings.INLINE_URL_EMBED_PREVIEW, # Misc. extra data. have_initial_messages = user_has_messages, initial_servertime = time.time(), # Used for calculating relative presence age default_language_name = get_language_name(register_ret['default_language']), language_list_dbl_col = get_language_list_for_templates(register_ret['default_language']), language_list = get_language_list(), needs_tutorial = needs_tutorial, first_in_realm = first_in_realm, prompt_for_invites = prompt_for_invites, unread_count = approximate_unread_count(user_profile), furthest_read_time = sent_time_in_epoch_seconds(latest_read), has_mobile_devices = num_push_devices_for_user(user_profile) > 0, ) undesired_register_ret_fields = [ 'streams', ] for field_name in set(register_ret.keys()) - set(undesired_register_ret_fields): page_params[field_name] = register_ret[field_name] if narrow_stream is not None: # In narrow_stream context, initial pointer is just latest message recipient = get_recipient(Recipient.STREAM, narrow_stream.id) try: initial_pointer = Message.objects.filter(recipient=recipient).order_by('id').reverse()[0].id except IndexError: initial_pointer = -1 page_params["narrow_stream"] = narrow_stream.name if narrow_topic is not None: page_params["narrow_topic"] = narrow_topic page_params["narrow"] = [dict(operator=term[0], operand=term[1]) for term in narrow] page_params["max_message_id"] = initial_pointer page_params["pointer"] = initial_pointer page_params["have_initial_messages"] = (initial_pointer != -1) page_params["enable_desktop_notifications"] = False statsd.incr('views.home') show_invites = True # Some realms only allow admins to invite users if user_profile.realm.invite_by_admins_only and not user_profile.is_realm_admin: show_invites = False request._log_data['extra'] = "[%s]" % (register_ret["queue_id"],) response = render(request, 'zerver/index.html', context={'user_profile': user_profile, 'page_params': simplejson.encoder.JSONEncoderForHTML().encode(page_params), 'nofontface': is_buggy_ua(request.META.get("HTTP_USER_AGENT", "Unspecified")), 'avatar_url': avatar_url(user_profile), 'show_debug': settings.DEBUG and ('show_debug' in request.GET), 'pipeline': settings.PIPELINE_ENABLED, 'show_invites': show_invites, 'is_admin': user_profile.is_realm_admin, 'show_webathena': user_profile.realm.webathena_enabled, 'enable_feedback': settings.ENABLE_FEEDBACK, 'embedded': narrow_stream is not None, },) patch_cache_control(response, no_cache=True, no_store=True, must_revalidate=True) return response
def test_stream_recipient_info(self): # type: () -> None hamlet = self.example_user('hamlet') cordelia = self.example_user('cordelia') othello = self.example_user('othello') realm = hamlet.realm stream_name = 'Test Stream' topic_name = 'test topic' for user in [hamlet, cordelia, othello]: self.subscribe(user, stream_name) stream = get_stream(stream_name, realm) recipient = get_recipient(Recipient.STREAM, stream.id) stream_topic = StreamTopicTarget( stream_id=stream.id, topic_name=topic_name, ) sub = get_subscription(stream_name, hamlet) sub.push_notifications = True sub.save() info = get_recipient_info( recipient=recipient, sender_id=hamlet.id, stream_topic=stream_topic, ) all_user_ids = {hamlet.id, cordelia.id, othello.id} expected_info = dict( active_user_ids=all_user_ids, push_notify_user_ids=set(), stream_push_user_ids={hamlet.id}, um_eligible_user_ids=all_user_ids, long_term_idle_user_ids=set(), default_bot_user_ids=set(), service_bot_tuples=[], ) self.assertEqual(info, expected_info) # Now mute Hamlet to omit him from stream_push_user_ids. add_topic_mute( user_profile=hamlet, stream_id=stream.id, recipient_id=recipient.id, topic_name=topic_name, ) info = get_recipient_info( recipient=recipient, sender_id=hamlet.id, stream_topic=stream_topic, ) self.assertEqual(info['stream_push_user_ids'], set()) # Add a service bot. service_bot = do_create_user( email='*****@*****.**', password='', realm=realm, full_name='', short_name='', active=True, bot_type=UserProfile.EMBEDDED_BOT, ) info = get_recipient_info(recipient=recipient, sender_id=hamlet.id, stream_topic=stream_topic, possibly_mentioned_user_ids={service_bot.id}) self.assertEqual(info['service_bot_tuples'], [ (service_bot.id, UserProfile.EMBEDDED_BOT), ]) # Add a normal bot. normal_bot = do_create_user( email='*****@*****.**', password='', realm=realm, full_name='', short_name='', active=True, bot_type=UserProfile.DEFAULT_BOT, ) info = get_recipient_info( recipient=recipient, sender_id=hamlet.id, stream_topic=stream_topic, possibly_mentioned_user_ids={service_bot.id, normal_bot.id}) self.assertEqual(info['default_bot_user_ids'], {normal_bot.id})