Commit Graph
5 Commits
Author SHA1 Message Date
Linus Rath 6d22814e5f fix: move settings and plugin credentials that no longer decrypt aside instead of refusing every save #1066
The earlier fix answered 503 to every read and write of a settings file
or plugin vault that doesn't decrypt, so a rotated SESSION_SECRET left
the user with no way out: even disconnecting a plugin failed. Now such a
document reads as nothing stored, and the next write first moves it
aside, then saves as usual. The bytes are kept unchanged, so the data can
be restored with the old secret:

- local mode renames the file to `<file>.unreadable-<time>` next to it
- shared mode copies the document to `<id>.unreadable-<time>`, then
  deletes the original only if it is still the same document

A settings file too short to hold anything reads as nothing stored and
is written over, as before 585e10041. The 503 is now only for a shared
store that can't be reached or a file that can't be read at all.

Credentials the admin set up for a plugin no longer read the user's
vault, so they keep working when it can't be read, and the credential
list still reports their status.
2026-10-31 23:57:08 +01:00
Linus Rath 741983c53c feat: keep users' plugin credentials in the shared store without losing a concurrent save #1066 2026-10-31 23:00:42 +01:00
Linus Rath 585e10041e fix: refuse to save over stored settings or plugin credentials that no longer decrypt #1066 2026-10-31 22:54:35 +01:00
Linus Rath 6aa48c300d fix: keep plugin credentials when the docker container is recreated 2026-10-31 17:50:07 +01:00
Linus Rath 022b83c005 feat: let plugins use accounts and API keys through the server without seeing them
Plugins that talk to Nextcloud, Paperless or an AI provider used to need
the password or key in their own settings, readable by the plugin and
stored in the browser. A plugin can now declare credentials in its
manifest and send requests "with credential X" through the server:

- `credentials` in the manifest: admin scope (secret and server from the
  admin config) or user scope (the user connects an account; the server
  address is fixed or chosen by the user)
- `/api/plugin-secrets`: the user's connected accounts, encrypted per
  mail account under `PLUGIN_SECRETS_DIR`; listing never returns secrets
- `/api/plugin-proxy`: adds the secret and forwards only to the
  credential's own origin, through the SSRF guard unless the admin set
  the server up or listed it in `PLUGIN_PROXY_PRIVATE_ORIGINS`; no
  redirects or WebDAV moves to other servers, streamed bodies capped at
  512 MB up and 2 GB down, 300 requests a minute per plugin, 8 at once
  per user, and one audit line per request without paths or bodies
- a capture mode that stores a secret from a sign-in response (Nextcloud
  Login Flow v2) and removes it from what the plugin gets back
2026-10-14 04:00:36 +02:00