Commit Graph

49717 Commits

Author SHA1 Message Date
Sahil Batra 0bc61281df stream_settings: Fix upgrade text in stream edit panel.
The upgrade text shown for message retention setting for realms
on limited plans should mention about sponsorship only for
non-business orgs. In the stream edit panel, the sponsorship
text was present even for non-business orgs because the
is_business_type_org parameter was not being passed to the
template, so this commit fixes the code to pass the
is_busines_type_org parameter correctly to the template.
2023-01-15 13:36:33 -08:00
Sahil Batra 90566ab772 stream_create: Disable the message retention setting for limited plans.
We should disable the message retention setting in stream creation
form for limited plans.
2023-01-15 13:36:33 -08:00
Sahil Batra 6f20d7c9ab stream_create: Refactor code to set default value for retention setting.
The message retention setting is only visible to owners in the
stream creation form, so the jquery code to hide the custom
input, set the default value for dropdown and listener to
show and hide the custom input should be called only for owners.
2023-01-15 13:36:33 -08:00
Sahil Batra 1c1b911a42 stream_create: Fix comments in show_new_stream_modal.
We fix the comment stating that announce_stream setting
is set on "on", as we handle it differently now in
update_announce_stream_state.
2023-01-15 13:36:33 -08:00
Aman Agrawal 1f3367abfb message_list_view: Remove dead next_is_same_sender code.
The `next_is_same_sender` has no effect on the CSS of the message
displayed and the JS changes seem to have no effect too.

See cc8021a742 for more details.
2023-01-14 14:49:28 -08:00
Josh Klar 465d0b2710 message_list_view: Use translated form of "at" in timestamp tooltip.
The English word "at" was manually appended to the string output of
datetime-related functions to generate the string shown in the tooltip
when hovering over the timestamp of a message. Use the translated form
"{date} at {time}" instead, as found elsewhere in the codebase.
2023-01-12 20:47:01 -08:00
Lauryn Menard 1a3b0edf4b account-settings: Disable deactivate account button when only owner.
Disables the deactivate account button in the user's account and
privacy settings tab if they are the only active organization owner.

Adds a tooltip when hovering on the deactivated button to let the
user know why the button is disabled.

The backend already returns an error for self account deactivation
requests if the user is the only organization owner.
2023-01-11 13:30:31 -08:00
Lauryn Menard 7abf476443 settings_account: Update avatar widget if user/org permissions changed.
Adds `avatar.build_user_avatar_widget` to the updates done in
`settings_account.update_avatar_change_display` when the user
has permission to change/delete their avatar.

For the case where a user has their personal account profile
settings open while the organization or user's permissions are
changed, `user_avatar_widget_created` boolean is added to
`settings_account.js` to track whether the widget and handlers
have been created so that live updates don't rebuild the
existing widget and handlers.

Also, updates `avatar.build_user_avatar_widget` to return early if
the user cannot change their avatar. This pattern better matches
the other instances where we use the direct upload widget for the
organization icon and logos.
2023-01-11 13:12:59 -08:00
Lauryn Menard fd4e071f32 organization-logo: Update the titles for the logo color schemes.
The "day" and "night" color scheme names were updated in #20371,
but the organization profile settings tab still has had the old
names for the two types of wide logos.

Updates "Day logo" to be "Light theme logo" and "Night logo" to
be "Dark theme logo".
2023-01-11 13:12:59 -08:00
Lauryn Menard 55f34c3086 settings-org: Hide image upload button if user no longer admin.
Adds hiding any elements with the `image_upload_button` class in
the organization profile (icon and logos) to the live updates in
`settings_org.maybe_disable_widgets`, so that any role changes
that remove admin permissions will update these images so that
they no longer appear able to be updated / deleted.
2023-01-11 13:12:59 -08:00
Lauryn Menard eef22e4e04 settings-account: Make live update for avatar changes consistent.
The `settings-info-icon` with the tooltip for the user avatar
section was removed in commit 103db2afaf. This removes the changes
to that tooltip in `settings_account.update_avatar_change_display`.

Instead of hiding or showing the `image_upload_button` in that same
live update function, we now add or remove the `hide` class, which
in the previous commit has a specific CSS hover rule for the image
upload widget.

