Commit Graph
3960 Commits
Author SHA1 Message Date
Linus Rath 2acf79db43 fix: keep other instances' domain branding and server secrets when saving one entry #1066 2026-10-31 23:57:28 +01:00
Linus Rath 68d64f5018 fix: pair the policy with its own version and keep config reloads and saves from undoing each other #1066
Fixes from the review of the admin part:
- GET /api/admin/policy reads the policy and its version together; an
  identity check waiting on the store let another replica's change pair
  the old policy with the new ETag, and a save with it then won.
- A policy save answers with the stored policy and its ETag, and the
  policy, organisation, plugins and themes pages continue from that
  instead of reading it back from an instance that may not have it yet.
- A stored policy that doesn't parse keeps its version, so a save can
  replace it instead of answering 409 forever.
- A reload of another replica's change throws when this replica's writes
  kept landing while it read, so the change poller tries again; a write
  whose reload raced it reads the document again instead of applying its
  older result.
- Dropping a deleted plugin from the policy rereads policy.json first in
  local mode, as every other write does.
- New updateAdminConfig(key, change) builds a value on the stored one.

The policy route's test mocks gain getPolicyWithVersion.
2026-10-31 23:55:17 +01:00
Linus Rath 698b881f1f refactor: use the shared store's own outage check in the admin code #1066 2026-10-31 23:45:53 +01:00
Linus Rath d6e98e207a Merge branch 'feat/multi-instance' into feat/multi-instance-admin 2026-10-31 23:45:00 +01:00
Linus Rath 9e2b59847f refactor: recognise a shared-store outage by name, so every bundle's module copy sees it 2026-10-31 23:31:02 +01:00
Linus Rath 4983325f32 feat: bring the admin config, password, state and audit log along when moving to a shared store #1066 2026-10-31 23:26:52 +01:00
Linus Rath f531ef63b1 feat: print the same setup token on every instance #1066 2026-10-31 23:25:10 +01:00
Linus Rath ade95013f8 feat: keep one admin audit log for every instance #1066 2026-10-31 23:23:00 +01:00
Linus Rath 291b6364c9 feat: count admin login attempts across every instance and refuse sign-in while the shared store is down #1066
The three admin login limiters (5 per address and 50 overall in one
reservation, 5 per known device) keep their numbers and still don't count
refused attempts, but live in the store: memory in this process as before,
or the shared store with several replicas. checkRateLimit and
checkDeviceRateLimit are async now; the login route awaits them and
answers 503 "Sign-in is temporarily unavailable" when the store can't be
reached. The two limiter tests gain await and reset the store's counters,
which vi.resetModules no longer clears.

The admin code tells a store outage by the error's name, since the store
may come from another bundle's copy of the module.
2026-10-31 23:18:40 +01:00
Linus Rath ee5a107649 fix: answer 409 for a stale policy save also when another bundle made the config manager #1066 2026-10-31 23:17:36 +01:00
Linus Rath a048689179 feat: check admin sign-outs and password changes against the shared store on every instance #1066 2026-10-31 23:12:23 +01:00
Linus Rath cde02f5a48 fix: refuse the old admin password everywhere right after it was changed 2026-10-31 23:07:11 +01:00
Linus Rath 7a482a4d0e feat: share admin config and policy between instances and spread changes within seconds #1066 2026-10-31 23:03:57 +01:00
Linus Rath 25408b2ac2 fix: refuse a policy save from a page opened before someone else saved #1066
The admin pages save the whole policy from the draft they loaded. A
save from a page opened before another tab's or another admin's save,
or before a deleted plugin was dropped from the policy, used to put the
older policy back. GET /api/admin/policy now sends the policy version as
an ETag; the policy, organisation, plugins and themes pages send it back
as If-Match, and a save based on an older version answers 409 and keeps
the draft on the page. A PUT without If-Match replaces the policy as
before. Deleting a plugin or theme changes only its id in the stored
policy, and a policy import compares against what it replaces.

