Esempio n. 1
0
    def test_compute_show_invites_and_add_streams_guest(self) -> None:
        user = self.example_user("polonius")

        show_invites, show_add_streams = compute_show_invites_and_add_streams(
            user)
        self.assertEqual(show_invites, False)
        self.assertEqual(show_add_streams, False)
Esempio n. 2
0
    def test_compute_show_invites_and_add_streams_admin(self) -> None:
        user = self.example_user("iago")

        realm = user.realm
        realm.invite_by_admins_only = True
        realm.save()

        show_invites, show_add_streams = compute_show_invites_and_add_streams(user)
        self.assertEqual(show_invites, True)
        self.assertEqual(show_add_streams, True)
Esempio n. 3
0
    def test_compute_show_invites_and_add_streams_require_admin(self) -> None:
        user = self.example_user("hamlet")

        realm = user.realm
        realm.invite_to_realm_policy = Realm.POLICY_ADMINS_ONLY
        realm.save()

        show_invites, show_add_streams = compute_show_invites_and_add_streams(user)
        self.assertEqual(show_invites, False)
        self.assertEqual(show_add_streams, True)
Esempio n. 4
0
 def test_compute_show_invites_and_add_streams_unauthenticated(
         self) -> None:
     show_invites, show_add_streams = compute_show_invites_and_add_streams(
         None)
     self.assertEqual(show_invites, False)
     self.assertEqual(show_add_streams, False)
Esempio n. 5
0
File: home.py Progetto: dcfix/zulip
def home_real(request: HttpRequest) -> HttpResponse:
    # Before we do any real work, check if the app is banned.
    client_user_agent = request.META.get("HTTP_USER_AGENT", "")
    (insecure_desktop_app, banned_desktop_app,
     auto_update_broken) = is_outdated_desktop_app(client_user_agent)
    if banned_desktop_app:
        return render(
            request,
            "zerver/insecure_desktop_app.html",
            context={
                "auto_update_broken": auto_update_broken,
            },
        )
    (unsupported_browser,
     browser_name) = is_unsupported_browser(client_user_agent)
    if unsupported_browser:
        return render(
            request,
            "zerver/unsupported_browser.html",
            context={
                "browser_name": browser_name,
            },
        )

    # 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

    if request.user.is_authenticated:
        user_profile = request.user
        realm = user_profile.realm
    else:
        # user_profile=None corresponds to the logged-out "web_public" visitor case.
        user_profile = None
        realm = get_valid_realm_from_request(request)

    update_last_reminder(user_profile)

    statsd.incr("views.home")

    # If a user hasn't signed the current Terms of Service, send them there
    if need_accept_tos(user_profile):
        return accounts_accept_terms(request)

    narrow, narrow_stream, narrow_topic = detect_narrowed_window(
        request, user_profile)

    if user_profile is not None:
        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())
        needs_tutorial = user_profile.tutorial_status == UserProfile.TUTORIAL_WAITING

    else:
        first_in_realm = False
        prompt_for_invites = False
        # The current tutorial doesn't super make sense for logged-out users.
        needs_tutorial = False

    queue_id, page_params = build_page_params_for_home_page_load(
        request=request,
        user_profile=user_profile,
        realm=realm,
        insecure_desktop_app=insecure_desktop_app,
        narrow=narrow,
        narrow_stream=narrow_stream,
        narrow_topic=narrow_topic,
        first_in_realm=first_in_realm,
        prompt_for_invites=prompt_for_invites,
        needs_tutorial=needs_tutorial,
    )

    show_invites, show_add_streams = compute_show_invites_and_add_streams(
        user_profile)

    request._log_data["extra"] = "[{}]".format(queue_id)

    csp_nonce = secrets.token_hex(24)

    user_permission_info = get_user_permission_info(user_profile)

    response = render(
        request,
        "zerver/app/index.html",
        context={
            "user_profile": user_profile,
            "page_params": page_params,
            "csp_nonce": csp_nonce,
            "search_pills_enabled": settings.SEARCH_PILLS_ENABLED,
            "show_invites": show_invites,
            "show_add_streams": show_add_streams,
            "is_owner": user_permission_info.is_realm_owner,
            "is_admin": user_permission_info.is_realm_admin,
            "is_guest": user_permission_info.is_guest,
            "color_scheme": user_permission_info.color_scheme,
            "embedded": narrow_stream is not None,
            "max_file_upload_size_mib": settings.MAX_FILE_UPLOAD_SIZE,
        },
    )
    patch_cache_control(response,
                        no_cache=True,
                        no_store=True,
                        must_revalidate=True)
    return response
