Exemple #1
0
def support(request: HttpRequest) -> HttpResponse:
    context = {}  # type: Dict[str, Any]
    if settings.BILLING_ENABLED and request.method == "POST":
        realm_id = request.POST.get("realm_id", None)
        realm = Realm.objects.get(id=realm_id)

        new_plan_type = request.POST.get("plan_type", None)
        if new_plan_type is not None:
            new_plan_type = int(new_plan_type)
            current_plan_type = realm.plan_type
            do_change_plan_type(realm, new_plan_type)
            msg = "Plan type of {} changed to {} from {} ".format(realm.name, get_plan_name(new_plan_type),
                                                                  get_plan_name(current_plan_type))
            context["plan_type_msg"] = msg

        new_discount = request.POST.get("discount", None)
        if new_discount is not None:
            new_discount = Decimal(new_discount)
            current_discount = get_discount_for_realm(realm)
            attach_discount_to_realm(realm, new_discount)
            msg = "Discount of {} changed to {} from {} ".format(realm.name, new_discount, current_discount)
            context["discount_msg"] = msg

    query = request.GET.get("q", None)
    if query:
        key_words = get_invitee_emails_set(query)

        users = UserProfile.objects.filter(email__in=key_words)
        if users:
            for user in users:
                user.realm.realm_icon_url = realm_icon_url(user.realm)
                user.realm.admins = UserProfile.objects.filter(realm=user.realm, is_realm_admin=True)
                user.realm.default_discount = get_discount_for_realm(user.realm)
            context["users"] = users

        realms = set(Realm.objects.filter(string_id__in=key_words))

        for key_word in key_words:
            try:
                URLValidator()(key_word)
                parse_result = urllib.parse.urlparse(key_word)
                hostname = parse_result.hostname
                if parse_result.port:
                    hostname = "{}:{}".format(hostname, parse_result.port)
                subdomain = get_subdomain_from_hostname(hostname)
                realm = get_realm(subdomain)
                if realm is not None:
                    realms.add(realm)
            except ValidationError:
                pass

        if realms:
            for realm in realms:
                realm.realm_icon_url = realm_icon_url(realm)
                realm.admins = UserProfile.objects.filter(realm=realm, is_realm_admin=True)
                realm.default_discount = get_discount_for_realm(realm)
            context["realms"] = realms
    return render(request, 'analytics/support.html', context=context)
Exemple #2
0
    def test_get_gravatar_icon(self) -> None:
        self.login(self.example_email("hamlet"))
        realm = get_realm('zulip')
        realm.icon_source = Realm.ICON_FROM_GRAVATAR
        realm.save()
        with self.settings(ENABLE_GRAVATAR=True):
            response = self.client_get("/json/realm/icon?foo=bar")
            redirect_url = response['Location']
            self.assertEqual(redirect_url, realm_icon_url(realm) + '&foo=bar')

        with self.settings(ENABLE_GRAVATAR=False):
            response = self.client_get("/json/realm/icon?foo=bar")
            redirect_url = response['Location']
            self.assertTrue(redirect_url.endswith(realm_icon_url(realm) + '&foo=bar'))
Exemple #3
0
    def test_get_gravatar_icon(self) -> None:
        self.login(self.example_email("hamlet"))
        realm = get_realm('zulip')
        realm.icon_source = Realm.ICON_FROM_GRAVATAR
        realm.save()
        with self.settings(ENABLE_GRAVATAR=True):
            response = self.client_get("/json/realm/icon?foo=bar")
            redirect_url = response['Location']
            self.assertEqual(redirect_url, realm_icon_url(realm) + '&foo=bar')

        with self.settings(ENABLE_GRAVATAR=False):
            response = self.client_get("/json/realm/icon?foo=bar")
            redirect_url = response['Location']
            self.assertTrue(redirect_url.endswith(realm_icon_url(realm) + '&foo=bar'))
Exemple #4
0
def finish_desktop_flow(request: HttpRequest, user_profile: UserProfile,
                        otp: str) -> HttpResponse:
    """
    The desktop otp flow returns to the app (through a zulip:// redirect)
    a token that allows obtaining (through log_into_subdomain) a logged in session
    for the user account we authenticated in this flow.
    The token can only be used once and within ExternalAuthResult.LOGIN_KEY_EXPIRATION_SECONDS
    of being created, as nothing more powerful is needed for the desktop flow
    and this ensures the key can only be used for completing this authentication attempt.
    """
    result = ExternalAuthResult(user_profile=user_profile)
    token = result.store_data()
    response = create_response_for_otp_flow(
        token,
        otp,
        user_profile,
        encrypted_key_field_name='otp_encrypted_login_key')
    browser_url = user_profile.realm.uri + reverse(
        'zerver.views.auth.log_into_subdomain', args=[token])
    context = {
        'desktop_url': response['Location'],
        'browser_url': browser_url,
        'realm_icon_url': realm_icon_url(user_profile.realm)
    }
    return render(request, 'zerver/desktop_redirect.html', context=context)
Exemple #5
0
def finish_desktop_flow(request: HttpRequest, user_profile: UserProfile,
                        otp: str) -> HttpResponse:
    """
    The desktop otp flow returns to the app (through the clipboard)
    a token that allows obtaining (through log_into_subdomain) a logged in session
    for the user account we authenticated in this flow.
    The token can only be used once and within ExternalAuthResult.LOGIN_KEY_EXPIRATION_SECONDS
    of being created, as nothing more powerful is needed for the desktop flow
    and this ensures the key can only be used for completing this authentication attempt.
    """
    result = ExternalAuthResult(user_profile=user_profile)
    token = result.store_data()
    key = bytes.fromhex(otp)
    iv = os.urandom(12)
    desktop_data = (iv + AESGCM(key).encrypt(iv, token.encode(), b"")).hex()
    context = {
        'desktop_data':
        desktop_data,
        'browser_url':
        reverse('zerver.views.auth.login_page',
                kwargs={'template_name': 'zerver/login.html'}),
        'realm_icon_url':
        realm_icon_url(user_profile.realm)
    }
    return render(request, 'zerver/desktop_redirect.html', context=context)
Exemple #6
0
def do_change_icon_source(
    realm: Realm, icon_source: str, *, acting_user: Optional[UserProfile]
) -> None:
    realm.icon_source = icon_source
    realm.icon_version += 1
    realm.save(update_fields=["icon_source", "icon_version"])

    event_time = timezone_now()
    RealmAuditLog.objects.create(
        realm=realm,
        event_type=RealmAuditLog.REALM_ICON_SOURCE_CHANGED,
        extra_data={"icon_source": icon_source, "icon_version": realm.icon_version},
        event_time=event_time,
        acting_user=acting_user,
    )

    event = dict(
        type="realm",
        op="update_dict",
        property="icon",
        data=dict(icon_source=realm.icon_source, icon_url=realm_icon_url(realm)),
    )
    transaction.on_commit(
        lambda: send_event(
            realm,
            event,
            active_user_ids(realm.id),
        )
    )
Exemple #7
0
    def test_get_realm_icon(self) -> None:
        self.login(self.example_email("hamlet"))

        realm = get_realm('zulip')
        realm.icon_source = Realm.ICON_UPLOADED
        realm.save()
        response = self.client_get("/json/realm/icon?foo=bar")
        redirect_url = response['Location']
        self.assertTrue(redirect_url.endswith(realm_icon_url(realm) + '&foo=bar'))
Exemple #8
0
    def test_get_realm_icon(self) -> None:
        self.login(self.example_email("hamlet"))

        realm = get_realm('zulip')
        realm.icon_source = Realm.ICON_UPLOADED
        realm.save()
        response = self.client_get("/json/realm/icon?foo=bar")
        redirect_url = response['Location']
        self.assertTrue(redirect_url.endswith(realm_icon_url(realm) + '&foo=bar'))