Also adds test coverage for the `is_admin` case for this setting
because administrators can always change their own avatar even if
the organization has disabled avatar changes.
2023-01-11 13:12:59 -08:00
Lauryn Menard d3a513f4bd image-upload-widget: Render `image_disabled` div if text to display.
If there is no `disabled_text` provided for the image upload widget,
then there is no need to have the `image_disabled` div rendered in
the template. This allows the hover CSS rules to be more general for
the image upload widget in general.

Adds a check for `disabled_text` around the `image_disabled` div
element in `image_upload_widget.hbs`.

Also, changes `image_upload_background` class to
`image_hover_background` so that it more accurately describes what
the CSS rule is for and why it's used in both the `image_disabled`
div and the `image_upload_button` div.
2023-01-11 13:12:59 -08:00
Manas Jayaswal 3cbec56e81 image-upload-widget: Fix hover behavior when image cannot be changed.
The `hide` CSS rule in `app_components.css` was being overwritten
by the more specific rules in `image_upload_widget.css`, which
meant that when changing the inage was disabled the hover text for
updating or deleting the image was still visible.

Adds `hide` class (and therefore more specific rule) to
`image_upload_widget.css` for when this text should be display
none.

Fixes #23844.
2023-01-11 13:12:59 -08:00
Tim Abbott e50ab2dad3 message_list_view: Remove include_footer parameter.
This only set the last_message CSS class, which is no longer used for
styling or JavaScript code.

(The calculation was also wrong, in that new messages arriving would
not cause it to be removed from the previous message with the
last_message class).
2023-01-10 17:03:37 -08:00
Tim Abbott b1155516d1 lightbox: Rewrite logic depending on last_message CSS class.
The last_message CSS class didn't mean what it said it did, due to
issues with live update.

Further, this logic was poorly written, with `$message` changing types
from a .message_row to a .recipient_row for now apparent reason.

I was able to reproduce at least one bug where the `v` shortcut would
not correctly open the lightbox that is fixed by this rewrite.
2023-01-10 17:03:37 -08:00
Aman Agrawal 2fa88362bc message: Hide first action button on narrow widths.
Fixes zulip#19759

Before grid, there was overlap of action buttons and text (photo 1).
With grid, there was just very little space for messages (photo 2).
With this commit, the message gets a bit more space (photo 3).

This helps us add more width to the content column of message
on narrow widths. Note that it will still always be less than
before grid, since we are explicitly preventing overlap.
2023-01-10 17:03:37 -08:00
Aman Agrawal 26011c98fd css: Use grid layout for messages.
Using grid layout moves us away from fixed widths
and position for items where possible, which will
make it easier to make messagebox changes without
breaking formatting.

Visual changes expected in this commit:
- When the action buttons overlap the message content,
it will no longer visually overlap but completely cut off
the content — which is good, but means the messages can’t
be as wide on narrow width views. There’s a slight improvement
to this in an upcoming commit.

Also removes the `last_message` CSS, which was busted due to the
`last_message` calculation not correctly being updated for new
messages arriving, and didn't improve styling.
2023-01-10 17:03:37 -08:00
Aman Agrawal 953277bdae message_list: Add `content_edit_mode` when editing a message.
Having the class at the top of message DOM structure when the
user is editing a message, helps apply css when user is editing
a message.

Short prep commit for the next commit; no visible changes
2023-01-10 17:03:37 -08:00
Lauryn Menard fe03d2a533 api-docs: Clarify only API doc paths check for endpoint info.
Previously, we got the directory path for all documentation pages
before checking for API method and path information in the OpenAPI
documentation. Instead, we now check the `path_template` is the
API documentation view template before getting the directory path.

Also, changes the confusingly named `article_path` variable, which
overlapped with the DocumentationArticle dataclass `article_path`
field, to now be `api_documentation_path`.

Prep commit for moving the help center documentation to a top level
directory.
2023-01-10 15:32:47 -08:00
Alex Vandiver e351df4095 changelog: Add entry for S3 nginx proxying. 2023-01-10 15:30:57 -08:00
Mateusz Mandera 89d1f1f385 messages: Eliminate redundant realm fetch in has_message_access.
Accessing .realm will cause a fetch query from the database if the
attribute hasn't been fetched already earlier in the codepath. That's
completely redundant if we're just comparing realms, and we should only
access .realm_id attribute. This seems to eliminate a query in some
codepaths, which is nice in this performance-sensitive function.
2023-01-10 15:27:55 -08:00
Lauryn Menard a7fd994cbd docs: Link to management commands documentation in user facing docs.
Adds links to the documentation about management commands in the
API documentation for creating users, as well as the `/devtools`
documentation, the GDPR compliance article and the incoming
webhooks tutorial.
2023-01-10 08:50:00 -08:00
Alex Vandiver 04cf68b45e uploads: Serve S3 uploads directly from nginx.
When file uploads are stored in S3, this means that Zulip serves as a
302 to S3.  Because browsers do not cache redirects, this means that
no image contents can be cached -- and upon every page load or reload,
every recently-posted image must be re-fetched.  This incurs extra
load on the Zulip server, as well as potentially excessive bandwidth
usage from S3, and on the client's connection.