Esempio n. 6
0
def home_real(request: HttpRequest) -> HttpResponse:
    # Before we do any real work, check if the app is banned.
    client_user_agent = request.META.get("HTTP_USER_AGENT", "")
    (insecure_desktop_app, banned_desktop_app,
     auto_update_broken) = is_outdated_desktop_app(client_user_agent)
    if banned_desktop_app:
        return render(
            request,
            'zerver/insecure_desktop_app.html',
            context={
                "auto_update_broken": auto_update_broken,
            },
        )
    (unsupported_browser,
     browser_name) = is_unsupported_browser(client_user_agent)
    if unsupported_browser:
        return render(
            request,
            'zerver/unsupported_browser.html',
            context={
                "browser_name": browser_name,
            },
        )

    # 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

    if request.user.is_authenticated:
        user_profile = request.user
    else:  # nocoverage
        # This code path should not be reachable because of zulip_login_required above.
        user_profile = None

    update_last_reminder(user_profile)

    statsd.incr('views.home')

    # If a user hasn't signed the current Terms of Service, send them there
    if need_accept_tos(user_profile):
        return accounts_accept_terms(request)

    narrow, narrow_stream, narrow_topic = detect_narrowed_window(
        request, user_profile)

    if user_profile is not None:
        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())
        needs_tutorial = user_profile.tutorial_status == UserProfile.TUTORIAL_WAITING

    else:  # nocoverage
        first_in_realm = False
        prompt_for_invites = False
        # The current tutorial doesn't super make sense for logged-out users.
        needs_tutorial = False

    has_mobile_devices = user_profile is not None and num_push_devices_for_user(
        user_profile) > 0

    queue_id, page_params = build_page_params_for_home_page_load(
        request=request,
        user_profile=user_profile,
        insecure_desktop_app=insecure_desktop_app,
        has_mobile_devices=has_mobile_devices,
        narrow=narrow,
        narrow_stream=narrow_stream,
        narrow_topic=narrow_topic,
        first_in_realm=first_in_realm,
        prompt_for_invites=prompt_for_invites,
        needs_tutorial=needs_tutorial,
    )

    show_invites, show_add_streams = compute_show_invites_and_add_streams(
        user_profile)

    billing_info = get_billing_info(user_profile)

    request._log_data['extra'] = "[{}]".format(queue_id)

    csp_nonce = secrets.token_hex(24)

    user_permission_info = get_user_permission_info(user_profile)

    navbar_logo_url = compute_navbar_logo_url(page_params)

    response = render(request,
                      'zerver/app/index.html',
                      context={
                          'user_profile':
                          user_profile,
                          'page_params':
                          page_params,
                          'csp_nonce':
                          csp_nonce,
                          'search_pills_enabled':
                          settings.SEARCH_PILLS_ENABLED,
                          'show_invites':
                          show_invites,
                          'show_add_streams':
                          show_add_streams,
                          'show_billing':
                          billing_info.show_billing,
                          'corporate_enabled':
                          settings.CORPORATE_ENABLED,
                          'show_plans':
                          billing_info.show_plans,
                          'is_owner':
                          user_permission_info.is_realm_owner,
                          'is_admin':
                          user_permission_info.is_realm_admin,
                          'is_guest':
                          user_permission_info.is_guest,
                          'color_scheme':
                          user_permission_info.color_scheme,
                          'navbar_logo_url':
                          navbar_logo_url,
                          'show_webathena':
                          user_permission_info.show_webathena,
                          'embedded':
                          narrow_stream is not None,
                          'invite_as':
                          PreregistrationUser.INVITE_AS,
                          'max_file_upload_size_mib':
                          settings.MAX_FILE_UPLOAD_SIZE,
                      })
    patch_cache_control(response,
                        no_cache=True,
                        no_store=True,
                        must_revalidate=True)
    return response