Exemple #9
0
def get_icon_backend(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
    url = realm_icon_url(user_profile.realm)

    # We can rely on the URL already having query parameters. Because
    # our templates depend on being able to use the ampersand to
    # add query parameters to our url, get_icon_url does '?version=version_number'
    # hacks to prevent us from having to jump through decode/encode hoops.
    url = append_url_query_string(url, request.META["QUERY_STRING"])
    return redirect(url)
def delete_icon_backend(request: HttpRequest,
                        user_profile: UserProfile) -> HttpResponse:
    # We don't actually delete the icon because it might still
    # be needed if the URL was cached and it is rewrited
    # in any case after next update.
    do_change_icon_source(user_profile.realm,
                          user_profile.realm.ICON_FROM_GRAVATAR)
    gravatar_url = realm_icon_url(user_profile.realm)
    json_result = dict(icon_url=gravatar_url, )
    return json_success(json_result)
Exemple #11
0
def get_icon_backend(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
    url = realm_icon_url(user_profile.realm)

    # We can rely on the url already having query parameters. Because
    # our templates depend on being able to use the ampersand to
    # add query parameters to our url, get_icon_url does '?version=version_number'
    # hacks to prevent us from having to jump through decode/encode hoops.
    assert '?' in url
    url += '&' + request.META['QUERY_STRING']
    return redirect(url)
Exemple #12
0
def delete_icon_backend(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
    # We don't actually delete the icon because it might still
    # be needed if the URL was cached and it is rewrited
    # in any case after next update.
    do_change_icon_source(user_profile.realm, user_profile.realm.ICON_FROM_GRAVATAR)
    gravatar_url = realm_icon_url(user_profile.realm)
    json_result = dict(
        icon_url=gravatar_url
    )
    return json_success(json_result)
Exemple #13
0
def get_icon_backend(request, user_profile):
    # type: (HttpRequest, UserProfile) -> HttpResponse
    url = realm_icon_url(user_profile.realm)

    # We can rely on the url already having query parameters. Because
    # our templates depend on being able to use the ampersand to
    # add query parameters to our url, get_icon_url does '?version=version_number'
    # hacks to prevent us from having to jump through decode/encode hoops.
    assert '?' in url
    url += '&' + request.META['QUERY_STRING']
    return redirect(url)
Exemple #14
0
def upload_icon(request, user_profile):
    # type: (HttpRequest, UserProfile) -> HttpResponse

    if len(request.FILES) != 1:
        return json_error(_("You must upload exactly one icon."))

    icon_file = list(request.FILES.values())[0]
    upload_icon_image(icon_file, user_profile)
    do_change_icon_source(user_profile.realm, user_profile.realm.ICON_UPLOADED)
    icon_url = realm_icon_url(user_profile.realm)

    json_result = dict(icon_url=icon_url)
    return json_success(json_result)
Exemple #15
0
    def test_delete_icon(self) -> None:
        """
        A DELETE request to /json/realm/icon should delete the realm icon and return gravatar URL
        """
        self.login(self.example_email("iago"))
        realm = get_realm('zulip')
        realm.icon_source = Realm.ICON_UPLOADED
        realm.save()

        result = self.client_delete("/json/realm/icon")

        self.assert_json_success(result)
        self.assertIn("icon_url", result.json())
        realm = get_realm('zulip')
        self.assertEqual(result.json()["icon_url"], realm_icon_url(realm))
        self.assertEqual(realm.icon_source, Realm.ICON_FROM_GRAVATAR)
Exemple #16
0
    def test_delete_icon(self) -> None:
        """
        A DELETE request to /json/realm/icon should delete the realm icon and return gravatar URL
        """
        self.login(self.example_email("iago"))
        realm = get_realm('zulip')
        realm.icon_source = Realm.ICON_UPLOADED
        realm.save()

        result = self.client_delete("/json/realm/icon")

        self.assert_json_success(result)
        self.assertIn("icon_url", result.json())
        realm = get_realm('zulip')
        self.assertEqual(result.json()["icon_url"], realm_icon_url(realm))
        self.assertEqual(realm.icon_source, Realm.ICON_FROM_GRAVATAR)
def upload_icon(request: HttpRequest,
                user_profile: UserProfile) -> HttpResponse:

    if len(request.FILES) != 1:
        return json_error(_("You must upload exactly one icon."))

    icon_file = list(request.FILES.values())[0]
    if ((settings.MAX_ICON_FILE_SIZE * 1024 * 1024) < icon_file.size):
        return json_error(
            _("Uploaded file is larger than the allowed limit of {} MiB").
            format(settings.MAX_ICON_FILE_SIZE, ))
    upload_icon_image(icon_file, user_profile)
    do_change_icon_source(user_profile.realm, user_profile.realm.ICON_UPLOADED)
    icon_url = realm_icon_url(user_profile.realm)

    json_result = dict(icon_url=icon_url, )
    return json_success(json_result)
Exemple #18
0
def upload_icon(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:

    if len(request.FILES) != 1:
        return json_error(_("You must upload exactly one icon."))

    icon_file = list(request.FILES.values())[0]
    if ((settings.MAX_ICON_FILE_SIZE * 1024 * 1024) < icon_file.size):
        return json_error(_("Uploaded file is larger than the allowed limit of %s MB") % (
            settings.MAX_ICON_FILE_SIZE))
    upload_icon_image(icon_file, user_profile)
    do_change_icon_source(user_profile.realm, user_profile.realm.ICON_UPLOADED)
    icon_url = realm_icon_url(user_profile.realm)

    json_result = dict(
        icon_url=icon_url
    )
    return json_success(json_result)
Exemple #19
0
def upload_icon(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:

    if len(request.FILES) != 1:
        raise JsonableError(_("You must upload exactly one icon."))

    icon_file = list(request.FILES.values())[0]
    assert isinstance(icon_file, UploadedFile)
    assert icon_file.size is not None
    if (settings.MAX_ICON_FILE_SIZE_MIB * 1024 * 1024) < icon_file.size:
        raise JsonableError(
            _("Uploaded file is larger than the allowed limit of {} MiB").format(
                settings.MAX_ICON_FILE_SIZE_MIB,
            )
        )
    upload_icon_image(icon_file, user_profile)
    do_change_icon_source(
        user_profile.realm, user_profile.realm.ICON_UPLOADED, acting_user=user_profile
    )
    icon_url = realm_icon_url(user_profile.realm)

    json_result = dict(
        icon_url=icon_url,
    )
    return json_success(request, data=json_result)
Exemple #20
0
def fetch_initial_state_data(
        user_profile: UserProfile,
        event_types: Optional[Iterable[str]],
        queue_id: str,
        client_gravatar: bool,
        include_subscribers: bool = True) -> Dict[str, Any]:
    state = {'queue_id': queue_id}  # type: Dict[str, Any]
    realm = user_profile.realm

    if event_types is None:
        # return True always
        want = always_want  # type: Callable[[str], bool]
    else:
        want = set(event_types).__contains__

    if want('alert_words'):
        state['alert_words'] = user_alert_words(user_profile)

    if want('custom_profile_fields'):
        fields = custom_profile_fields_for_realm(realm.id)
        state['custom_profile_fields'] = [f.as_dict() for f in fields]
        state[
            'custom_profile_field_types'] = CustomProfileField.FIELD_TYPE_CHOICES

    if want('hotspots'):
        state['hotspots'] = get_next_hotspots(user_profile)

    if want('message'):
        # The client should use get_messages() to fetch messages
        # starting with the max_message_id.  They will get messages
        # newer than that ID via get_events()
        messages = Message.objects.filter(
            usermessage__user_profile=user_profile).order_by('-id')[:1]
        if messages:
            state['max_message_id'] = messages[0].id
        else:
            state['max_message_id'] = -1

    if want('muted_topics'):
        state['muted_topics'] = get_topic_mutes(user_profile)

    if want('pointer'):
        state['pointer'] = user_profile.pointer

    if want('presence'):
        state['presences'] = get_status_dict(user_profile)

    if want('realm'):
        for property_name in Realm.property_types:
            state['realm_' + property_name] = getattr(realm, property_name)

        # Most state is handled via the property_types framework;
        # these manual entries are for those realm settings that don't
        # fit into that framework.
        state[
            'realm_authentication_methods'] = realm.authentication_methods_dict(
            )
        state['realm_allow_message_editing'] = realm.allow_message_editing
        state[
            'realm_allow_community_topic_editing'] = realm.allow_community_topic_editing
        state['realm_allow_message_deleting'] = realm.allow_message_deleting
        state[
            'realm_message_content_edit_limit_seconds'] = realm.message_content_edit_limit_seconds
        state[
            'realm_message_content_delete_limit_seconds'] = realm.message_content_delete_limit_seconds
        state['realm_icon_url'] = realm_icon_url(realm)
        state['realm_icon_source'] = realm.icon_source
        state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
        state['realm_bot_domain'] = realm.get_bot_domain()
        state['realm_uri'] = realm.uri
        state[
            'realm_available_video_chat_providers'] = realm.VIDEO_CHAT_PROVIDERS
        state['realm_presence_disabled'] = realm.presence_disabled
        state[
            'realm_digest_emails_enabled'] = realm.digest_emails_enabled and settings.SEND_DIGEST_EMAILS
        state['realm_is_zephyr_mirror_realm'] = realm.is_zephyr_mirror_realm
        state['realm_email_auth_enabled'] = email_auth_enabled(realm)
        state['realm_password_auth_enabled'] = password_auth_enabled(realm)
        state['realm_push_notifications_enabled'] = push_notifications_enabled(
        )
        if realm.notifications_stream and not realm.notifications_stream.deactivated:
            notifications_stream = realm.notifications_stream
            state['realm_notifications_stream_id'] = notifications_stream.id
        else:
            state['realm_notifications_stream_id'] = -1

        signup_notifications_stream = realm.get_signup_notifications_stream()
        if signup_notifications_stream:
            state[
                'realm_signup_notifications_stream_id'] = signup_notifications_stream.id
        else:
            state['realm_signup_notifications_stream_id'] = -1

    if want('realm_domains'):
        state['realm_domains'] = get_realm_domains(realm)

    if want('realm_emoji'):
        state['realm_emoji'] = realm.get_emoji()

    if want('realm_filters'):
        state['realm_filters'] = realm_filters_for_realm(realm.id)

    if want('realm_user_groups'):
        state['realm_user_groups'] = user_groups_in_realm_serialized(realm)

    if want('realm_user'):
        state['raw_users'] = get_raw_user_data(
            realm_id=realm.id,
            client_gravatar=client_gravatar,
        )

        # For the user's own avatar URL, we force
        # client_gravatar=False, since that saves some unnecessary
        # client-side code for handing medium-size avatars.  See #8253
        # for details.
        state['avatar_source'] = user_profile.avatar_source
        state['avatar_url_medium'] = avatar_url(
            user_profile,
            medium=True,
            client_gravatar=False,
        )
        state['avatar_url'] = avatar_url(
            user_profile,
            medium=False,
            client_gravatar=False,
        )

        state['can_create_streams'] = user_profile.can_create_streams()
        state['cross_realm_bots'] = list(get_cross_realm_dicts())
        state['is_admin'] = user_profile.is_realm_admin
        state['is_guest'] = user_profile.is_guest
        state['user_id'] = user_profile.id
        state['enter_sends'] = user_profile.enter_sends
        state['email'] = user_profile.email
        state['delivery_email'] = user_profile.delivery_email
        state['full_name'] = user_profile.full_name

    if want('realm_bot'):
        state['realm_bots'] = get_owned_bot_dicts(user_profile)

    # This does not yet have an apply_event counterpart, since currently,
    # new entries for EMBEDDED_BOTS can only be added directly in the codebase.
    if want('realm_embedded_bots'):
        realm_embedded_bots = []
        for bot in EMBEDDED_BOTS:
            realm_embedded_bots.append({
                'name':
                bot.name,
                'config':
                load_bot_config_template(bot.name)
            })
        state['realm_embedded_bots'] = realm_embedded_bots

    if want('subscription'):
        subscriptions, unsubscribed, never_subscribed = gather_subscriptions_helper(
            user_profile, include_subscribers=include_subscribers)
        state['subscriptions'] = subscriptions
        state['unsubscribed'] = unsubscribed
        state['never_subscribed'] = never_subscribed

    if want('update_message_flags') and want('message'):
        # Keeping unread_msgs updated requires both message flag updates and
        # message updates. This is due to the fact that new messages will not
        # generate a flag update so we need to use the flags field in the
        # message event.
        state['raw_unread_msgs'] = get_raw_unread_data(user_profile)

    if want('stream'):
        state['streams'] = do_get_streams(user_profile)
        state['stream_name_max_length'] = Stream.MAX_NAME_LENGTH
        state['stream_description_max_length'] = Stream.MAX_DESCRIPTION_LENGTH
    if want('default_streams'):
        state['realm_default_streams'] = streams_to_dicts_sorted(
            get_default_streams_for_realm(realm.id))
    if want('default_stream_groups'):
        state[
            'realm_default_stream_groups'] = default_stream_groups_to_dicts_sorted(
                get_default_stream_groups(realm))

    if want('update_display_settings'):
        for prop in UserProfile.property_types:
            state[prop] = getattr(user_profile, prop)
        state['emojiset_choices'] = user_profile.emojiset_choices()

    if want('update_global_notifications'):
        for notification in UserProfile.notification_setting_types:
            state[notification] = getattr(user_profile, notification)

    if want('zulip_version'):
        state['zulip_version'] = ZULIP_VERSION

    return state
Exemple #21
0
def fetch_initial_state_data(
        user_profile: UserProfile,
        event_types: Optional[Iterable[str]],
        queue_id: str,
        client_gravatar: bool,
        user_avatar_url_field_optional: bool,
        slim_presence: bool = False,
        include_subscribers: bool = True) -> Dict[str, Any]:
    state: Dict[str, Any] = {'queue_id': queue_id}
    realm = user_profile.realm

    if event_types is None:
        # return True always
        want: Callable[[str], bool] = always_want
    else:
        want = set(event_types).__contains__

    # Show the version info unconditionally.
    state['zulip_version'] = ZULIP_VERSION
    state['zulip_feature_level'] = API_FEATURE_LEVEL

    if want('alert_words'):
        state['alert_words'] = user_alert_words(user_profile)

    if want('custom_profile_fields'):
        fields = custom_profile_fields_for_realm(realm.id)
        state['custom_profile_fields'] = [f.as_dict() for f in fields]
        state[
            'custom_profile_field_types'] = CustomProfileField.FIELD_TYPE_CHOICES_DICT

    if want('hotspots'):
        state['hotspots'] = get_next_hotspots(user_profile)

    if want('message'):
        # The client should use get_messages() to fetch messages
        # starting with the max_message_id.  They will get messages
        # newer than that ID via get_events()
        user_messages = UserMessage.objects \
            .filter(user_profile=user_profile) \
            .order_by('-message_id') \
            .values('message_id')[:1]
        if user_messages:
            state['max_message_id'] = user_messages[0]['message_id']
        else:
            state['max_message_id'] = -1

    if want('muted_topics'):
        state['muted_topics'] = get_topic_mutes(user_profile)

    if want('presence'):
        state['presences'] = get_presences_for_realm(realm, user_profile,
                                                     slim_presence)

    if want('realm'):
        for property_name in Realm.property_types:
            state['realm_' + property_name] = getattr(realm, property_name)

        # Most state is handled via the property_types framework;
        # these manual entries are for those realm settings that don't
        # fit into that framework.
        state[
            'realm_authentication_methods'] = realm.authentication_methods_dict(
            )
        state['realm_allow_message_editing'] = realm.allow_message_editing
        state[
            'realm_allow_community_topic_editing'] = realm.allow_community_topic_editing
        state['realm_allow_message_deleting'] = realm.allow_message_deleting
        state[
            'realm_message_content_edit_limit_seconds'] = realm.message_content_edit_limit_seconds
        state[
            'realm_message_content_delete_limit_seconds'] = realm.message_content_delete_limit_seconds
        state['realm_community_topic_editing_limit_seconds'] = \
            Realm.DEFAULT_COMMUNITY_TOPIC_EDITING_LIMIT_SECONDS
        state['realm_icon_url'] = realm_icon_url(realm)
        state['realm_icon_source'] = realm.icon_source
        state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
        add_realm_logo_fields(state, realm)
        state['realm_bot_domain'] = realm.get_bot_domain()
        state['realm_uri'] = realm.uri
        state[
            'realm_available_video_chat_providers'] = realm.VIDEO_CHAT_PROVIDERS
        state['realm_presence_disabled'] = realm.presence_disabled
        state['settings_send_digest_emails'] = settings.SEND_DIGEST_EMAILS
        state[
            'realm_digest_emails_enabled'] = realm.digest_emails_enabled and settings.SEND_DIGEST_EMAILS
        state['realm_is_zephyr_mirror_realm'] = realm.is_zephyr_mirror_realm
        state['realm_email_auth_enabled'] = email_auth_enabled(realm)
        state['realm_password_auth_enabled'] = password_auth_enabled(realm)
        state['realm_push_notifications_enabled'] = push_notifications_enabled(
        )
        state['realm_upload_quota'] = realm.upload_quota_bytes()
        state['realm_plan_type'] = realm.plan_type
        state['zulip_plan_is_not_limited'] = realm.plan_type != Realm.LIMITED
        state['upgrade_text_for_wide_organization_logo'] = str(
            Realm.UPGRADE_TEXT_STANDARD)
        state['realm_default_external_accounts'] = DEFAULT_EXTERNAL_ACCOUNTS
        state['jitsi_server_url'] = settings.JITSI_SERVER_URL
        state['development_environment'] = settings.DEVELOPMENT
        state['server_generation'] = settings.SERVER_GENERATION
        state['password_min_length'] = settings.PASSWORD_MIN_LENGTH
        state['password_min_guesses'] = settings.PASSWORD_MIN_GUESSES
        state['max_file_upload_size_mib'] = settings.MAX_FILE_UPLOAD_SIZE
        state['max_avatar_file_size_mib'] = settings.MAX_AVATAR_FILE_SIZE
        state['server_inline_image_preview'] = settings.INLINE_IMAGE_PREVIEW
        state[
            'server_inline_url_embed_preview'] = settings.INLINE_URL_EMBED_PREVIEW
        state[
            'server_avatar_changes_disabled'] = settings.AVATAR_CHANGES_DISABLED
        state['server_name_changes_disabled'] = settings.NAME_CHANGES_DISABLED

        if realm.notifications_stream and not realm.notifications_stream.deactivated:
            notifications_stream = realm.notifications_stream
            state['realm_notifications_stream_id'] = notifications_stream.id
        else:
            state['realm_notifications_stream_id'] = -1

        signup_notifications_stream = realm.get_signup_notifications_stream()
        if signup_notifications_stream:
            state[
                'realm_signup_notifications_stream_id'] = signup_notifications_stream.id
        else:
            state['realm_signup_notifications_stream_id'] = -1

    if want('realm_domains'):
        state['realm_domains'] = get_realm_domains(realm)

    if want('realm_emoji'):
        state['realm_emoji'] = realm.get_emoji()

    if want('realm_filters'):
        state['realm_filters'] = realm_filters_for_realm(realm.id)

    if want('realm_user_groups'):
        state['realm_user_groups'] = user_groups_in_realm_serialized(realm)

    if want('realm_filtered_user'):
        state['filtered_users'] = get_filtered_user_data(
            realm,
            user_profile,
            client_gravatar=client_gravatar,
            user_avatar_url_field_optional=user_avatar_url_field_optional)
        # For the user's own avatar URL, we force
        # client_gravatar=False, since that saves some unnecessary
        # client-side code for handing medium-size avatars.  See #8253
        # for details.
        state['avatar_source'] = user_profile.avatar_source
        state['avatar_url_medium'] = avatar_url(
            user_profile,
            medium=True,
            client_gravatar=False,
        )
        state['avatar_url'] = avatar_url(
            user_profile,
            medium=False,
            client_gravatar=False,
        )

        state['can_create_streams'] = user_profile.can_create_streams()
        state[
            'can_subscribe_other_users'] = user_profile.can_subscribe_other_users(
            )
        state['cross_realm_bots'] = list(get_cross_realm_dicts())
        state['is_admin'] = user_profile.is_realm_admin
        state['is_owner'] = user_profile.is_realm_owner
        state['is_guest'] = user_profile.is_guest
        state['user_id'] = user_profile.id
        state['enter_sends'] = user_profile.enter_sends
        state['email'] = user_profile.email
        state['delivery_email'] = user_profile.delivery_email
        state['full_name'] = user_profile.full_name

    if want('realm_user'):
        state['raw_users'] = get_raw_user_data(
            realm,
            user_profile,
            client_gravatar=client_gravatar,
            user_avatar_url_field_optional=user_avatar_url_field_optional)

        # For the user's own avatar URL, we force
        # client_gravatar=False, since that saves some unnecessary
        # client-side code for handing medium-size avatars.  See #8253
        # for details.
        state['avatar_source'] = user_profile.avatar_source
        state['avatar_url_medium'] = avatar_url(
            user_profile,
            medium=True,
            client_gravatar=False,
        )
        state['avatar_url'] = avatar_url(
            user_profile,
            medium=False,
            client_gravatar=False,
        )

        state['can_create_streams'] = user_profile.can_create_streams()
        state[
            'can_subscribe_other_users'] = user_profile.can_subscribe_other_users(
            )
        state['cross_realm_bots'] = list(get_cross_realm_dicts())
        state['is_admin'] = user_profile.is_realm_admin
        state['is_owner'] = user_profile.is_realm_owner
        state['is_guest'] = user_profile.is_guest
        state['user_id'] = user_profile.id
        state['enter_sends'] = user_profile.enter_sends
        state['email'] = user_profile.email
        state['delivery_email'] = user_profile.delivery_email
        state['full_name'] = user_profile.full_name

    if want('realm_bot'):
        state['realm_bots'] = get_owned_bot_dicts(user_profile)

    # This does not yet have an apply_event counterpart, since currently,
    # new entries for EMBEDDED_BOTS can only be added directly in the codebase.
    if want('realm_embedded_bots'):
        realm_embedded_bots = []
        for bot in EMBEDDED_BOTS:
            realm_embedded_bots.append({
                'name':
                bot.name,
                'config':
                load_bot_config_template(bot.name)
            })
        state['realm_embedded_bots'] = realm_embedded_bots

    # This does not have an apply_events counterpart either since
    # this data is mostly static.
    if want('realm_incoming_webhook_bots'):
        realm_incoming_webhook_bots = []
        for integration in WEBHOOK_INTEGRATIONS:
            realm_incoming_webhook_bots.append({
                'name': integration.name,
                'config': {c[1]: c[0]
                           for c in integration.config_options},
            })
        state['realm_incoming_webhook_bots'] = realm_incoming_webhook_bots

    if want('recent_private_conversations'):
        # A data structure containing records of this form:
        #
        #   [{'max_message_id': 700175, 'user_ids': [801]}]
        #
        # for all recent private message conversations, ordered by the
        # highest message ID in the conversation.  The user_ids list
        # is the list of users other than the current user in the
        # private message conversation (so it is [] for PMs to self).
        # Note that raw_recent_private_conversations is an
        # intermediate form as a dictionary keyed by recipient_id,
        # which is more efficient to update, and is rewritten to the
        # final format in post_process_state.
        state[
            'raw_recent_private_conversations'] = get_recent_private_conversations(
                user_profile)

    if want('subscription'):
        subscriptions, unsubscribed, never_subscribed = gather_subscriptions_helper(
            user_profile, include_subscribers=include_subscribers)
        state['subscriptions'] = subscriptions
        state['unsubscribed'] = unsubscribed
        state['never_subscribed'] = never_subscribed

    if want('update_message_flags') and want('message'):
        # Keeping unread_msgs updated requires both message flag updates and
        # message updates. This is due to the fact that new messages will not
        # generate a flag update so we need to use the flags field in the
        # message event.
        state['raw_unread_msgs'] = get_raw_unread_data(user_profile)

    if want('starred_messages'):
        state['starred_messages'] = get_starred_message_ids(user_profile)

    if want('stream'):
        state['streams'] = do_get_streams(user_profile)
        state['stream_name_max_length'] = Stream.MAX_NAME_LENGTH
        state['stream_description_max_length'] = Stream.MAX_DESCRIPTION_LENGTH
    if want('default_streams'):
        if user_profile.is_guest:
            state['realm_default_streams'] = []
        else:
            state['realm_default_streams'] = streams_to_dicts_sorted(
                get_default_streams_for_realm(realm.id))
    if want('default_stream_groups'):
        if user_profile.is_guest:
            state['realm_default_stream_groups'] = []
        else:
            state[
                'realm_default_stream_groups'] = default_stream_groups_to_dicts_sorted(
                    get_default_stream_groups(realm))

    if want('stop_words'):
        state['stop_words'] = read_stop_words()

    if want('update_display_settings'):
        for prop in UserProfile.property_types:
            state[prop] = getattr(user_profile, prop)
        state['emojiset_choices'] = user_profile.emojiset_choices()

    if want('update_global_notifications'):
        for notification in UserProfile.notification_setting_types:
            state[notification] = getattr(user_profile, notification)
        state[
            'available_notification_sounds'] = get_available_notification_sounds(
            )

    if want('user_status'):
        state['user_status'] = get_user_info_dict(realm_id=realm.id)

    if want('video_calls'):
        state['has_zoom_token'] = user_profile.zoom_token is not None

    return state
Exemple #22
0
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

    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(
        # 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,
        server_generation=settings.SERVER_GENERATION,
        use_websockets=settings.USE_WEBSOCKETS,
        save_stacktraces=settings.SAVE_FRONTEND_STACKTRACES,

        # realm data.
        # TODO: Move all of these data to register_ret and pull from there
        realm_uri=user_profile.realm.uri,
        password_auth_enabled=password_auth_enabled(user_profile.realm),
        domain=user_profile.realm.domain,
        domains=list_of_domains_for_realm(user_profile.realm),
        realm_icon_url=realm_icon_url(user_profile.realm),
        realm_icon_source=user_profile.realm.icon_source,
        name_changes_disabled=name_changes_disabled(user_profile.realm),
        mandatory_topics=user_profile.realm.mandatory_topics,
        show_digest_email=user_profile.realm.show_digest_email,
        realm_presence_disabled=user_profile.realm.presence_disabled,
        is_zephyr_mirror_realm=user_profile.realm.is_zephyr_mirror_realm,

        # user_profile data.
        # TODO: Move all of these data to register_ret and pull from there
        fullname=user_profile.full_name,
        email=user_profile.email,
        enter_sends=user_profile.enter_sends,
        user_id=user_profile.id,
        is_admin=user_profile.is_realm_admin,
        can_create_streams=user_profile.can_create_streams(),
        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),
        avatar_source=user_profile.avatar_source,

        # 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,
        pm_content_in_desktop_notifications=user_profile.
        pm_content_in_desktop_notifications,
        enable_offline_push_notifications=user_profile.
        enable_offline_push_notifications,
        enable_online_push_notifications=user_profile.
        enable_online_push_notifications,
        enable_digest_emails=user_profile.enable_digest_emails,

        # Realm foreign key data from register_ret.
        # TODO: Rename these to match register_ret values.
        subbed_info=register_ret['subscriptions'],
        unsubbed_info=register_ret['unsubscribed'],
        neversubbed_info=register_ret['never_subscribed'],
        people_list=register_ret['realm_users'],
        bot_list=register_ret['realm_bots'],
        initial_pointer=register_ret['pointer'],
        initial_presences=register_ret['presences'],
        event_queue_id=register_ret['queue_id'],

        # 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,
        notifications_stream=notifications_stream,
        cross_realm_bots=list(get_cross_realm_dicts()),
        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,
    )

    # These fields will be automatically copied from register_ret into
    # page_params.  It is a goal to move more of the page_params list
    # into this sort of cleaner structure.
    page_params_core_fields = [
        'alert_words',
        'attachments',
        'default_language',
        'last_event_id',
        'left_side_userlist',
        'max_message_id',
        'muted_topics',
        'realm_add_emoji_by_admins_only',
        'realm_allow_message_editing',
        'realm_authentication_methods',
        'realm_create_stream_by_admins_only',
        'realm_default_language',
        'realm_default_streams',
        'realm_emoji',
        'realm_message_content_edit_limit_seconds',
        'realm_name',
        'realm_invite_by_admins_only',
        'realm_invite_required',
        'realm_filters',
        'realm_restricted_to_domain',
        'realm_waiting_period_threshold',
        'referrals',
        'twenty_four_hour_time',
        'zulip_version',
    ]

    for field_name in page_params_core_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["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
Exemple #23
0
def fetch_initial_state_data(user_profile: UserProfile,
                             event_types: Optional[Iterable[str]],
                             queue_id: str, client_gravatar: bool,
                             include_subscribers: bool = True) -> Dict[str, Any]:
    state = {'queue_id': queue_id}  # type: Dict[str, Any]
    realm = user_profile.realm

    if event_types is None:
        # return True always
        want = always_want  # type: Callable[[str], bool]
    else:
        want = set(event_types).__contains__

    if want('alert_words'):
        state['alert_words'] = user_alert_words(user_profile)

    if want('custom_profile_fields'):
        fields = custom_profile_fields_for_realm(realm.id)
        state['custom_profile_fields'] = [f.as_dict() for f in fields]
        state['custom_profile_field_types'] = CustomProfileField.FIELD_TYPE_CHOICES_DICT

    if want('hotspots'):
        state['hotspots'] = get_next_hotspots(user_profile)

    if want('message'):
        # The client should use get_messages() to fetch messages
        # starting with the max_message_id.  They will get messages
        # newer than that ID via get_events()
        messages = Message.objects.filter(usermessage__user_profile=user_profile).order_by('-id')[:1]
        if messages:
            state['max_message_id'] = messages[0].id
        else:
            state['max_message_id'] = -1

    if want('muted_topics'):
        state['muted_topics'] = get_topic_mutes(user_profile)

    if want('pointer'):
        state['pointer'] = user_profile.pointer

    if want('presence'):
        state['presences'] = get_status_dict(user_profile)

    if want('realm'):
        for property_name in Realm.property_types:
            state['realm_' + property_name] = getattr(realm, property_name)

        # Most state is handled via the property_types framework;
        # these manual entries are for those realm settings that don't
        # fit into that framework.
        state['realm_authentication_methods'] = realm.authentication_methods_dict()
        state['realm_allow_message_editing'] = realm.allow_message_editing
        state['realm_allow_community_topic_editing'] = realm.allow_community_topic_editing
        state['realm_allow_message_deleting'] = realm.allow_message_deleting
        state['realm_message_content_edit_limit_seconds'] = realm.message_content_edit_limit_seconds
        state['realm_message_content_delete_limit_seconds'] = realm.message_content_delete_limit_seconds
        state['realm_icon_url'] = realm_icon_url(realm)
        state['realm_icon_source'] = realm.icon_source
        state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
        state['realm_logo_url'] = realm_logo_url(realm)
        state['realm_logo_source'] = realm.logo_source
        state['max_logo_file_size'] = settings.MAX_LOGO_FILE_SIZE
        state['realm_bot_domain'] = realm.get_bot_domain()
        state['realm_uri'] = realm.uri
        state['realm_available_video_chat_providers'] = realm.VIDEO_CHAT_PROVIDERS
        state['realm_presence_disabled'] = realm.presence_disabled
        state['realm_digest_emails_enabled'] = realm.digest_emails_enabled and settings.SEND_DIGEST_EMAILS
        state['realm_is_zephyr_mirror_realm'] = realm.is_zephyr_mirror_realm
        state['realm_email_auth_enabled'] = email_auth_enabled(realm)
        state['realm_password_auth_enabled'] = password_auth_enabled(realm)
        state['realm_push_notifications_enabled'] = push_notifications_enabled()
        if realm.notifications_stream and not realm.notifications_stream.deactivated:
            notifications_stream = realm.notifications_stream
            state['realm_notifications_stream_id'] = notifications_stream.id
        else:
            state['realm_notifications_stream_id'] = -1

        signup_notifications_stream = realm.get_signup_notifications_stream()
        if signup_notifications_stream:
            state['realm_signup_notifications_stream_id'] = signup_notifications_stream.id
        else:
            state['realm_signup_notifications_stream_id'] = -1

    if want('realm_domains'):
        state['realm_domains'] = get_realm_domains(realm)

    if want('realm_emoji'):
        state['realm_emoji'] = realm.get_emoji()

    if want('realm_filters'):
        state['realm_filters'] = realm_filters_for_realm(realm.id)

    if want('realm_user_groups'):
        state['realm_user_groups'] = user_groups_in_realm_serialized(realm)

    if want('realm_user'):
        state['raw_users'] = get_raw_user_data(
            realm_id=realm.id,
            client_gravatar=client_gravatar,
        )

        # For the user's own avatar URL, we force
        # client_gravatar=False, since that saves some unnecessary
        # client-side code for handing medium-size avatars.  See #8253
        # for details.
        state['avatar_source'] = user_profile.avatar_source
        state['avatar_url_medium'] = avatar_url(
            user_profile,
            medium=True,
            client_gravatar=False,
        )
        state['avatar_url'] = avatar_url(
            user_profile,
            medium=False,
            client_gravatar=False,
        )

        state['can_create_streams'] = user_profile.can_create_streams()
        state['can_subscribe_other_users'] = user_profile.can_subscribe_other_users()
        state['cross_realm_bots'] = list(get_cross_realm_dicts())
        state['is_admin'] = user_profile.is_realm_admin
        state['is_guest'] = user_profile.is_guest
        state['user_id'] = user_profile.id
        state['enter_sends'] = user_profile.enter_sends
        state['email'] = user_profile.email
        state['delivery_email'] = user_profile.delivery_email
        state['full_name'] = user_profile.full_name

    if want('realm_bot'):
        state['realm_bots'] = get_owned_bot_dicts(user_profile)

    # This does not yet have an apply_event counterpart, since currently,
    # new entries for EMBEDDED_BOTS can only be added directly in the codebase.
    if want('realm_embedded_bots'):
        realm_embedded_bots = []
        for bot in EMBEDDED_BOTS:
            realm_embedded_bots.append({'name': bot.name,
                                        'config': load_bot_config_template(bot.name)})
        state['realm_embedded_bots'] = realm_embedded_bots

    if want('subscription'):
        subscriptions, unsubscribed, never_subscribed = gather_subscriptions_helper(
            user_profile, include_subscribers=include_subscribers)
        state['subscriptions'] = subscriptions
        state['unsubscribed'] = unsubscribed
        state['never_subscribed'] = never_subscribed

    if want('update_message_flags') and want('message'):
        # Keeping unread_msgs updated requires both message flag updates and
        # message updates. This is due to the fact that new messages will not
        # generate a flag update so we need to use the flags field in the
        # message event.
        state['raw_unread_msgs'] = get_raw_unread_data(user_profile)

    if want('starred_messages'):
        state['starred_messages'] = get_starred_message_ids(user_profile)

    if want('stream'):
        state['streams'] = do_get_streams(user_profile)
        state['stream_name_max_length'] = Stream.MAX_NAME_LENGTH
        state['stream_description_max_length'] = Stream.MAX_DESCRIPTION_LENGTH
    if want('default_streams'):
        state['realm_default_streams'] = streams_to_dicts_sorted(
            get_default_streams_for_realm(realm.id))
    if want('default_stream_groups'):
        state['realm_default_stream_groups'] = default_stream_groups_to_dicts_sorted(
            get_default_stream_groups(realm))

    if want('update_display_settings'):
        for prop in UserProfile.property_types:
            state[prop] = getattr(user_profile, prop)
        state['emojiset_choices'] = user_profile.emojiset_choices()

    if want('update_global_notifications'):
        for notification in UserProfile.notification_setting_types:
            state[notification] = getattr(user_profile, notification)
        state['available_notification_sounds'] = get_available_notification_sounds()

    if want('user_status'):
        state['away_user_ids'] = sorted(list(get_away_user_ids(realm_id=realm.id)))

    if want('zulip_version'):
        state['zulip_version'] = ZULIP_VERSION

    return state
Exemple #24
0
def fetch_initial_state_data(user_profile,
                             event_types,
                             queue_id,
                             include_subscribers=True):
    # type: (UserProfile, Optional[Iterable[str]], str, bool) -> Dict[str, Any]
    state = {'queue_id': queue_id}  # type: Dict[str, Any]

    if event_types is None:
        want = lambda msg_type: True
    else:
        want = set(event_types).__contains__

    if want('alert_words'):
        state['alert_words'] = user_alert_words(user_profile)

    if want('custom_profile_fields'):
        fields = custom_profile_fields_for_realm(user_profile.realm.id)
        state['custom_profile_fields'] = [f.as_dict() for f in fields]

    if want('attachments'):
        state['attachments'] = user_attachments(user_profile)

    if want('hotspots'):
        state['hotspots'] = get_next_hotspots(user_profile)

    if want('message'):
        # The client should use get_messages() to fetch messages
        # starting with the max_message_id.  They will get messages
        # newer than that ID via get_events()
        messages = Message.objects.filter(
            usermessage__user_profile=user_profile).order_by('-id')[:1]
        if messages:
            state['max_message_id'] = messages[0].id
        else:
            state['max_message_id'] = -1

    if want('muted_topics'):
        state['muted_topics'] = ujson.loads(user_profile.muted_topics)

    if want('pointer'):
        state['pointer'] = user_profile.pointer

    if want('presence'):
        state['presences'] = get_status_dict(user_profile)

    if want('realm'):
        for property_name in Realm.property_types:
            state['realm_' + property_name] = getattr(user_profile.realm,
                                                      property_name)

        # Most state is handled via the property_types framework;
        # these manual entries are for those realm settings that don't
        # fit into that framework.
        state[
            'realm_authentication_methods'] = user_profile.realm.authentication_methods_dict(
            )
        state[
            'realm_allow_message_editing'] = user_profile.realm.allow_message_editing
        state[
            'realm_message_content_edit_limit_seconds'] = user_profile.realm.message_content_edit_limit_seconds
        state['realm_icon_url'] = realm_icon_url(user_profile.realm)
        state['realm_icon_source'] = user_profile.realm.icon_source
        state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
        state['realm_bot_domain'] = user_profile.realm.get_bot_domain()
        state['realm_uri'] = user_profile.realm.uri
        state['realm_presence_disabled'] = user_profile.realm.presence_disabled
        state['realm_show_digest_email'] = user_profile.realm.show_digest_email
        state[
            'realm_is_zephyr_mirror_realm'] = user_profile.realm.is_zephyr_mirror_realm
        state['realm_password_auth_enabled'] = password_auth_enabled(
            user_profile.realm)
        if user_profile.realm.notifications_stream and not user_profile.realm.notifications_stream.deactivated:
            notifications_stream = user_profile.realm.notifications_stream
            state['realm_notifications_stream_id'] = notifications_stream.id
        else:
            state['realm_notifications_stream_id'] = -1

    if want('realm_domains'):
        state['realm_domains'] = get_realm_domains(user_profile.realm)

    if want('realm_emoji'):
        state['realm_emoji'] = user_profile.realm.get_emoji()

    if want('realm_filters'):
        state['realm_filters'] = realm_filters_for_realm(user_profile.realm_id)

    if want('realm_user'):
        state['realm_users'] = get_realm_user_dicts(user_profile)
        state['avatar_source'] = user_profile.avatar_source
        state['avatar_url_medium'] = avatar_url(user_profile, medium=True)
        state['avatar_url'] = avatar_url(user_profile)
        state['can_create_streams'] = user_profile.can_create_streams()
        state['cross_realm_bots'] = list(get_cross_realm_dicts())
        state['is_admin'] = user_profile.is_realm_admin
        state['user_id'] = user_profile.id
        state['enter_sends'] = user_profile.enter_sends
        state['email'] = user_profile.email
        state['full_name'] = user_profile.full_name

    if want('realm_bot'):
        state['realm_bots'] = get_owned_bot_dicts(user_profile)

    if want('subscription'):
        subscriptions, unsubscribed, never_subscribed = gather_subscriptions_helper(
            user_profile, include_subscribers=include_subscribers)
        state['subscriptions'] = subscriptions
        state['unsubscribed'] = unsubscribed
        state['never_subscribed'] = never_subscribed

    if want('update_message_flags') and want('message'):
        # Keeping unread_msgs updated requires both message flag updates and
        # message updates. This is due to the fact that new messages will not
        # generate a flag update so we need to use the flags field in the
        # message event.
        state['unread_msgs'] = get_unread_message_ids_per_recipient(
            user_profile)

    if want('stream'):
        state['streams'] = do_get_streams(user_profile)
    if want('default_streams'):
        state['realm_default_streams'] = streams_to_dicts_sorted(
            get_default_streams_for_realm(user_profile.realm))

    if want('update_display_settings'):
        for prop in UserProfile.property_types:
            state[prop] = getattr(user_profile, prop)
        state['emojiset_choices'] = user_profile.emojiset_choices()
        state['autoscroll_forever'] = user_profile.autoscroll_forever

    if want('update_global_notifications'):
        for notification in UserProfile.notification_setting_types:
            state[notification] = getattr(user_profile, notification)
        state[
            'default_desktop_notifications'] = user_profile.default_desktop_notifications

    if want('zulip_version'):
        state['zulip_version'] = ZULIP_VERSION

    return state
Exemple #25
0
def fetch_initial_state_data(
    user_profile: Optional[UserProfile],
    *,
    realm: Optional[Realm] = None,
    event_types: Optional[Iterable[str]] = None,
    queue_id: Optional[str] = "",
    client_gravatar: bool = False,
    user_avatar_url_field_optional: bool = False,
    slim_presence: bool = False,
    include_subscribers: bool = True,
    include_streams: bool = True,
) -> Dict[str, Any]:
    """When `event_types` is None, fetches the core data powering the
    webapp's `page_params` and `/api/v1/register` (for mobile/terminal
    apps).  Can also fetch a subset as determined by `event_types`.

    The user_profile=None code path is used for logged-out public
    access to streams with is_web_public=True.

    Whenever you add new code to this function, you should also add
    corresponding events for changes in the data structures and new
    code to apply_events (and add a test in test_events.py).
    """
    if realm is None:
        assert user_profile is not None
        realm = user_profile.realm

    state: Dict[str, Any] = {'queue_id': queue_id}

    if event_types is None:
        # return True always
        want: Callable[[str], bool] = always_want
    else:
        want = set(event_types).__contains__

    # Show the version info unconditionally.
    state['zulip_version'] = ZULIP_VERSION
    state['zulip_feature_level'] = API_FEATURE_LEVEL

    if want('alert_words'):
        state['alert_words'] = [] if user_profile is None else user_alert_words(user_profile)

    if want('custom_profile_fields'):
        fields = custom_profile_fields_for_realm(realm.id)
        state['custom_profile_fields'] = [f.as_dict() for f in fields]
        state['custom_profile_field_types'] = {
            item[4]: {"id": item[0], "name": str(item[1])} for item in CustomProfileField.ALL_FIELD_TYPES
        }

    if want('hotspots'):
        # Even if we offered special hotspots for guests without an
        # account, we'd maybe need to store their state using cookies
        # or local storage, rather than in the database.
        state['hotspots'] = [] if user_profile is None else get_next_hotspots(user_profile)

    if want('message'):
        # Since the introduction of `anchor="latest"` in the API,
        # `max_message_id` is primarily used for generating `local_id`
        # values that are higher than this.  We likely can eventually
        # remove this parameter from the API.
        user_messages = []
        if user_profile is not None:
            user_messages = UserMessage.objects \
                .filter(user_profile=user_profile) \
                .order_by('-message_id') \
                .values('message_id')[:1]
        if user_messages:
            state['max_message_id'] = user_messages[0]['message_id']
        else:
            state['max_message_id'] = -1

    if want('muted_topics'):
        state['muted_topics'] = [] if user_profile is None else get_topic_mutes(user_profile)

    if want('presence'):
        state['presences'] = {} if user_profile is None else get_presences_for_realm(realm, slim_presence)

    if want('realm'):
        for property_name in Realm.property_types:
            state['realm_' + property_name] = getattr(realm, property_name)

        # Most state is handled via the property_types framework;
        # these manual entries are for those realm settings that don't
        # fit into that framework.
        state['realm_authentication_methods'] = realm.authentication_methods_dict()

        # We pretend these features are disabled because guests can't
        # access them.  In the future, we may want to move this logic
        # to the frontends, so that we can correctly display what
        # these fields are in the settings.
        state['realm_allow_message_editing'] = False if user_profile is None else realm.allow_message_editing
        state['realm_allow_community_topic_editing'] = False if user_profile is None else realm.allow_community_topic_editing
        state['realm_allow_message_deleting'] = False if user_profile is None else realm.allow_message_deleting

        state['realm_message_content_edit_limit_seconds'] = realm.message_content_edit_limit_seconds
        state['realm_message_content_delete_limit_seconds'] = realm.message_content_delete_limit_seconds
        state['realm_community_topic_editing_limit_seconds'] = \
            Realm.DEFAULT_COMMUNITY_TOPIC_EDITING_LIMIT_SECONDS

        # This setting determines whether to send presence and also
        # whether to display of users list in the right sidebar; we
        # want both behaviors for logged-out users.  We may in the
        # future choose to move this logic to the frontend.
        state['realm_presence_disabled'] = True if user_profile is None else realm.presence_disabled

        state['realm_icon_url'] = realm_icon_url(realm)
        state['realm_icon_source'] = realm.icon_source
        state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
        add_realm_logo_fields(state, realm)
        state['realm_bot_domain'] = realm.get_bot_domain()
        state['realm_uri'] = realm.uri
        state['realm_available_video_chat_providers'] = realm.VIDEO_CHAT_PROVIDERS
        state['settings_send_digest_emails'] = settings.SEND_DIGEST_EMAILS
        state['realm_digest_emails_enabled'] = realm.digest_emails_enabled and settings.SEND_DIGEST_EMAILS
        state['realm_is_zephyr_mirror_realm'] = realm.is_zephyr_mirror_realm
        state['realm_email_auth_enabled'] = email_auth_enabled(realm)
        state['realm_password_auth_enabled'] = password_auth_enabled(realm)
        state['realm_push_notifications_enabled'] = push_notifications_enabled()
        state['realm_upload_quota'] = realm.upload_quota_bytes()
        state['realm_plan_type'] = realm.plan_type
        state['zulip_plan_is_not_limited'] = realm.plan_type != Realm.LIMITED
        state['upgrade_text_for_wide_organization_logo'] = str(Realm.UPGRADE_TEXT_STANDARD)
        state['realm_default_external_accounts'] = DEFAULT_EXTERNAL_ACCOUNTS
        state['jitsi_server_url']                = settings.JITSI_SERVER_URL.rstrip('/')
        state['development_environment']         = settings.DEVELOPMENT
        state['server_generation']               = settings.SERVER_GENERATION
        state['password_min_length']             = settings.PASSWORD_MIN_LENGTH
        state['password_min_guesses']            = settings.PASSWORD_MIN_GUESSES
        state['max_file_upload_size_mib']        = settings.MAX_FILE_UPLOAD_SIZE
        state['max_avatar_file_size_mib']        = settings.MAX_AVATAR_FILE_SIZE
        state['server_inline_image_preview']     = settings.INLINE_IMAGE_PREVIEW
        state['server_inline_url_embed_preview'] = settings.INLINE_URL_EMBED_PREVIEW
        state['server_avatar_changes_disabled']  = settings.AVATAR_CHANGES_DISABLED
        state['server_name_changes_disabled']    = settings.NAME_CHANGES_DISABLED

        if realm.notifications_stream and not realm.notifications_stream.deactivated:
            notifications_stream = realm.notifications_stream
            state['realm_notifications_stream_id'] = notifications_stream.id
        else:
            state['realm_notifications_stream_id'] = -1

        signup_notifications_stream = realm.get_signup_notifications_stream()
        if signup_notifications_stream:
            state['realm_signup_notifications_stream_id'] = signup_notifications_stream.id
        else:
            state['realm_signup_notifications_stream_id'] = -1

    if want('realm_domains'):
        state['realm_domains'] = get_realm_domains(realm)

    if want('realm_emoji'):
        state['realm_emoji'] = realm.get_emoji()

    if want('realm_filters'):
        state['realm_filters'] = realm_filters_for_realm(realm.id)

    if want('realm_user_groups'):
        state['realm_user_groups'] = user_groups_in_realm_serialized(realm)

    if user_profile is not None:
        settings_user = user_profile
    else:
        # When UserProfile=None, we want to serve the values for various
        # settings as the defaults.  Instead of copying the default values
        # from models.py here, we access these default values from a
        # temporary UserProfile object that will not be saved to the database.
        #
        # We also can set various fields to avoid duplicating code
        # unnecessarily.
        settings_user = UserProfile(
            full_name="Anonymous User",
            email="*****@*****.**",
            delivery_email="*****@*****.**",
            realm=realm,
            # We tag logged-out users as guests because most guest
            # restrictions apply to these users as well, and it lets
            # us avoid unnecessary conditionals.
            role=UserProfile.ROLE_GUEST,
            avatar_source=UserProfile.AVATAR_FROM_GRAVATAR,
            # ID=0 is not used in real Zulip databases, ensuring this is unique.
            id=0,
        )
    if want('realm_user'):
        state['raw_users'] = get_raw_user_data(realm, user_profile,
                                               client_gravatar=client_gravatar,
                                               user_avatar_url_field_optional=user_avatar_url_field_optional)
        state['cross_realm_bots'] = list(get_cross_realm_dicts())

        # For the user's own avatar URL, we force
        # client_gravatar=False, since that saves some unnecessary
        # client-side code for handing medium-size avatars.  See #8253
        # for details.
        state['avatar_source'] = settings_user.avatar_source
        state['avatar_url_medium'] = avatar_url(
            settings_user,
            medium=True,
            client_gravatar=False,
        )
        state['avatar_url'] = avatar_url(
            settings_user,
            medium=False,
            client_gravatar=False,
        )

        state['can_create_streams'] = settings_user.can_create_streams()
        state['can_subscribe_other_users'] = settings_user.can_subscribe_other_users()
        state['is_admin'] = settings_user.is_realm_admin
        state['is_owner'] = settings_user.is_realm_owner
        state['is_guest'] = settings_user.is_guest
        state['user_id'] = settings_user.id
        state['enter_sends'] = settings_user.enter_sends
        state['email'] = settings_user.email
        state['delivery_email'] = settings_user.delivery_email
        state['full_name'] = settings_user.full_name

    if want('realm_bot'):
        state['realm_bots'] = [] if user_profile is None else get_owned_bot_dicts(user_profile)

    # This does not yet have an apply_event counterpart, since currently,
    # new entries for EMBEDDED_BOTS can only be added directly in the codebase.
    if want('realm_embedded_bots'):
        realm_embedded_bots = []
        for bot in EMBEDDED_BOTS:
            realm_embedded_bots.append({'name': bot.name,
                                        'config': load_bot_config_template(bot.name)})
        state['realm_embedded_bots'] = realm_embedded_bots

    # This does not have an apply_events counterpart either since
    # this data is mostly static.
    if want('realm_incoming_webhook_bots'):
        realm_incoming_webhook_bots = []
        for integration in WEBHOOK_INTEGRATIONS:
            realm_incoming_webhook_bots.append({
                'name': integration.name,
                'config': {c[1]: c[0] for c in integration.config_options},
            })
        state['realm_incoming_webhook_bots'] = realm_incoming_webhook_bots

    if want('recent_private_conversations'):
        # A data structure containing records of this form:
        #
        #   [{'max_message_id': 700175, 'user_ids': [801]}]
        #
        # for all recent private message conversations, ordered by the
        # highest message ID in the conversation.  The user_ids list
        # is the list of users other than the current user in the
        # private message conversation (so it is [] for PMs to self).
        # Note that raw_recent_private_conversations is an
        # intermediate form as a dictionary keyed by recipient_id,
        # which is more efficient to update, and is rewritten to the
        # final format in post_process_state.
        state['raw_recent_private_conversations'] = {} if user_profile is None else get_recent_private_conversations(user_profile)

    if want('subscription'):
        if user_profile is not None:
            sub_info = gather_subscriptions_helper(
                user_profile,
                include_subscribers=include_subscribers,
            )
        else:
            sub_info = get_web_public_subs(realm)

        state['subscriptions'] = sub_info.subscriptions
        state['unsubscribed'] = sub_info.unsubscribed
        state['never_subscribed'] = sub_info.never_subscribed

    if want('update_message_flags') and want('message'):
        # Keeping unread_msgs updated requires both message flag updates and
        # message updates. This is due to the fact that new messages will not
        # generate a flag update so we need to use the flags field in the
        # message event.

        if user_profile is not None:
            state['raw_unread_msgs'] = get_raw_unread_data(user_profile)
        else:
            # For logged-out visitors, we treat all messages as read;
            # calling this helper lets us return empty objects in the
            # appropriate format.
            state['raw_unread_msgs'] = extract_unread_data_from_um_rows([], user_profile)

    if want('starred_messages'):
        state['starred_messages'] = [] if user_profile is None else get_starred_message_ids(user_profile)

    if want('stream'):
        if include_streams:
            # The webapp doesn't use the data from here; instead,
            # it uses data from state["subscriptions"] and other
            # places.
            if user_profile is not None:
                state['streams'] = do_get_streams(user_profile)
            else:
                # TODO: This line isn't used by the webapp because it
                # gets these data via the `subscriptions` key; it will
                # be used when the mobile apps support logged-out
                # access.
                state['streams'] = get_web_public_streams(realm)  # nocoverage
        state['stream_name_max_length'] = Stream.MAX_NAME_LENGTH
        state['stream_description_max_length'] = Stream.MAX_DESCRIPTION_LENGTH
    if want('default_streams'):
        if settings_user.is_guest:
            # Guest users and logged-out users don't have access to
            # all default streams, so we pretend the organization
            # doesn't have any.
            state['realm_default_streams'] = []
        else:
            state['realm_default_streams'] = streams_to_dicts_sorted(
                get_default_streams_for_realm(realm.id))
    if want('default_stream_groups'):
        if settings_user.is_guest:
            state['realm_default_stream_groups'] = []
        else:
            state['realm_default_stream_groups'] = default_stream_groups_to_dicts_sorted(
                get_default_stream_groups(realm))

    if want('stop_words'):
        state['stop_words'] = read_stop_words()

    if want('update_display_settings'):
        for prop in UserProfile.property_types:
            state[prop] = getattr(settings_user, prop)
            state['emojiset_choices'] = UserProfile.emojiset_choices()

    if want('update_global_notifications'):
        for notification in UserProfile.notification_setting_types:
            state[notification] = getattr(settings_user, notification)
        state['available_notification_sounds'] = get_available_notification_sounds()

    if want('user_status'):
        # We require creating an account to access statuses.
        state['user_status'] = {} if user_profile is None else get_user_info_dict(realm_id=realm.id)

    if want('video_calls'):
        state['has_zoom_token'] = settings_user.zoom_token is not None

    return state
Exemple #26
0
def fetch_initial_state_data(user_profile,
                             event_types,
                             queue_id,
                             include_subscribers=True):
    # type: (UserProfile, Optional[Iterable[str]], str, bool) -> Dict[str, Any]
    state = {'queue_id': queue_id}  # type: Dict[str, Any]

    if event_types is None:
        want = lambda msg_type: True
    else:
        want = set(event_types).__contains__

    if want('alert_words'):
        state['alert_words'] = user_alert_words(user_profile)

    if want('attachments'):
        state['attachments'] = user_attachments(user_profile)

    if want('message'):
        # The client should use get_old_messages() to fetch messages
        # starting with the max_message_id.  They will get messages
        # newer than that ID via get_events()
        messages = Message.objects.filter(
            usermessage__user_profile=user_profile).order_by('-id')[:1]
        if messages:
            state['max_message_id'] = messages[0].id
        else:
            state['max_message_id'] = -1

    if want('muted_topics'):
        state['muted_topics'] = ujson.loads(user_profile.muted_topics)

    if want('pointer'):
        state['pointer'] = user_profile.pointer

    if want('presence'):
        state['presences'] = get_status_dict(user_profile)

    if want('realm'):
        state['realm_name'] = user_profile.realm.name
        state['realm_description'] = user_profile.realm.description
        state[
            'realm_restricted_to_domain'] = user_profile.realm.restricted_to_domain
        state['realm_invite_required'] = user_profile.realm.invite_required
        state[
            'realm_invite_by_admins_only'] = user_profile.realm.invite_by_admins_only
        state[
            'realm_authentication_methods'] = user_profile.realm.authentication_methods_dict(
            )
        state[
            'realm_create_stream_by_admins_only'] = user_profile.realm.create_stream_by_admins_only
        state[
            'realm_add_emoji_by_admins_only'] = user_profile.realm.add_emoji_by_admins_only
        state[
            'realm_allow_message_editing'] = user_profile.realm.allow_message_editing
        state[
            'realm_message_content_edit_limit_seconds'] = user_profile.realm.message_content_edit_limit_seconds
        state['realm_default_language'] = user_profile.realm.default_language
        state[
            'realm_waiting_period_threshold'] = user_profile.realm.waiting_period_threshold
        state['realm_icon_url'] = realm_icon_url(user_profile.realm)
        state['realm_icon_source'] = user_profile.realm.icon_source
        state[
            'realm_name_changes_disabled'] = user_profile.realm.name_changes_disabled
        state[
            'realm_email_changes_disabled'] = user_profile.realm.email_changes_disabled
        state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
        state['realm_bot_domain'] = user_profile.realm.get_bot_domain()

    if want('realm_domains'):
        state['realm_domains'] = get_realm_aliases(user_profile.realm)

    if want('realm_emoji'):
        state['realm_emoji'] = user_profile.realm.get_emoji()

    if want('realm_filters'):
        state['realm_filters'] = realm_filters_for_realm(user_profile.realm_id)

    if want('realm_user'):
        state['realm_users'] = get_realm_user_dicts(user_profile)

    if want('realm_bot'):
        state['realm_bots'] = get_owned_bot_dicts(user_profile)

    if want('referral'):
        state['referrals'] = {
            'granted': user_profile.invites_granted,
            'used': user_profile.invites_used
        }

    if want('subscription'):
        subscriptions, unsubscribed, never_subscribed = gather_subscriptions_helper(
            user_profile, include_subscribers=include_subscribers)
        state['subscriptions'] = subscriptions
        state['unsubscribed'] = unsubscribed
        state['never_subscribed'] = never_subscribed

    if want('update_message_flags'):
        # There's no initial data for message flag updates, client will
        # get any updates during a session from get_events()
        pass

    if want('stream'):
        state['streams'] = do_get_streams(user_profile)
    if want('default_streams'):
        state['realm_default_streams'] = streams_to_dicts_sorted(
            get_default_streams_for_realm(user_profile.realm))

    if want('update_display_settings'):
        state['twenty_four_hour_time'] = user_profile.twenty_four_hour_time
        state['left_side_userlist'] = user_profile.left_side_userlist
        state['emoji_alt_code'] = user_profile.emoji_alt_code

        default_language = user_profile.default_language
        state['default_language'] = default_language

    if want('update_global_notifications'):
        state[
            'enable_stream_desktop_notifications'] = user_profile.enable_stream_desktop_notifications
        state['enable_stream_sounds'] = user_profile.enable_stream_sounds
        state[
            'enable_desktop_notifications'] = user_profile.enable_desktop_notifications
        state['enable_sounds'] = user_profile.enable_sounds
        state[
            'enable_offline_email_notifications'] = user_profile.enable_offline_email_notifications
        state[
            'enable_offline_push_notifications'] = user_profile.enable_offline_push_notifications
        state[
            'enable_online_push_notifications'] = user_profile.enable_online_push_notifications
        state['enable_digest_emails'] = user_profile.enable_digest_emails

    if want('zulip_version'):
        state['zulip_version'] = ZULIP_VERSION

    return state
Exemple #27
0
def fetch_initial_state_data(user_profile, event_types, queue_id,
                             include_subscribers=True):
    # type: (UserProfile, Optional[Iterable[str]], str, bool) -> Dict[str, Any]
    state = {'queue_id': queue_id}  # type: Dict[str, Any]

    if event_types is None:
        want = lambda msg_type: True
    else:
        want = set(event_types).__contains__

    if want('alert_words'):
        state['alert_words'] = user_alert_words(user_profile)

    if want('custom_profile_fields'):
        fields = custom_profile_fields_for_realm(user_profile.realm.id)
        state['custom_profile_fields'] = [f.as_dict() for f in fields]

    if want('attachments'):
        state['attachments'] = user_attachments(user_profile)

    if want('hotspots'):
        state['hotspots'] = get_next_hotspots(user_profile)

    if want('message'):
        # The client should use get_messages() to fetch messages
        # starting with the max_message_id.  They will get messages
        # newer than that ID via get_events()
        messages = Message.objects.filter(usermessage__user_profile=user_profile).order_by('-id')[:1]
        if messages:
            state['max_message_id'] = messages[0].id
        else:
            state['max_message_id'] = -1

    if want('muted_topics'):
        state['muted_topics'] = ujson.loads(user_profile.muted_topics)

    if want('pointer'):
        state['pointer'] = user_profile.pointer

    if want('presence'):
        state['presences'] = get_status_dict(user_profile)

    if want('realm'):
        for property_name in Realm.property_types:
            state['realm_' + property_name] = getattr(user_profile.realm, property_name)

        # Most state is handled via the property_types framework;
        # these manual entries are for those realm settings that don't
        # fit into that framework.
        state['realm_authentication_methods'] = user_profile.realm.authentication_methods_dict()
        state['realm_allow_message_editing'] = user_profile.realm.allow_message_editing
        state['realm_message_content_edit_limit_seconds'] = user_profile.realm.message_content_edit_limit_seconds
        state['realm_icon_url'] = realm_icon_url(user_profile.realm)
        state['realm_icon_source'] = user_profile.realm.icon_source
        state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
        state['realm_bot_domain'] = user_profile.realm.get_bot_domain()
        state['realm_uri'] = user_profile.realm.uri
        state['realm_presence_disabled'] = user_profile.realm.presence_disabled
        state['realm_show_digest_email'] = user_profile.realm.show_digest_email
        state['realm_is_zephyr_mirror_realm'] = user_profile.realm.is_zephyr_mirror_realm
        state['realm_password_auth_enabled'] = password_auth_enabled(user_profile.realm)
        if user_profile.realm.notifications_stream and not user_profile.realm.notifications_stream.deactivated:
            notifications_stream = user_profile.realm.notifications_stream
            state['realm_notifications_stream_id'] = notifications_stream.id
        else:
            state['realm_notifications_stream_id'] = -1

    if want('realm_domains'):
        state['realm_domains'] = get_realm_domains(user_profile.realm)

    if want('realm_emoji'):
        state['realm_emoji'] = user_profile.realm.get_emoji()

    if want('realm_filters'):
        state['realm_filters'] = realm_filters_for_realm(user_profile.realm_id)

    if want('realm_user'):
        state['realm_users'] = get_realm_user_dicts(user_profile)
        state['avatar_source'] = user_profile.avatar_source
        state['avatar_url_medium'] = avatar_url(user_profile, medium=True)
        state['avatar_url'] = avatar_url(user_profile)
        state['can_create_streams'] = user_profile.can_create_streams()
        state['cross_realm_bots'] = list(get_cross_realm_dicts())
        state['is_admin'] = user_profile.is_realm_admin
        state['user_id'] = user_profile.id
        state['enter_sends'] = user_profile.enter_sends
        state['email'] = user_profile.email
        state['full_name'] = user_profile.full_name

    if want('realm_bot'):
        state['realm_bots'] = get_owned_bot_dicts(user_profile)

    if want('subscription'):
        subscriptions, unsubscribed, never_subscribed = gather_subscriptions_helper(
            user_profile, include_subscribers=include_subscribers)
        state['subscriptions'] = subscriptions
        state['unsubscribed'] = unsubscribed
        state['never_subscribed'] = never_subscribed

    if want('update_message_flags') and want('message'):
        # Keeping unread_msgs updated requires both message flag updates and
        # message updates. This is due to the fact that new messages will not
        # generate a flag update so we need to use the flags field in the
        # message event.
        state['unread_msgs'] = get_unread_message_ids_per_recipient(user_profile)

    if want('stream'):
        state['streams'] = do_get_streams(user_profile)
    if want('default_streams'):
        state['realm_default_streams'] = streams_to_dicts_sorted(get_default_streams_for_realm(user_profile.realm))

    if want('update_display_settings'):
        for prop in UserProfile.property_types:
            state[prop] = getattr(user_profile, prop)
        state['emojiset_choices'] = user_profile.emojiset_choices()
        state['autoscroll_forever'] = user_profile.autoscroll_forever

    if want('update_global_notifications'):
        for notification in UserProfile.notification_setting_types:
            state[notification] = getattr(user_profile, notification)
        state['default_desktop_notifications'] = user_profile.default_desktop_notifications

    if want('zulip_version'):
        state['zulip_version'] = ZULIP_VERSION

    return state
Exemple #28
0
def fetch_initial_state_data(user_profile, event_types, queue_id,
                             include_subscribers=True):
    # type: (UserProfile, Optional[Iterable[str]], str, bool) -> Dict[str, Any]
    state = {'queue_id': queue_id} # type: Dict[str, Any]

    if event_types is None:
        want = lambda msg_type: True
    else:
        want = set(event_types).__contains__

    if want('alert_words'):
        state['alert_words'] = user_alert_words(user_profile)

    if want('attachments'):
        state['attachments'] = user_attachments(user_profile)

    if want('message'):
        # The client should use get_old_messages() to fetch messages
        # starting with the max_message_id.  They will get messages
        # newer than that ID via get_events()
        messages = Message.objects.filter(usermessage__user_profile=user_profile).order_by('-id')[:1]
        if messages:
            state['max_message_id'] = messages[0].id
        else:
            state['max_message_id'] = -1

    if want('muted_topics'):
        state['muted_topics'] = ujson.loads(user_profile.muted_topics)

    if want('pointer'):
        state['pointer'] = user_profile.pointer

    if want('presence'):
        state['presences'] = get_status_dict(user_profile)

    if want('realm'):
        state['realm_name'] = user_profile.realm.name
        state['realm_restricted_to_domain'] = user_profile.realm.restricted_to_domain
        state['realm_invite_required'] = user_profile.realm.invite_required
        state['realm_invite_by_admins_only'] = user_profile.realm.invite_by_admins_only
        state['realm_authentication_methods'] = user_profile.realm.authentication_methods_dict()
        state['realm_create_stream_by_admins_only'] = user_profile.realm.create_stream_by_admins_only
        state['realm_add_emoji_by_admins_only'] = user_profile.realm.add_emoji_by_admins_only
        state['realm_allow_message_editing'] = user_profile.realm.allow_message_editing
        state['realm_message_content_edit_limit_seconds'] = user_profile.realm.message_content_edit_limit_seconds
        state['realm_default_language'] = user_profile.realm.default_language
        state['realm_waiting_period_threshold'] = user_profile.realm.waiting_period_threshold
        state['realm_icon_url'] = realm_icon_url(user_profile.realm)
        state['realm_icon_source'] = user_profile.realm.icon_source
        state['realm_name_changes_disabled'] = user_profile.realm.name_changes_disabled
        state['realm_email_changes_disabled'] = user_profile.realm.email_changes_disabled
        state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
        state['realm_bot_domain'] = user_profile.realm.get_bot_domain()

    if want('realm_domains'):
        state['realm_domains'] = get_realm_aliases(user_profile.realm)

    if want('realm_emoji'):
        state['realm_emoji'] = user_profile.realm.get_emoji()

    if want('realm_filters'):
        state['realm_filters'] = realm_filters_for_realm(user_profile.realm_id)

    if want('realm_user'):
        state['realm_users'] = get_realm_user_dicts(user_profile)

    if want('realm_bot'):
        state['realm_bots'] = get_owned_bot_dicts(user_profile)

    if want('referral'):
        state['referrals'] = {'granted': user_profile.invites_granted,
                              'used': user_profile.invites_used}

    if want('subscription'):
        subscriptions, unsubscribed, never_subscribed = gather_subscriptions_helper(
            user_profile, include_subscribers=include_subscribers)
        state['subscriptions'] = subscriptions
        state['unsubscribed'] = unsubscribed
        state['never_subscribed'] = never_subscribed

    if want('update_message_flags'):
        # There's no initial data for message flag updates, client will
        # get any updates during a session from get_events()
        pass

    if want('stream'):
        state['streams'] = do_get_streams(user_profile)
    if want('default_streams'):
        state['realm_default_streams'] = streams_to_dicts_sorted(get_default_streams_for_realm(user_profile.realm))

    if want('update_display_settings'):
        state['twenty_four_hour_time'] = user_profile.twenty_four_hour_time
        state['left_side_userlist'] = user_profile.left_side_userlist
        state['emoji_alt_code'] = user_profile.emoji_alt_code

        default_language = user_profile.default_language
        state['default_language'] = default_language

    if want('update_global_notifications'):
        state['enable_stream_desktop_notifications'] = user_profile.enable_stream_desktop_notifications
        state['enable_stream_sounds'] = user_profile.enable_stream_sounds
        state['enable_desktop_notifications'] = user_profile.enable_desktop_notifications
        state['enable_sounds'] = user_profile.enable_sounds
        state['enable_offline_email_notifications'] = user_profile.enable_offline_email_notifications
        state['enable_offline_push_notifications'] = user_profile.enable_offline_push_notifications
        state['enable_online_push_notifications'] = user_profile.enable_online_push_notifications
        state['enable_digest_emails'] = user_profile.enable_digest_emails

    if want('zulip_version'):
        state['zulip_version'] = ZULIP_VERSION

    return state
Exemple #29
0
def fetch_initial_state_data(user_profile, event_types, queue_id,
                             include_subscribers=True):
    # type: (UserProfile, Optional[Iterable[str]], str, bool) -> Dict[str, Any]
    state = {'queue_id': queue_id}  # type: Dict[str, Any]

    if event_types is None:
        want = lambda msg_type: True
    else:
        want = set(event_types).__contains__

    if want('alert_words'):
        state['alert_words'] = user_alert_words(user_profile)

    if want('custom_profile_fields'):
        fields = custom_profile_fields_for_realm(user_profile.realm.id)
        state['custom_profile_fields'] = [f.as_dict() for f in fields]

    if want('attachments'):
        state['attachments'] = user_attachments(user_profile)

    if want('hotspots'):
        state['hotspots'] = get_next_hotspots(user_profile)

    if want('message'):
        # The client should use get_messages() to fetch messages
        # starting with the max_message_id.  They will get messages
        # newer than that ID via get_events()
        messages = Message.objects.filter(usermessage__user_profile=user_profile).order_by('-id')[:1]
        if messages:
            state['max_message_id'] = messages[0].id
        else:
            state['max_message_id'] = -1

    if want('muted_topics'):
        state['muted_topics'] = ujson.loads(user_profile.muted_topics)

    if want('pointer'):
        state['pointer'] = user_profile.pointer

    if want('presence'):
        state['presences'] = get_status_dict(user_profile)

    if want('realm'):
        for property_name in Realm.property_types:
            state['realm_' + property_name] = getattr(user_profile.realm, property_name)
        state['realm_authentication_methods'] = user_profile.realm.authentication_methods_dict()
        state['realm_allow_message_editing'] = user_profile.realm.allow_message_editing
        state['realm_message_content_edit_limit_seconds'] = user_profile.realm.message_content_edit_limit_seconds
        state['realm_icon_url'] = realm_icon_url(user_profile.realm)
        state['realm_icon_source'] = user_profile.realm.icon_source
        state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
        state['realm_bot_domain'] = user_profile.realm.get_bot_domain()
        state['realm_uri'] = user_profile.realm.uri
        state['realm_presence_disabled'] = user_profile.realm.presence_disabled
        state['realm_mandatory_topics'] = user_profile.realm.mandatory_topics
        state['realm_show_digest_email'] = user_profile.realm.show_digest_email
        state['realm_is_zephyr_mirror_realm'] = user_profile.realm.is_zephyr_mirror_realm
        state['realm_password_auth_enabled'] = password_auth_enabled(user_profile.realm)
        if user_profile.realm.notifications_stream and not user_profile.realm.notifications_stream.deactivated:
            notifications_stream = user_profile.realm.notifications_stream
            state['realm_notifications_stream_id'] = notifications_stream.id
        else:
            state['realm_notifications_stream_id'] = -1

    if want('realm_domains'):
        state['realm_domains'] = get_realm_domains(user_profile.realm)

    if want('realm_emoji'):
        state['realm_emoji'] = user_profile.realm.get_emoji()

    if want('realm_filters'):
        state['realm_filters'] = realm_filters_for_realm(user_profile.realm_id)

    if want('realm_user'):
        state['realm_users'] = get_realm_user_dicts(user_profile)
        state['avatar_source'] = user_profile.avatar_source
        state['avatar_url_medium'] = avatar_url(user_profile, medium=True)
        state['avatar_url'] = avatar_url(user_profile)
        state['can_create_streams'] = user_profile.can_create_streams()
        state['cross_realm_bots'] = list(get_cross_realm_dicts())
        state['is_admin'] = user_profile.is_realm_admin
        state['user_id'] = user_profile.id
        state['enter_sends'] = user_profile.enter_sends
        state['email'] = user_profile.email
        state['full_name'] = user_profile.full_name

    if want('realm_bot'):
        state['realm_bots'] = get_owned_bot_dicts(user_profile)

    if want('referral'):
        state['referrals'] = {'granted': user_profile.invites_granted,
                              'used': user_profile.invites_used}

    if want('subscription'):
        subscriptions, unsubscribed, never_subscribed = gather_subscriptions_helper(
            user_profile, include_subscribers=include_subscribers)
        state['subscriptions'] = subscriptions
        state['unsubscribed'] = unsubscribed
        state['never_subscribed'] = never_subscribed

    if want('update_message_flags'):
        # There's no initial data for message flag updates, client will
        # get any updates during a session from get_events()
        pass

    if want('stream'):
        state['streams'] = do_get_streams(user_profile)
    if want('default_streams'):
        state['realm_default_streams'] = streams_to_dicts_sorted(get_default_streams_for_realm(user_profile.realm))

    if want('update_display_settings'):
        state['twenty_four_hour_time'] = user_profile.twenty_four_hour_time
        state['left_side_userlist'] = user_profile.left_side_userlist
        state['emoji_alt_code'] = user_profile.emoji_alt_code
        state['emojiset'] = user_profile.emojiset
        state['emojiset_choices'] = user_profile.emojiset_choices()
        state['timezone'] = user_profile.timezone
        state['default_language'] = user_profile.default_language
        state['autoscroll_forever'] = user_profile.autoscroll_forever

    if want('update_global_notifications'):
        state['default_desktop_notifications'] = user_profile.default_desktop_notifications
        state['enable_stream_desktop_notifications'] = user_profile.enable_stream_desktop_notifications
        state['enable_stream_sounds'] = user_profile.enable_stream_sounds
        state['enable_desktop_notifications'] = user_profile.enable_desktop_notifications
        state['enable_sounds'] = user_profile.enable_sounds
        state['enable_offline_email_notifications'] = user_profile.enable_offline_email_notifications
        state['enable_offline_push_notifications'] = user_profile.enable_offline_push_notifications
        state['enable_online_push_notifications'] = user_profile.enable_online_push_notifications
        state['enable_digest_emails'] = user_profile.enable_digest_emails
        state['pm_content_in_desktop_notifications'] = user_profile.pm_content_in_desktop_notifications

    if want('zulip_version'):
        state['zulip_version'] = ZULIP_VERSION

    return state