Switch to fetching the content from S3 in nginx, and serving the
content from nginx.  These have `Cache-control: private, immutable`
headers set on the response, allowing browsers to cache them locally.

Because nginx fetching from S3 can be slow, and requests for uploads
will generally be bunched around when a message containing them are
first posted, we instruct nginx to cache the contents locally.  This
is safe because uploaded file contents are immutable; access control
is still mediated by Django.  The nginx cache key is the URL without
query parameters, as those parameters include a time-limited signed
authentication parameter which lets nginx fetch the non-public file.

This adds a number of nginx-level configuration parameters to control
the caching which nginx performs, including the amount of in-memory
index for he cache, the maximum storage of the cache on disk, and how
long data is retained in the cache.  The currently-chosen figures are
reasonable for small to medium deployments.

The most notable effect of this change is in allowing browsers to
cache uploaded image content; however, while there will be many fewer
requests, it also has an improvement on request latency.  The
following tests were done with a non-AWS client in SFO, a server and
S3 storage in us-east-1, and with 100 requests after 10 requests of
warm-up (to fill the nginx cache).  The mean and standard deviation
are shown.

|                   | Redirect to S3      | Caching proxy, hot  | Caching proxy, cold |
| ----------------- | ------------------- | ------------------- | ------------------- |
| Time in Django    | 263.0 ms ±  28.3 ms | 258.0 ms ±  12.3 ms | 258.0 ms ±  12.3 ms |
| Small file (842b) | 586.1 ms ±  21.1 ms | 266.1 ms ±  67.4 ms | 288.6 ms ±  17.7 ms |
| Large file (660k) | 959.6 ms ± 137.9 ms | 609.5 ms ±  13.0 ms | 648.1 ms ±  43.2 ms |

The hot-cache performance is faster for both large and small files,
since it saves the client the time having to make a second request to
a separate host.  This performance improvement remains at least 100ms
even if the client is on the same coast as the server.

Cold nginx caches are only slightly slower than hot caches, because
VPC access to S3 endpoints is extremely fast (assuming it is in the
same region as the host), and nginx can pool connections to S3 and
reuse them.

However, all of the 648ms taken to serve a cold-cache large file is
occupied in nginx, as opposed to the only 263ms which was spent in
nginx when using redirects to S3.  This means that to overall spend
less time responding to uploaded-file requests in nginx, clients will
need to find files in their local cache, and skip making an
uploaded-file request, at least 60% of the time.  Modeling shows a
reduction in the number of client requests by about 70% - 80%.

The `Content-Disposition` header logic can now also be entirely shared
with the local-file codepath, as can the `url_only` path used by
mobile clients.  While we could provide the direct-to-S3 temporary
signed URL to mobile clients, we choose to provide the
served-from-Zulip signed URL, to better control caching headers on it,
and greater consistency.  In doing so, we adjust the salt used for the
URL; since these URLs are only valid for 60s, the effect of this salt
change is minimal.
2023-01-09 18:23:58 -05:00
Alex Vandiver 58dc1059f3 uploads: Move unauth-signed tokens into view. 2023-01-09 18:23:58 -05:00
Alex Vandiver ed6d62a9e7 avatars: Serve /user_avatars/ through Django, which offloads to nginx.
Moving `/user_avatars/` to being served partially through Django
removes the need for the `no_serve_uploads` nginx reconfiguring when
switching between S3 and local backends.  This is important because a
subsequent commit will move S3 attachments to being served through
nginx, which would make `no_serve_uploads` entirely nonsensical of a
name.

Serve the files through Django, with an offload for the actual image
response to an internal nginx route.  In development, serve the files
directly in Django.