Esempio n. 7
0
def home_real(request: HttpRequest) -> HttpResponse:
    # Before we do any real work, check if the app is banned.
    (insecure_desktop_app, banned_desktop_app,
     auto_update_broken) = is_outdated_desktop_app(
         request.META.get("HTTP_USER_AGENT", ""))
    if banned_desktop_app:
        return render(request,
                      'zerver/insecure_desktop_app.html',
                      context={
                          "auto_update_broken": auto_update_broken,
                      })

    # 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

    if request.user.is_authenticated:
        user_profile = request.user
    else:  # nocoverage
        # This code path should not be reachable because of zulip_login_required above.
        user_profile = None

    # If a user hasn't signed the current Terms of Service, send them there
    if need_accept_tos(user_profile):
        return accounts_accept_terms(request)

    narrow, narrow_stream, narrow_topic = detect_narrowed_window(
        request, user_profile)

    register_ret = do_events_register(user_profile,
                                      request.client,
                                      apply_markdown=True,
                                      client_gravatar=True,
                                      slim_presence=True,
                                      notification_settings_null=True,
                                      narrow=narrow)
    user_has_messages = (register_ret['max_message_id'] != -1)
    update_last_reminder(user_profile)

    if user_profile is not None:
        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())
        needs_tutorial = user_profile.tutorial_status == UserProfile.TUTORIAL_WAITING
    else:  # nocoverage
        first_in_realm = False
        prompt_for_invites = False
        # The current tutorial doesn't super make sense for logged-out users.
        needs_tutorial = False

    if user_profile is None:  # nocoverage
        furthest_read_time = time.time()  # type: Optional[float]
    elif user_profile.pointer == -1:
        if 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
        furthest_read_time = None
    else:
        latest_read = get_usermessage_by_message_id(user_profile,
                                                    user_profile.pointer)
        if latest_read is None:
            # Don't completely fail if your saved pointer ID is invalid
            logging.warning("User %s has invalid pointer %s" %
                            (user_profile.id, user_profile.pointer))
        furthest_read_time = sent_time_in_epoch_seconds(latest_read)

    # We pick a language for the user as follows:
    # * First priority is the language in the URL, for debugging.
    # * If not in the URL, we use the language from the user's settings.
    request_language = translation.get_language_from_path(request.path_info)
    if request_language is None:
        request_language = register_ret['default_language']
    translation.activate(request_language)
    # We also save the language to the user's session, so that
    # something reasonable will happen in logged-in portico pages.
    request.session[
        translation.LANGUAGE_SESSION_KEY] = translation.get_language()

    two_fa_enabled = settings.TWO_FACTOR_AUTHENTICATION_ENABLED and user_profile is not None

    # Pass parameters to the client-side JavaScript code.
    # These end up in a global JavaScript Object named 'page_params'.
    page_params = dict(
        # Server settings.
        development_environment=settings.DEVELOPMENT,
        debug_mode=settings.DEBUG,
        test_suite=settings.TEST_SUITE,
        poll_timeout=settings.POLL_TIMEOUT,
        insecure_desktop_app=insecure_desktop_app,
        login_page=settings.HOME_NOT_LOGGED_IN,
        root_domain_uri=settings.ROOT_DOMAIN_URI,
        max_file_upload_size=settings.MAX_FILE_UPLOAD_SIZE,
        max_avatar_file_size=settings.MAX_AVATAR_FILE_SIZE,
        server_generation=settings.SERVER_GENERATION,
        save_stacktraces=settings.SAVE_FRONTEND_STACKTRACES,
        warn_no_email=settings.WARN_NO_EMAIL,
        server_inline_image_preview=settings.INLINE_IMAGE_PREVIEW,
        server_inline_url_embed_preview=settings.INLINE_URL_EMBED_PREVIEW,
        password_min_length=settings.PASSWORD_MIN_LENGTH,
        password_min_guesses=settings.PASSWORD_MIN_GUESSES,
        jitsi_server_url=settings.JITSI_SERVER_URL,
        search_pills_enabled=settings.SEARCH_PILLS_ENABLED,
        server_avatar_changes_disabled=settings.AVATAR_CHANGES_DISABLED,
        server_name_changes_disabled=settings.NAME_CHANGES_DISABLED,

        # 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,
        furthest_read_time=furthest_read_time,
        has_mobile_devices=user_profile is not None
        and num_push_devices_for_user(user_profile) > 0,
        bot_types=get_bot_types(user_profile),
        two_fa_enabled=two_fa_enabled,
        # Adding two_fa_enabled as condition saves us 3 queries when
        # 2FA is not enabled.
        two_fa_enabled_user=two_fa_enabled
        and bool(default_device(user_profile)),
    )

    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 = narrow_stream.recipient
        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, show_add_streams = compute_show_invites_and_add_streams(
        user_profile)

    show_billing = False
    show_plans = False
    if settings.CORPORATE_ENABLED and user_profile is not None:
        from corporate.models import Customer, CustomerPlan
        if user_profile.is_billing_admin or user_profile.is_realm_admin:
            customer = Customer.objects.filter(
                realm=user_profile.realm).first()
            if customer is not None and CustomerPlan.objects.filter(
                    customer=customer).exists():
                show_billing = True
        if user_profile.realm.plan_type == Realm.LIMITED:
            show_plans = True

    request._log_data['extra'] = "[%s]" % (register_ret["queue_id"], )

    page_params['translation_data'] = {}
    if request_language != 'en':
        page_params['translation_data'] = get_language_translation_data(
            request_language)

    csp_nonce = generate_random_token(48)
    if user_profile is not None:
        night_mode = user_profile.night_mode
        is_guest = user_profile.is_guest
        is_realm_admin = user_profile.is_realm_admin
        show_webathena = user_profile.realm.webathena_enabled
    else:  # nocoverage
        night_mode = False
        is_guest = False
        is_realm_admin = False
        show_webathena = False

    navbar_logo_url = compute_navbar_logo_url(page_params)

    response = render(
        request,
        'zerver/app/index.html',
        context={
            'user_profile': user_profile,
            'page_params': page_params,
            'csp_nonce': csp_nonce,
            'search_pills_enabled': settings.SEARCH_PILLS_ENABLED,
            'show_invites': show_invites,
            'show_add_streams': show_add_streams,
            'show_billing': show_billing,
            'show_plans': show_plans,
            'is_admin': is_realm_admin,
            'is_guest': is_guest,
            'night_mode': night_mode,
            'navbar_logo_url': navbar_logo_url,
            'show_webathena': show_webathena,
            'embedded': narrow_stream is not None,
            'invite_as': PreregistrationUser.INVITE_AS,
            'max_file_upload_size': settings.MAX_FILE_UPLOAD_SIZE,
        },
    )
    patch_cache_control(response,
                        no_cache=True,
                        no_store=True,
                        must_revalidate=True)
    return response
