Files under /_next/static/ carry a content hash in their name but were
served without Cache-Control, so browsers fell back to heuristic freshness
and revalidated each of the ~45 files of a page with a conditional request.
Serve them with a one-year immutable lifetime.
HTML pages, service-worker.js and public files keep a stable name: send
Cache-Control: no-cache so the browser revalidates them and always gets
the chunk list and service worker of the current release. The headers are
repeated in every location, as nginx drops the inherited add_header
directives as soon as a location defines its own.
Closes#2770
Signed-off-by: Anthony LC <anthony.le-courric@mail.numerique.gouv.fr>
For big documents, calling yhub for each sub documents can be a big
amount of request at the same time. We decided to group reset by batch
in the path order and call again the reset celery task with a delay to
continue.
Fix#2656
Reset to the collaboration server when an access is changed was
partially made. There is still action in the application that does not
cover this like when a document is moved or soft deleted.
Instead of doing the reset in the viewset and searching for every action
it should be made, we are making it now in the model to miss new or
modified path acting on an access. For detecting when a bulk
update/delete is made on the access model, we use existing
signal.
The login and logout navigations (authenticate/, callback/, logout/,
logout-callback/) reach the service worker on the same origin, and the
catch-all api route cached their redirects. When the network step
failed, the worker answered authenticate/ with a cached redirect that
carried an OIDC state already used, so the login failed: a 400 on the
callback before django-lasuite 0.0.30.
Give these urls their own NetworkOnly route, registered before the
catch-all one, so they never read or write the cache. ApiPlugin stays
on it, so the offline mutations are still replayed before a logout
ends the session.
Fixes#2477
Signed-off-by: Roee Sivan <roee.sivan@post.runi.ac.il>
A test was getting flaky, and was blocking the CI pipeline.
This change improves the handling of sub-pages in
the e2e tests to make them more reliable.
The language picker marked an option as selected when it matched the
current language, falling back to a match on the language alone. With the
current language zh-tw, the zh-cn option matched too, so several regions
of a language were selected at once, and the legacy picker could show the
label of the wrong one. Now that zh-cn and zh-tw are separate frontend
translations, this shows up for the Chinese locales, and it would for any
language with several regions (en-us/en-gb, pt-pt/pt-br).
Add getClosestLocale, which returns the one available locale closest to
the current language (the exact match first, then the first region of the
language), and use it in both pickers to select the option and to display
the current label.
Pull the translations from Crowdin with the new locale-based export, so
that the frontend translations reflect the new taxonomy: zh-CN and zh-TW
are now two distinct entries (zh-cn and zh-tw) in translations.json
instead of a single "zh" one, and the backend .po files are refreshed.
Crowdin exported the frontend translations to a folder named after
%two_letters_code%, so every regional variant of a language landed in the
same folder: zh-CN and zh-TW both gave "zh", and the last one downloaded
overwrote the other. Mapping the Chinese locales apart would have fixed
only that pair, and each new variant (pt-BR, es-MX, en-GB...) would have
needed its own entry.
Use %locale% instead, which is unique per locale, like the backend already
does with %locale_with_underscore%. format-deploy keeps the keys of
translations.json as they are today (fr, de...) and only keeps the region
(zh-cn, zh-tw) when several locales of the same language are translated.
The language detection and the language picker already match a locale
exactly before falling back to its language, so they need no change.
The export pattern is stored by Crowdin with the source file: the sources
must be uploaded again before the next download, and the zh-CN data that
was polluted with Traditional Chinese still needs to be re-uploaded.
Fixes#2749
The antivirus loader rebuilt the image block with an empty caption and
left alignment, so both were lost after a replace.
Signed-off-by: Ovgodd <c.gromoff@gmail.com>
The Playwright base image in the Dockerfile has been
updated from v1.62.1 to v1.63.0, in order to follow the
version of the `playwright` package in package.json.
The export feature is not working correctly with
the newer version, so we are downgrading to 0.54.0.
We need to refactorize the code to be compatible
with typst in order to work correctly.
Duplicating a document tree made two calls to the collaboration server
per node, all inside the database transaction: it held locks for the
duration of every call, and a failure midway left the documents already
created on the collaboration server behind, as orphans nothing can
reach anymore.
The duplication now runs in two phases. The structure is first
replicated in a transaction that makes no call to the collaboration
server, then each duplicate is seeded with the content of its source.
A failure while seeding deletes what was seeded - the deletion of the
collaboration server is idempotent and never refused - and removes the
replicated documents, so neither side keeps an orphan.
Signed-off-by: Marrrrrrrrry <34876935+Marrrrrrrrry@users.noreply.github.com>
`backendFetch` had no timeout: a backend that hangs hangs every
websocket
upgrade and fallback poll with it, piling up under load. The three
auth-path
calls it serves (`users/me`, `documents/{id}`, `accesses/me`) waited
forever,
so a slow backend took the whole collaboration service down with it.
Signed-off-by: Marrrrrrrrry <34876935+Marrrrrrrrry@users.noreply.github.com>
Users mentioning themselves got an email about something they just
did, which is noise. Keep recording the mention, skip the email.
Signed-off-by: BOUKERFA Mohamed El Amine <boukerfa.ma@gmail.com>
The cache key claimed before sending outlived a failed notification,
so the next mention in the same context was silently dropped until the
key expired although nobody had been notified. Delete it unless the
email went out and `notified_at` was saved.
Signed-off-by: BOUKERFA Mohamed El Amine <boukerfa.ma@gmail.com>
Gate the ability to mention to users with explicit
access so only collaborators can mention collaborators.
Signed-off-by: BOUKERFA Mohamed El Amine <boukerfa.ma@gmail.com>
A reader cannot see comments, so a mention would lead them nowhere.
Reject readers as mention targets. while users allowed to comment
see each other so they can pick who to mention.
Signed-off-by: BOUKERFA Mohamed El Amine <boukerfa.ma@gmail.com>
Use cache.add as a distributed lock keyed by document/user/thread to
ensure only the first concurrent mention sends the notification
Signed-off-by: BOUKERFA Mohamed El Amine <boukerfa.ma@gmail.com>
Add a dedicated "mention" throttle scope limiting calls
to the document mention endpoint to 30 requests per minute.
Signed-off-by: BOUKERFA Mohamed El Amine <boukerfa.ma@gmail.com>
Move the mention email off the request/response cycle into a Celery task
so the SMTP round-trip no longer delays the API response.
Signed-off-by: BOUKERFA Mohamed El Amine <boukerfa.ma@gmail.com>
Allow users with at least the commenter role on a document to mention
other collaborators in the document body or in a comment thread via
POST /documents/{id}/mention/. The mentioned user must already have
access to the document.
The mention record is always created, and the mentioned user is
notified by email with a link to the anchor, unless a notification
was already sent in the same context (document body or specific
thread) within a configurable cooldown period (15 minutes by default).
Signed-off-by: Mohamed El Amine BOUKERFA <boukerfa.ma@gmail.com>
Return all accesses on the document and its ancestors to any
user with access, keeping the limited user details serializer
and adding the user id to it, so that collaborators allowed
to comment can identify and mention each other.
Signed-off-by: Mohamed El Amine BOUKERFA <boukerfa.ma@gmail.com>
We can now paste docs url that will become interlinking.
So we don't want to pass titles through the inline content itself
anymore, to not leak any titles. The problem is that inline content
Inline content mappers are not async, so titles must be
resolved upfront.
We adapted the export interlinking to get titles from
a pre-resolved map instead of relying on inline content.
Pasting a bare link to another doc on the same domain now inserts an
interlink instead of a plain hyperlink, so it benefits from the same
title-sync and navigation behaviour as links added through the `/` or
`@` menu. Pasting over a selection, inside a code block, or a link the
current user can't resolve will display the doc id instead.
We want to introduce a feature flag that allows
duplicating documents along with their children when
enabled. We will be able to control not only
frontend side but also backend behavior
regarding document with children duplication.
We want to have a fine grained control over the
Duplicate with Children feature.
By adding the feature flag for Duplicate with Children,
we can enable or disable this feature for specific
users or groups without deploying new code.
This allows us to test the feature in a controlled
environment and gather feedback before a full rollout.
The quay.io/minio/minio and quay.io/minio/mc images now answer 401, and
the minio images are gone from Docker Hub as well: the dev stack, the
backend CI job and the helm dev-backend could not pull them anymore.
[pgsty/silo](https://hub.docker.com/r/pgsty/silo) and
[pgsty/mc](https://hub.docker.com/r/pgsty/mc) are community builds and drop
in replacement of minio. Only the executable name is changing from minio
to silo.
Search results were cmdk items navigating with router.push on select,
so the browser had no link to open elsewhere. Each result is now a real
link to the document: a plain click still goes through the quick search
onSelect, while ctrl, cmd, shift or middle click let the browser open it
in a new tab or window and keep the search modal open.
Signed-off-by: Armand <schneideretcollier.innovation@gmail.com>