Skip to content

Releases

v5.6.3

Choose a tag to compare

@tchapi tchapi released this 30 Oct 20:38

This is a patch release adding a small feature:

  • Add a default availability for clients that don't follow the spec in 6113e16

How to upgrade

Nothing to do if you're on 5.6.0+

Full Changelog: v5.6.2...v5.6.3

v5.6.2

Choose a tag to compare

@tchapi tchapi released this 25 Oct 21:03

This is a patch release fixing two minor bugs:

  • Docker container now has tzdata and honours the TZ env var
  • Auth bypass now correctly shows the admin menu and light/dark mode menu

How to upgrade

Nothing to do if you're on 5.6.0

Full Changelog: v5.6.1...v5.6.2

v5.6.1

Choose a tag to compare

@tchapi tchapi released this 24 Oct 19:56

This is a patch release over 5.6.0 adding app key secret selectability in the dashboard.

How to upgrade

Nothing to do if you're on 5.6.0

Full Changelog: v5.6.0...v5.6.1

v5.6.0

Choose a tag to compare

@tchapi tchapi released this 24 Oct 19:24

This release mainly adds app keys: a way for a trusted service to read and write a user's calendars and address books without knowing the user's password. App keys are off by default, so nothing changes for existing instances.

  • App keys are off by default. Set APP_KEYS_ENABLED=true to turn them on. When they are off, the app keys page, the davis:app-key:* commands and the app key login are not available at all.
  • Keys are created and revoked from the new App keys page (in the user menu), or with bin/console davis:app-key:create, davis:app-key:list and davis:app-key:revoke <app_id>.
  • Each key has an explicit scope: a list of usernames, or * for all users. * does not include admins, because they can read every calendar and address book. To let a key act as an admin, add the admin's username to the scope.
  • A key can only act as an existing account, with exactly the same username. It never creates an account, even with *_AUTH_USER_AUTOCREATE.
  • The secret is shown once at creation and stored hashed. A key can have an expiry date, and can be revoked at any time.
  • Davis records which users each key acted as, with the first and last use. You can see it on the App keys page and in davis:app-key:list.
  • When you delete a user from the dashboard, Davis removes them from the keys that list them. A key that was only for this user is revoked.
  • The Diagnostics page shows whether app keys are on, and how many keys are active.

Important

A key acting as a user has the same access as this user. This includes calendars that other users shared with them, and calendars they are a delegate for. Keep the secret on the server side, never in a browser, and prefer a list of usernames over * when you can.

What's Changed

  • Added app keys in #313
  • Deleting a user, calendar or address book now also deletes the properties clients stored on it
  • Old MD5 passwords are now compared in constant time
  • Syncing the birthday calendar stops re-reading the address book for every contact
  • Public calendars are checked once per request instead of once per event

How to upgrade

0. Back up your database

This is a safety precaution in case you end up messing with a migration or the database in general. It's highly recommended, even if you know exactly what you're doing.

1. Update the code and migrate

You can now update the code (either directly or get the up to date container), and then run the remaining migrations with:

bin/console doctrine:migrations:migrate --allow-no-migration

2. Update or add necessary env vars

There is one new, optional env var:

 # Set to true to use app keys (see the README). Off by default.
 APP_KEYS_ENABLED=false

Full Changelog: v5.5.1...v5.6.0

v5.5.1

Choose a tag to compare

@tchapi tchapi released this 22 Oct 19:13

This is a minor releases mostly covering internals.

Important

The containers built with this release are now safe from CVE-2026-109618 and CVE-2026-109619 as the base PHP 8.4 alpine image has been patched. Update is highly recommended.

What's Changed

  • More unit tests
  • Use IDENTITY + Add CI checks for sqlite and pg in #304
  • Misc perf and validation fixes in #306 and #305

How to upgrade

Nothing to do if you're on v5.5.0

Full Changelog: v5.5.0...v5.5.1

v5.5.0

Choose a tag to compare

@tchapi tchapi released this 28 Sep 19:34

This is a minor releases covering a wide span of bug fixes and features to harden Davis and make it even more robust and resilient to various clients' behaviors and auth provider shenanigans.

⚠️ Read the changelog and the "How to upgrade" section below carefully