Esempio n. 8
0
def build_page_params_for_home_page_load(
    request: HttpRequest,
    user_profile: Optional[UserProfile],
    realm: Realm,
    insecure_desktop_app: bool,
    narrow: List[List[str]],
    narrow_stream: Optional[Stream],
    narrow_topic: Optional[str],
    first_in_realm: bool,
    prompt_for_invites: bool,
    needs_tutorial: bool,
) -> Tuple[int, Dict[str, Any]]:
    """
    This function computes page_params for when we load the home page.

    The page_params data structure gets sent to the client.
    """
    client_capabilities = {
        "notification_settings_null": True,
        "bulk_message_deletion": True,
        "user_avatar_url_field_optional": True,
        "stream_typing_notifications": False,  # Set this to True when frontend support is implemented.
    }

    if user_profile is not None:
        register_ret = do_events_register(
            user_profile,
            request.client,
            apply_markdown=True,
            client_gravatar=True,
            slim_presence=True,
            client_capabilities=client_capabilities,
            narrow=narrow,
            include_streams=False,
        )
    else:
        # Since events for spectator is not implemented, we only fetch the data
        # at the time of request and don't register for any events.
        # TODO: Implement events for spectator.
        from zerver.lib.events import fetch_initial_state_data, post_process_state

        register_ret = fetch_initial_state_data(
            user_profile,
            realm=realm,
            event_types=None,
            queue_id=None,
            client_gravatar=False,
            user_avatar_url_field_optional=client_capabilities["user_avatar_url_field_optional"],
            slim_presence=False,
            include_subscribers=False,
            include_streams=False,
        )

        post_process_state(user_profile, register_ret, False)

    furthest_read_time = get_furthest_read_time(user_profile)

    request_language = get_and_set_request_language(
        request,
        register_ret["default_language"],
        translation.get_language_from_path(request.path_info),
    )

    two_fa_enabled = settings.TWO_FACTOR_AUTHENTICATION_ENABLED and user_profile is not None
    billing_info = get_billing_info(user_profile)
    show_invites, _ = compute_show_invites_and_add_streams(user_profile)
    user_permission_info = get_user_permission_info(user_profile)

    # Pass parameters to the client-side JavaScript code.
    # These end up in a JavaScript Object named 'page_params'.
    page_params = dict(
        ## Server settings.
        test_suite=settings.TEST_SUITE,
        insecure_desktop_app=insecure_desktop_app,
        login_page=settings.HOME_NOT_LOGGED_IN,
        save_stacktraces=settings.SAVE_FRONTEND_STACKTRACES,
        warn_no_email=settings.WARN_NO_EMAIL,
        search_pills_enabled=settings.SEARCH_PILLS_ENABLED,
        # Only show marketing email settings if on Zulip Cloud
        corporate_enabled=settings.CORPORATE_ENABLED,
        ## Misc. extra data.
        language_list=get_language_list(),
        needs_tutorial=needs_tutorial,
        first_in_realm=first_in_realm,
        prompt_for_invites=prompt_for_invites,
        furthest_read_time=furthest_read_time,
        bot_types=get_bot_types(user_profile),
        two_fa_enabled=two_fa_enabled,
        apps_page_url=get_apps_page_url(),
        show_billing=billing_info.show_billing,
        promote_sponsoring_zulip=promote_sponsoring_zulip_in_realm(realm),
        show_plans=billing_info.show_plans,
        show_invites=show_invites,
        show_webathena=user_permission_info.show_webathena,
        # Adding two_fa_enabled as condition saves us 3 queries when
        # 2FA is not enabled.
        two_fa_enabled_user=two_fa_enabled and bool(default_device(user_profile)),
        is_spectator=user_profile is None,
        # There is no event queue for spectators since
        # events support for spectators is not implemented yet.
        no_event_queue=user_profile is None,
        # Required for about_zulip.hbs
        zulip_merge_base=ZULIP_MERGE_BASE,
    )

    for field_name in register_ret.keys():
        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 = narrow_stream.recipient
        try:
            max_message_id = (
                Message.objects.filter(recipient=recipient).order_by("id").reverse()[0].id
            )
        except IndexError:
            max_message_id = -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"] = max_message_id
        page_params["enable_desktop_notifications"] = False

    page_params["translation_data"] = get_language_translation_data(request_language)

    return register_ret["queue_id"], page_params