We do _not_ mark the contents as immutable for caching purposes, since
the path for avatar images is hashed only by their user-id and a salt,
and as such are reused when a user's avatar is updated.
2023-01-09 18:23:58 -05:00
Alex Vandiver f0f4aa66e0 uploads: Inline the one callsite of get_local_file_path.
This helps make more explicit the assert_is_local_storage_path which
makes using local_path safe.
2023-01-09 18:23:58 -05:00
Alex Vandiver 862e3bb80a avatars: Use a helper method, rather than use upload_backend directly.
Importing `upload_backend` directly means that in testing it must also
be mocked where it is imported, in order to correctly test the right
backend.  Since `get_avatar_url` is part of the public
`ZulipUploadBackend` API, add another helper method to call that.
2023-01-09 18:23:58 -05:00
Alex Vandiver 0c3d74ea31 test_helpers: Use a mock, rather than explicitly setting and unsetting. 2023-01-09 18:23:58 -05:00
Alex Vandiver 7ad06473b6 uploads: Add LOCAL_AVATARS_DIR / LOCAL_FILES_DIR computed settings.
This avoids strewing "avatars" and "files" constants throughout.
2023-01-09 18:23:58 -05:00
Alex Vandiver 24f95a3788 uploads: Move internal upload serving path to under /internal/. 2023-01-09 18:23:58 -05:00
Alex Vandiver b20ecabf8f tornado: Move internal tornado redirect to under /internal/. 2023-01-09 18:23:58 -05:00
Alex Vandiver cc9b028312 uploads: Set X-Accel-Redirect manually, without using django-sendfile2.
The `django-sendfile2` module unfortunately only supports a single
`SENDFILE` root path -- an invariant which subsequent commits need to
break.  Especially as Zulip only runs with a single webserver, and
thus sendfile backend, the functionality is simple to inline.

It is worth noting that the following headers from the initial Django
response are _preserved_, if present, and sent unmodified to the
client; all other headers are overridden by those supplied by the
internal redirect[^1]:
 - Content-Type
 - Content-Disposition
 - Accept-Ranges
 - Set-Cookie
 - Cache-Control
 - Expires

As such, we explicitly unset the Content-type header to allow nginx to
set it from the static file, but set Content-Disposition and
Cache-Control as we want them to be.

[^1]: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/
2023-01-09 18:23:58 -05:00
Alex Vandiver 43fe24a5a0 uploads: Make realm_avatar_and_logo_path non-abstract. 2023-01-09 18:23:58 -05:00
Alex Vandiver 8e68d68f32 uploads: Be consistent about first arguments to write_local_file.
Enforcing a consistent `type` helps us double-check that we're not
playing fast-and-loose with any file paths for local files.  As noted
in the comment, this is purely for defense-in-depth.

Passing `write_local_file` a consistent `type` requires removing the
"avatars" out of `realm_avatar_and_logo_path` -- which makes it
consistent across upload backends.

This, in turn, requires a compensatory change to zerver.lib.export, to
be explicit that the realm icons are exported from the avatars
directory.  This clarity is likely an improvement.
2023-01-09 18:23:58 -05:00
Alex Vandiver 679fb76acf uploads: Provide our own Content-Disposition header.
sendfile already applied a Content-Disposition header, but the
algorithm may provide both `filename=` and `filename*=` values (which
is potentially confusing to clients) and incorrectly slash-escapes
quotes in Unicode strings.

Django provides a correct implementation, but it is only accessible to
FileResponse objects.  Since the entire point is to offload the
filehandle handling, we cannot use a FileResponse.

Django 4.2 will make the function available outside of FileResponse.
Until then, extract our own Content-Disposition handling, based on
Django's.

We remove the very verbose comment added in d4360e2287, describing
Content-Disposition headers, as it does not add much.
2023-01-09 18:23:58 -05:00
Alex Vandiver 83fd807885 uploads: Remove unncessary return in create_attachment. 2023-01-09 18:23:58 -05:00
Alex Vandiver 7c0d414aff uploads: Split out S3 and local file backends into separate files.
The uploads file is large, and conceptually the S3 and local-file
backends are separable.
2023-01-09 18:23:58 -05:00
Alex Vandiver 497abc2e48 nginx: Move uploads handling into app_frontend_base.
As uploads are a feature of the application, not of a generic nginx
deployment, move them into the `zulip::app_frontend_base` class.  This
is purely for organizational clarity -- we do not support deployments
with has `zulip::nginx` but not `zulip::app_frontend_base`.
2023-01-09 18:23:58 -05:00
Lauryn Menard 79fb2c38fb api-docs: Add `missing.md` file specifically for API documentation.
Previously, `templates/zerver/api/missing.md` was a symlink to the
file in the help center documentation.