Test mocks of the config manager gain getPolicyVersion and updatePolicy,
which the route and the extension cleanup now call.
2026-10-31 22:57:57 +01:00
Linus Rath fd4a319eae feat: show the storage and how many instances checked in on the admin overview #1066 2026-10-31 22:46:08 +01:00
Linus Rath c20ecd4b1a refactor: let each store bring its own step for the shared-store import 2026-10-31 22:42:14 +01:00
Linus Rath 1b2d81be27 feat: hold each instance back until it has loaded from the shared store and add a readiness check #1066 2026-10-31 22:40:51 +01:00
Linus Rath df90492258 feat: add a shared store that keeps today's files by default and can use a redis-protocol server #1066 2026-10-31 22:40:44 +01:00
Linus Rath 0571b8f2ec fix: show pictures apple mail sends inline as attachments #1478 2026-10-31 22:08:56 +01:00
Linus Rath 35508913ac feat: show marketplace screenshots above the versions and open them large on click 2026-10-31 18:55:05 +01:00
Linus Rath 5b8cf60bd9 ci: run the integration suite in the playwright image that matches the installed version 2026-10-31 18:53:00 +01:00
Linus Rath 521b0aedab fix: stop naming a jmap metadata property in the demo client 2026-10-31 18:52:29 +01:00
Linus Rath 088a982218 test: expect 30 locales now that vietnamese is in 2026-10-31 18:50:55 +01:00
Linus Rath 1918d1010f fix: word the vietnamese settings discard dialog like calendar and contacts 2026-10-31 18:50:29 +01:00
Linus Rath d23a2869d1 Merge remote-tracking branch 'origin/main' into fix/found-fix-server
# Conflicts:
#	Dockerfile
#	docker-compose.yml
2026-10-31 18:17:39 +01:00
Linus Rath f884ffe441 Merge branch 'fix/found-fix-ui' into fix/found-fix-server 2026-10-31 18:17:13 +01:00
Linus Rath 5fe7d1a65a fix: keep existing compose volumes and add the two that were missing 2026-10-31 18:12:00 +01:00
Linus Rath f6eb34c909 fix: remove the admin switch for user theme uploads, which users can't do 2026-10-31 18:10:03 +01:00
Linus Rath 136e6be8fd refactor: drop the unused draft autosave interval setting 2026-10-31 18:07:16 +01:00
Linus Rath fa9aad95b4 docs: describe where the push relay sends the account label 2026-10-31 18:06:08 +01:00
Linus Rath 9f0413d50b docs: say in the Lite readme that sign-in with SSO works when Stalwart serves Lite 2026-10-31 18:04:57 +01:00
Linus Rath 88351b2333 fix: point the outgoing hosts list at the current usage stats and updates pages 2026-10-31 18:02:01 +01:00
Linus Rath 65015e1630 fix: describe when the unified mailbox section appears instead of the old empty header 2026-10-31 18:00:56 +01:00
Linus Rath 6fc3994aac fix: keep plugin credentials and update-check state across container recreates 2026-10-31 18:00:13 +01:00
Linus Rath 100f6db309 fix: skip the setup wizard in demo mode without a mail server 2026-10-31 18:00:13 +01:00
Linus Rath ae96b9e0aa fix: say what the setup wizard's stalwart features switch turns on 2026-10-31 17:58:34 +01:00
Linus Rath 485e48648e fix: stop promising offline support in the install prompt 2026-10-31 17:57:38 +01:00
Linus Rath 6a1da49f52 fix: let accessibility reset bring back the organisation's defaults and cover every option 2026-10-31 17:57:20 +01:00
Linus Rath ddc24e4fc7 fix: let a browser an admin signed in from before past the shared admin login limit 2026-10-31 17:55:29 +01:00
Linus Rath e15c335bec fix: pick up admin changes saved by another replica without a restart 2026-10-31 17:54:40 +01:00
Linus Rath 48c8d37e37 fix: hide subscribe to calendar in lite, which can't fetch feeds 2026-10-31 17:52:28 +01:00
Linus Rath 825d6e76f8 fix: let admins switch off usage stats by clearing the collector address 2026-10-31 17:51:09 +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 072a4219be fix: drop the connector address setting that nothing used 2026-10-31 17:49:54 +01:00
Linus Rath f11ddf82dd fix: tell banner plugins when an admin opened the mailbox through impersonation 2026-10-31 17:48:29 +01:00
Linus Rath a9e93881b5 feat: match filter conditions against a regular expression #885 2026-10-31 17:45:26 +01:00
Linus Rath dcc785690c fix: apply the log level and format set in the setup wizard or admin console 2026-10-31 17:45:06 +01:00
Linus Rath 65ec66b8ef fix: send embedded-mode messages to the parent origin set in the admin console 2026-10-31 17:43:03 +01:00
Linus Rath 73a7bb7bcd fix: send the headers plugins add to an outgoing message instead of dropping them 2026-10-31 17:40:20 +01:00
Linus Rath f8805b8d52 fix: keep remote content blocked for trusted senders when the organisation locks it to block 2026-10-31 17:32:24 +01:00