Esempio n. 9
0
def home_real(request: 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[str]]
    narrow_stream = None
    narrow_topic = request.GET.get("topic")
    if request.GET.get("stream"):
        try:
            # TODO: We should support stream IDs and PMs here as well.
            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.warning("Invalid narrow requested, ignoring",
                            extra=dict(request=request))
        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,
                                      client_gravatar=True,
                                      notification_settings_null=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:  # nocoverage
        # TODO: Look into the history of last_reminder; we may have
        # eliminated that as a useful concept for non-bot users.
        user_profile.last_reminder = None
        user_profile.save(update_fields=["last_reminder"])

    # Brand new users get narrowed to PM with welcome-bot
    needs_tutorial = user_profile.tutorial_status == UserProfile.TUTORIAL_WAITING

    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:
        latest_read = get_usermessage_by_message_id(user_profile,
                                                    user_profile.pointer)
        if latest_read is None:
            # Don't completely fail if your saved pointer ID is invalid
            logging.warning("User %s has invalid pointer %s" %
                            (user_profile.id, user_profile.pointer))

    # We pick a language for the user as follows:
    # * First priority is the language in the URL, for debugging.
    # * If not in the URL, we use the language from the user's settings.
    request_language = translation.get_language_from_path(request.path_info)
    if request_language is None:
        request_language = register_ret['default_language']
    translation.activate(request_language)
    # We also save the language to the user's session, so that
    # something reasonable will happen in logged-in portico pages.
    request.session[
        translation.LANGUAGE_SESSION_KEY] = translation.get_language()

    two_fa_enabled = settings.TWO_FACTOR_AUTHENTICATION_ENABLED

    # Pass parameters to the client-side JavaScript code.
    # These end up in a global JavaScript Object named 'page_params'.
    page_params = dict(
        # Server settings.
        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,
        root_domain_uri=settings.ROOT_DOMAIN_URI,
        max_file_upload_size=settings.MAX_FILE_UPLOAD_SIZE,
        max_avatar_file_size=settings.MAX_AVATAR_FILE_SIZE,
        server_generation=settings.SERVER_GENERATION,
        save_stacktraces=settings.SAVE_FRONTEND_STACKTRACES,
        warn_no_email=settings.WARN_NO_EMAIL,
        server_inline_image_preview=settings.INLINE_IMAGE_PREVIEW,
        server_inline_url_embed_preview=settings.INLINE_URL_EMBED_PREVIEW,
        password_min_length=settings.PASSWORD_MIN_LENGTH,
        password_min_guesses=settings.PASSWORD_MIN_GUESSES,
        jitsi_server_url=settings.JITSI_SERVER_URL,
        search_pills_enabled=settings.SEARCH_PILLS_ENABLED,
        server_avatar_changes_disabled=settings.AVATAR_CHANGES_DISABLED,
        server_name_changes_disabled=settings.NAME_CHANGES_DISABLED,

        # 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,
        furthest_read_time=sent_time_in_epoch_seconds(latest_read),
        has_mobile_devices=num_push_devices_for_user(user_profile) > 0,
        bot_types=get_bot_types(user_profile),
        two_fa_enabled=two_fa_enabled,
        # Adding two_fa_enabled as condition saves us 3 queries when
        # 2FA is not enabled.
        two_fa_enabled_user=two_fa_enabled
        and bool(default_device(user_profile)),
    )

    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 = narrow_stream.recipient
        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, show_add_streams = compute_show_invites_and_add_streams(
        user_profile)

    show_billing = False
    show_plans = False
    if settings.CORPORATE_ENABLED:
        from corporate.models import Customer, CustomerPlan
        if user_profile.is_billing_admin or user_profile.is_realm_admin:
            customer = Customer.objects.filter(
                realm=user_profile.realm).first()
            if customer is not None and CustomerPlan.objects.filter(
                    customer=customer).exists():
                show_billing = True
        if user_profile.realm.plan_type == Realm.LIMITED:
            show_plans = True

    request._log_data['extra'] = "[%s]" % (register_ret["queue_id"], )

    page_params['translation_data'] = {}
    if request_language != 'en':
        page_params['translation_data'] = get_language_translation_data(
            request_language)

    csp_nonce = generate_random_token(48)
    emojiset = user_profile.emojiset
    if emojiset == UserProfile.TEXT_EMOJISET:
        # If current emojiset is `TEXT_EMOJISET`, then fallback to
        # GOOGLE_EMOJISET for picking which spritesheet's CSS to
        # include (and thus how to display emojis in the emoji picker
        # and composebox typeahead).
        emojiset = UserProfile.GOOGLE_BLOB_EMOJISET

    navbar_logo_url = compute_navbar_logo_url(page_params)

    response = render(
        request,
        'zerver/app/index.html',
        context={
            'user_profile': user_profile,
            'emojiset': emojiset,
            'page_params': page_params,
            'csp_nonce': csp_nonce,
            'avatar_url': avatar_url(user_profile),
            'show_debug': settings.DEBUG and ('show_debug' in request.GET),
            'search_pills_enabled': settings.SEARCH_PILLS_ENABLED,
            'show_invites': show_invites,
            'show_add_streams': show_add_streams,
            'show_billing': show_billing,
            'show_plans': show_plans,
            'is_admin': user_profile.is_realm_admin,
            'is_guest': user_profile.is_guest,
            'night_mode': user_profile.night_mode,
            'navbar_logo_url': navbar_logo_url,
            'show_webathena': user_profile.realm.webathena_enabled,
            'embedded': narrow_stream is not None,
            'invite_as': PreregistrationUser.INVITE_AS,
            'max_file_upload_size': settings.MAX_FILE_UPLOAD_SIZE,
        },
    )
    patch_cache_control(response,
                        no_cache=True,
                        no_store=True,
                        must_revalidate=True)
    return response