Prep commit for moving the help center documentation to a top level
directory.
2023-01-09 11:17:00 -08:00
Abhijeet Prasad Bodas 932ce6cee4 MissedMessageHookTest: Add more tests.
Add more tests analogous to existing ones but for different scenarios.

This is mostly boring text, but is important for completeness, since the
notificability logic underneath is subtle.
2023-01-06 17:08:20 -08:00
Abhijeet Prasad Bodas 6288d7ae3e test_event_queue: Split missed message hook tests.
Split the one giant `test_end_to_end_missedmessage_hook` into many
smaller tests.

This allows us to not worry about resetting database state after each
test case and also allows extracting a lot of common stuff into setUp
and tearDown.

There is probably even more scope of deduplication here (for example,
the mock and the `assert_maybe_enqueue_notifications_call_args` call are
same for all test cases) but that might not be worth the added
complexity.

We also change a few
```
user_profile.<setting> = <value>
user_profile.save()
```
expressions to instead use the `do_change_user_setting` function.
2023-01-06 17:08:20 -08:00
Abhijeet Prasad Bodas 04e6b04213 message send: Ignore alert words for presence idle users.
For alert words, we currently don't send email/push notifications --
only desktop notifications. Thus, we don't need to consider alert words
here, since desktop notifications do not utilize the presence status
calculated at this stage.

Tested manually that alert word desktop notifications work as expected.

When we implement email/push notifications for alert words (issues #5137
and #13127), we can add new fields like
`notifications_data.alert_word_email_notify`, similar to the existing
`notifications_data.wildcard_mention_email_notify`, which will allow us
to keep the alert word notifiability check inside the dataclass, similar
to how the mentions checks are done currently. So, even when that
feature is implemented, the code which this commit removes would be
unnecessary.
2023-01-06 17:08:20 -08:00
Abhijeet Prasad Bodas 75cb401f0b test_messages: Rename helper for clarity. 2023-01-06 17:08:20 -08:00
N-Shar-ma d88ce61801 typeahead: Make the typeahead completions undo friendly.
We now use the undo supporting `insert` function from the
`text-field-edit` module to update the text after autocompletion,
instead of just resetting the value of the textarea / input, which was
not undo-able.

So that the undo history seems sensible, we replace only the minimal
diff between the text before and after autocompletion. This ensures
that only this diff, and not the entire text, is highlighted when
undoing, as would be ideal.

Fixes: #14311.
2023-01-06 16:53:57 -08:00
N-Shar-ma 95b77c0c1a util: Add function `get_string_diff`.
The new function specifies the single minimal diff between 2 strings.
It takes in 2 string parameters and returns an array with 3 integers
where the 1st is the index where the difference starts and the 2nd and
3rd are the indices of the end of the diff in the 2 strings.
2023-01-06 16:53:57 -08:00
Lauryn Menard d1714b0671 help-docs: Update articles for restricting email and avatar changes.
Updates the help center articles on restricting email and avatar
changes so that it is clear that administrators can always change
these settings for themselves.

Also, fixes a broken link and a few small text/formatting errors.
2023-01-06 16:41:11 -08:00
Mateusz Mandera f4024f6e9d help center: Remove deprecated mmctl flag from instructions.
--attachments is redundant and should not be used:
```
$ mmctl export create --attachments
Flag --attachments has been deprecated, the tool now includes attachments by default. The flag will be removed in a future version.
```
2023-01-06 16:36:01 -08:00
Zixuan James Li 33716f6156 decorator: Do not send HEAD response with non-empty body.
An HTTP HEAD response with a non-empty message body is not compliant
with the standard.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
2023-01-06 13:32:47 -08:00
Zixuan James Li 1e36d79b83 intercom: Return success on HEAD requests.
Intercom sends a HEAD request to validate the webhook URL on their side,
which was not expected in the previous implementation.
This fixes the problem that we send out a confusing error message for it.

Fixes #23912.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
2023-01-06 13:32:47 -08:00
Alya Abbott 6fb4f10abb docs: Add communication guidance to mentor guide.
Also link to GSoC's mentor guide.
2023-01-06 11:05:51 -08:00