📰 Main new features or changes

  • ✨ New page: Diagnostics, at /dashboard/diagnostics (#297) to ease debugging and find misconfigurations (migrations you have not run, mail settings, DAV endpoint URL, timezone configuration, etc ...)
  • ✨ New command: php bin/console davis:mail:test you@example.org (#296). Sends one message with the actual mail settings to test them
  • 🔒 The shared directory is no longer writable by every account (#285). Any signed-in user can read it. Only admins can write, unless you set WEBDAV_PUBLIC_DIR_WRITABLE=true. See the upgrade note below.
  • 🐛 Events are saved even when there is a failure sending invitations (#296)
  • 🔒 An account cannot be saved without an email address (#296). An empty address quietly stops every invitation from that account. See the upgrade note below.
  • 🔤 LDAP is no longer case-sensitive for usernames (#289). Davis now uses the spelling the directory returns. See the upgrade note below.
  • 💪🏼 Frontend better validation and hardening (CSRF, CSS injection) (#290, #295)

🐛 Other bug fixes

  • CardDAV sync no longer loses changes and sync reports are much faster (#287) (based on @AnnoyingTechnology's work)
  • Saving a property no longer fails or adds up rows (#288)
  • Address books can be created without a name (#286) (Turns out the name is optional in CardDAV)
  • Subscribing to a calendar feed no longer fails when clients don't send default (#286)
  • The API answers when no key is set (API_KEY is empty by default) (#298)
  • The profiler no longer runs in production (#284)
  • Fix edge cases where a public calendar was not readable by everyone (#298)
  • Deleting an address book no longer crashes (#298)

⚙️ Misc

  • Docker images now use PHP 8.4 (#299), up from 8.3.
  • nginx and Caddy examples improvements and Dockerfile and env refactors to harden production and dev setup (#292)
  • /.well-known/caldav and /.well-known/carddav are now handled by Davis (#289) - No web server rule is needed, and it allows sub directories
  • Added logs on sending invitations to debug more easily (#296)
  • Repeated failed logins are throttled now (#292)
  • Performance improvements (new SAPI, allowing streaming responses) (#300)

How to upgrade

Important

The WebDAV folders are now checked at start-up: they must be absolute, exist, and sit outside the web root. Fix them before upgrading, if needed.

0. Back up your database

This is a safety precaution in case you end up messing with a migration or the database in general. It's highly recommended, even if you know exactly what you're doing.

1. Update the code and migrate

You can now update the code (either directly or get the up to date container), and then run the remaining migrations with:

bin/console doctrine:migrations:migrate --allow-no-migration

2. Update or add necessary env vars

WebDAV shared directory (only if WEBDAV_ENABLED=true)

Important

This is a change of behavior, read carefully

If you relied on the shared directory being writable by everyone, add:

WEBDAV_PUBLIC_DIR_WRITABLE=true

Otherwise only admins can write there from now on. Everyone can still read it in any case

3. LDAP accounts stored under a different spelling

Tip

Only if you use LDAP: AUTH_METHOD=LDAP on PostgreSQL or SQLite. MySQL and MariaDB compare text without regard to case so you can ignore

What changed. Davis used to store whatever username the person typed. It now stores the spelling your directory returns. So if someone logged in as ALICE and your directory says alice, Davis used to create the account as ALICE, and from now on it looks for alice.

What you would see. That person logs in fine but their calendars and contacts are gone — the data is still there, filed under the old spelling. If they typed their name two different ways over time, you may also have two accounts for them, one of them empty.

Find out if you are affected. Both lists should contain each person once, spelled the way your directory spells them:

SELECT username FROM users ORDER BY username;
SELECT uri FROM principals WHERE uri NOT LIKE '%calendar-proxy%' ORDER BY uri;

If a person appears twice, delete the empty account from the dashboard first, then follow the rename below for the one that kept the data.

To rename an account, back up your database, then run the block below. Replace ALICE with the spelling currently stored and alice with the spelling your directory returns

BEGIN;
UPDATE users                 SET username     = 'alice'            WHERE username = 'ALICE';
UPDATE principals            SET uri          = replace(uri, 'principals/ALICE', 'principals/alice')        WHERE uri = 'principals/ALICE' OR uri LIKE 'principals/ALICE/%';
UPDATE calendarinstances     SET principaluri = 'principals/alice' WHERE principaluri = 'principals/ALICE';
UPDATE addressbooks          SET principaluri = 'principals/alice' WHERE principaluri = 'principals/ALICE';
UPDATE calendarsubscriptions SET principaluri = 'principals/alice' WHERE principaluri = 'principals/ALICE';
UPDATE schedulingobjects     SET principaluri = 'principals/alice' WHERE principaluri = 'principals/ALICE';
UPDATE propertystorage       SET path = replace(path, 'calendars/ALICE/', 'calendars/alice/')       WHERE path LIKE 'calendars/ALICE/%';
UPDATE propertystorage       SET path = replace(path, 'addressbooks/ALICE/', 'addressbooks/alice/') WHERE path LIKE 'addressbooks/ALICE/%';
UPDATE propertystorage       SET path = replace(path, 'principals/ALICE', 'principals/alice')       WHERE path LIKE 'principals/ALICE%';
COMMIT;

The principals line also renames that person's two delegation entries, so you do not need to touch those separately. Run the two SELECTs again afterwards to confirm.

4. Accounts without an email address

An account whose email is empty never sends invitations (but it was hard to debug properly). The dashboard now refuses to save one, but existing accounts are untouched. To find all of the offending accounts:

SELECT uri, email FROM principals WHERE email IS NULL OR email = '';

The address has to be the one the account's calendar client sends as the event organiser, otherwise Davis has nothing to send an invitation on behalf of. You can check the mail settings themselves with php bin/console davis:mail:test you@example.org.

5. Web server configuration

If your web server rewrites /.well-known/caldav or /.well-known/carddav itself, you can drop those rules. They take precedence over Davis and will send clients to the wrong place on a sub-directory installation.

6. Reverse proxy on a PHP built without IPv6

If your PHP was built with --disable-ipv6 and you set SYMFONY_TRUSTED_PROXIES, your proxy has to reach Davis over IPv4 or every request returns a 500. Point it at 127.0.0.1 rather than localhost, which usually resolves to ::1 first. See the README for details.

Full Changelog: v5.4.4...v5.5.0

v5.4.4

Choose a tag to compare

@tchapi tchapi released this 06 Sep 21:23

This is mainly a security release. All users are encouraged to upgrade.

  • 🔒 Fixed an ACL bypass in the DAV server: appending ?sabreAction=asset to a URL skipped every permission check, letting any authenticated user read other users' events, contacts and files, and letting anonymous clients overwrite existing objects. The shortcut is now limited to the browser plugin's assets on the DAV root
  • 🔒 Empty passwords are now rejected by all authentication backends. With LDAP, an empty password was passed to ldap_bind, which some directories (notably Active Directory) treat as a successful anonymous bind, allowing a login as any user
  • 🔒 Destructive actions in the admin dashboard are now protected against CSRF: deleting users, calendars and address books, sharing and revoking calendars, and managing delegates are now POST requests carrying a token, instead of plain GET links
  • 🔒 The dashboard and the API now check that a calendar or address book belongs to the user in the URL before showing, editing, sharing or deleting it. Deleting a calendar that was shared with a user only removes that share and no longer touches the owner's calendar; a calendar can no longer be shared with its own owner
  • 🐛 The API no longer deletes all of a user's subscriptions and inbox items when one calendar is deleted, and GET /api/v1/calendars/{userId} no longer fails for users who have a calendar subscription

API note: PUT/PATCH/DELETE /api/v1/calendars/{userId}/{calendar_id} and the /shares endpoints now return 400 when calendar_id is a calendar merely shared with the user. DELETE on such an instance removes the share only.

What's Changed

  • Fixed security hole by @SeLLeRoNe in #268
  • Fixed Invitation replies (accepted / declined / tentative) sent by e-mail showing the attendee as "(null)" in some mail clients, Apple Mail in particular (db8e571)
  • Security fixes in #283

New Contributors

How to upgrade

Nothing to do if you're on v5.4.3

Full Changelog: v5.4.3...v5.4.4

v5.4.3

Choose a tag to compare

@tchapi tchapi released this 01 Jun 20:20

What's Changed

  • Shared calendars now inherit the calendar colour upon seeding in #266

This is a minor upgrade that embarks new minor dependencies releases.

How to upgrade

Nothing to do if you're on v5.4.2

Full Changelog: v5.4.2...v5.4.3

v5.4.2

Choose a tag to compare

@tchapi tchapi released this 25 May 14:24

What's Changed

This is a bugfix release correcting various small bugs around user deletion

How to upgrade

Nothing to do if you're on v5.4.1

Full Changelog: v5.4.1...v5.4.2

v5.4.1

Choose a tag to compare

@tchapi tchapi released this 14 Mar 17:41

What's Changed

This is a bugfix release correcting a bug where subscriptions would be deleted upon calendar deletion.

How to upgrade

Nothing to do if you're on v5.4.0

Full Changelog: v5.4.0...v5.4.1