Esempio n. 10
0
def home_real(request: HttpRequest) -> HttpResponse:
    # Before we do any real work, check if the app is banned.
    client_user_agent = request.META.get("HTTP_USER_AGENT", "")
    (insecure_desktop_app, banned_desktop_app, auto_update_broken) = is_outdated_desktop_app(
        client_user_agent)
    if banned_desktop_app:
        return render(
            request,
            'zerver/insecure_desktop_app.html',
            context={
                "auto_update_broken": auto_update_broken,
            },
        )
    (unsupported_browser, browser_name) = is_unsupported_browser(client_user_agent)
    if unsupported_browser:
        return render(
            request,
            'zerver/unsupported_browser.html',
            context={
                "browser_name": browser_name,
            },
        )

    # 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

    if request.user.is_authenticated:
        user_profile = request.user
    else:  # nocoverage
        # This code path should not be reachable because of zulip_login_required above.
        user_profile = None

    # If a user hasn't signed the current Terms of Service, send them there
    if need_accept_tos(user_profile):
        return accounts_accept_terms(request)

    narrow, narrow_stream, narrow_topic = detect_narrowed_window(request, user_profile)

    client_capabilities = {
        'notification_settings_null': True,
        'bulk_message_deletion': True,
        'user_avatar_url_field_optional': True,
    }

    register_ret = do_events_register(user_profile, request.client,
                                      apply_markdown=True, client_gravatar=True,
                                      slim_presence=True,
                                      client_capabilities=client_capabilities,
                                      narrow=narrow)
    update_last_reminder(user_profile)

    if user_profile is not None:
        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()
        )
        needs_tutorial = user_profile.tutorial_status == UserProfile.TUTORIAL_WAITING

    else:  # nocoverage
        first_in_realm = False
        prompt_for_invites = False
        # The current tutorial doesn't super make sense for logged-out users.
        needs_tutorial = False

    furthest_read_time = get_furthest_read_time(user_profile)

    # We pick a language for the user as follows:
    # * First priority is the language in the URL, for debugging.
    # * If not in the URL, we use the language from the user's settings.
    request_language = translation.get_language_from_path(request.path_info)
    if request_language is None:
        request_language = register_ret['default_language']
    translation.activate(request_language)
    # We also save the language to the user's session, so that
    # something reasonable will happen in logged-in portico pages.
    request.session[translation.LANGUAGE_SESSION_KEY] = translation.get_language()

    two_fa_enabled = settings.TWO_FACTOR_AUTHENTICATION_ENABLED and user_profile is not None

    # Pass parameters to the client-side JavaScript code.
    # These end up in a global JavaScript Object named 'page_params'.
    page_params = dict(
        # Server settings.
        debug_mode                      = settings.DEBUG,
        test_suite                      = settings.TEST_SUITE,
        poll_timeout                    = settings.POLL_TIMEOUT,
        insecure_desktop_app            = insecure_desktop_app,
        login_page                      = settings.HOME_NOT_LOGGED_IN,
        root_domain_uri                 = settings.ROOT_DOMAIN_URI,
        save_stacktraces                = settings.SAVE_FRONTEND_STACKTRACES,
        warn_no_email                   = settings.WARN_NO_EMAIL,
        search_pills_enabled            = settings.SEARCH_PILLS_ENABLED,

        # Misc. extra data.
        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,
        furthest_read_time    = furthest_read_time,
        has_mobile_devices    = user_profile is not None and num_push_devices_for_user(user_profile) > 0,
        bot_types             = get_bot_types(user_profile),
        two_fa_enabled        = two_fa_enabled,
        # Adding two_fa_enabled as condition saves us 3 queries when
        # 2FA is not enabled.
        two_fa_enabled_user   = two_fa_enabled and bool(default_device(user_profile)),
    )

    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 = narrow_stream.recipient
        try:
            max_message_id = Message.objects.filter(recipient=recipient).order_by('id').reverse()[0].id
        except IndexError:
            max_message_id = -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"] = max_message_id
        page_params["enable_desktop_notifications"] = False

    statsd.incr('views.home')
    show_invites, show_add_streams = compute_show_invites_and_add_streams(user_profile)

    show_billing = False
    show_plans = False
    if settings.CORPORATE_ENABLED and user_profile is not None:
        from corporate.models import CustomerPlan, get_customer_by_realm
        if user_profile.has_billing_access:
            customer = get_customer_by_realm(user_profile.realm)
            if customer is not None:
                if customer.sponsorship_pending:
                    show_billing = True
                elif CustomerPlan.objects.filter(customer=customer).exists():
                    show_billing = True

        if user_profile.realm.plan_type == Realm.LIMITED:
            show_plans = True

    request._log_data['extra'] = "[{}]".format(register_ret["queue_id"])

    page_params['translation_data'] = {}
    if request_language != 'en':
        page_params['translation_data'] = get_language_translation_data(request_language)

    csp_nonce = generate_random_token(48)
    if user_profile is not None:
        color_scheme = user_profile.color_scheme
        is_guest = user_profile.is_guest
        is_realm_owner = user_profile.is_realm_owner
        is_realm_admin = user_profile.is_realm_admin
        show_webathena = user_profile.realm.webathena_enabled
    else:  # nocoverage
        color_scheme = UserProfile.COLOR_SCHEME_AUTOMATIC
        is_guest = False
        is_realm_admin = False
        is_realm_owner = False
        show_webathena = False

    navbar_logo_url = compute_navbar_logo_url(page_params)

    # print("----------------->")
    # new_realm_users = []
    # user_initial = user_profile.full_name[0]
    # pattern = '^{}'.format(user_initial)

    # for _ in range(len(page_params['realm_users'])):
    #     current_user_fullname = page_params['realm_users'][_]['full_name']
    #     initials_matched_user = re.match(pattern,current_user_fullname)
    #     if initials_matched_user:
    #         new_realm_users.append(page_params['realm_users'][_])


    # page_params['realm_users'] = new_realm_users
    # print(page_params['realm_users'])
    # print('\n')

    # print(page_params.keys())
    # print("-----------------> UserProfile objects")
    # print(UserProfile.objects.all())
    response = render(request, 'zerver/app/index.html',
                      context={'user_profile': user_profile,
                               'page_params': page_params,
                               'csp_nonce': csp_nonce,
                               'search_pills_enabled': settings.SEARCH_PILLS_ENABLED,
                               'show_invites': show_invites,
                               'show_add_streams': show_add_streams,
                               'show_billing': show_billing,
                               'corporate_enabled': settings.CORPORATE_ENABLED,
                               'show_plans': show_plans,
                               'is_owner': is_realm_owner,
                               'is_admin': is_realm_admin,
                               'is_guest': is_guest,
                               'color_scheme': color_scheme,
                               'navbar_logo_url': navbar_logo_url,
                               'show_webathena': show_webathena,
                               'embedded': narrow_stream is not None,
                               'invite_as': PreregistrationUser.INVITE_AS,
                               'max_file_upload_size_mib': settings.MAX_FILE_UPLOAD_SIZE,
                               })
    patch_cache_control(response, no_cache=True, no_store=True, must_revalidate=True)
    # print("########################### | These are page_params keys | ##############")
    # print(page_params.keys())
    # print("########################### | Realm Users | #############################")
    # print(page_params['realm_users'])
    # print("############################ | Presences |############################")
    # print("\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/")
    # print(page_params['presences'])
    return response