feat(caldav): username/password (Basic Auth) access with discovery + https URLs

- dav_router: add Basic-Auth principal-discovery tree at /caldav/ (and
  /.well-known/caldav) so clients can add a CalDAV account with server URL +
  username + password; lists all published calendars. Token URL /dav/{token}/
  still works without login. Handlers generalised over a base href.
- dav_util: derive the public origin from X-Forwarded-Proto/-Host (or
  PUBLIC_BASE_URL) so published URLs are https, not internal http:8080.
- local_router: expose caldav_login_url alongside caldav_url.
- frontend/i18n: show both the no-login token URL and the login URL + hint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-01 12:44:16 +02:00
parent 34e701fa78
commit fb32f0424f
6 changed files with 258 additions and 90 deletions

View File

@@ -3471,6 +3471,12 @@ function renderCalendarTable() {
<button class="btn btn-ghost btn-sm ct-dav-rotate" data-ct-dav-id="${cal.id}">${t('caldav_token_rotate')}</button>
</div>
<div class="ct-dav-hint">${t('caldav_hint')}</div>
<div class="ct-dav-box">
<span class="ct-dav-label">${t('caldav_login_url')}</span>
<input class="ct-dav-url" type="text" readonly value="${escHtml(cal.caldav_login_url || '')}">
<button class="btn btn-ghost btn-sm ct-dav-copy">${t('copy')}</button>
</div>
<div class="ct-dav-hint">${t('caldav_login_hint')}</div>
</td></tr>`;
}
}

View File

@@ -117,12 +117,14 @@ const translations = {
copy: 'Kopieren',
caldav_publish: 'CalDAV veröffentlichen',
caldav_unpublish: 'CalDAV deaktivieren',
caldav_published_url: 'CalDAV-URL:',
caldav_published_url: 'CalDAV-URL (ohne Login):',
caldav_url_copied: 'CalDAV-URL kopiert',
caldav_token_rotate: 'Token neu generieren',
caldav_token_rotated: 'Neuer Token erzeugt alte Abos müssen neu eingerichtet werden',
caldav_rotate_confirm: 'Neuen Token erzeugen? Die bisherige URL wird ungültig und bestehende Abos müssen mit der neuen URL neu eingerichtet werden.',
caldav_hint: 'Jeder mit dieser URL kann diesen Kalender abonnieren und bearbeiten. Über CalDAV-fähige Clients (Apple Kalender, Thunderbird, DAVx5) einbinden.',
caldav_hint: 'Jeder mit dieser URL kann diesen Kalender abonnieren und bearbeiten kein Login nötig. Über CalDAV-fähige Clients (Apple Kalender, Thunderbird, DAVx5) einbinden.',
caldav_login_url: 'CalDAV-URL (mit Login):',
caldav_login_hint: 'Alternativ im Client ein „CalDAV-Konto" mit dieser Server-URL sowie deinem Benutzernamen und Passwort hinzufügen dann werden alle deine veröffentlichten Kalender gefunden.',
share: 'Teilen',
import: 'Importieren',
export: 'Exportieren',
@@ -419,12 +421,14 @@ const translations = {
copy: 'Copy',
caldav_publish: 'Publish via CalDAV',
caldav_unpublish: 'Unpublish CalDAV',
caldav_published_url: 'CalDAV URL:',
caldav_published_url: 'CalDAV URL (no login):',
caldav_url_copied: 'CalDAV URL copied',
caldav_token_rotate: 'Regenerate token',
caldav_token_rotated: 'New token generated existing subscriptions must be re-added',
caldav_rotate_confirm: 'Generate a new token? The current URL will stop working and existing subscriptions must be re-added with the new URL.',
caldav_hint: 'Anyone with this URL can subscribe to and edit this calendar. Add it in a CalDAV-capable client (Apple Calendar, Thunderbird, DAVx5).',
caldav_hint: 'Anyone with this URL can subscribe to and edit this calendar — no login required. Add it in a CalDAV-capable client (Apple Calendar, Thunderbird, DAVx5).',
caldav_login_url: 'CalDAV URL (with login):',
caldav_login_hint: 'Alternatively add a "CalDAV account" in your client using this server URL plus your username and password — it will discover all your published calendars.',
share: 'Share',
import: 'Import',
export: 'Export',

View File

@@ -1,2 +1,2 @@
// Increment APP_VERSION with every code change
export const APP_VERSION = 'v66';
export const APP_VERSION = 'v67';