Add calendar/address-book sharing backend

Introduce internal/db, a small SQLite-backed store (pure-Go
modernc.org/sqlite, no CGO) at <data_dir>/nidus.db holding
calendar_shares and addressbook_shares grant tables (owner, resource
name, shared-with user, read/write permission). This is the first step
towards user management and a web UI: a real datastore that a future
admin CLI/UI can build on, instead of the static config.yaml.

Wire sharing into the CalDAV/CardDAV backends:
- ListCalendars/ListAddressBooks now also include resources shared with
  the requesting user, exposed under the synthetic local name
  "<owner>~<name>" in the grantee's own home-set — no separate account,
  no data copying, the object still physically lives under the owner's
  store.Store namespace.
- All read paths (Get/List/QueryCalendarObjects, address book
  equivalents) resolve the synthetic name back to (owner, real name) and
  require any share (read or write) to exist.
- All write paths (Put/Delete object, DeleteCalendar/AddressBook)
  additionally require a write-permission share; read-only shares get a
  403 Forbidden.
- CreateCalendar/CreateAddressBook remain scoped to the acting user's own
  namespace — sharing an existing collection is done via ShareCalendar/
  ShareAddressBook, not by creating one directly in someone else's name.

Add internal/db/shares_test.go (grant/lookup/update/unshare/list
semantics) and internal/{caldav,carddav}/backend_test.go (shared
calendar/address book visibility, write permission enforcement,
unauthorized access rejection). Update README (features, new "Sharing
calendars and address books" section, project layout, dependencies) and
copilot-instructions.md to document the new package and sharing model.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-08-18 20:10:31 +02:00
co-authored by Copilot
parent 21bac66b07
commit daa51d62b1
12 changed files with 1041 additions and 59 deletions
+26
View File
@@ -12,6 +12,8 @@ A self-hosted **CalDAV**, **CardDAV**, and **WebDAV** server written in Go.
- HTTP Basic Auth with **bcrypt** password storage
- Per-user isolated collections
- **Calendar/address book sharing** — grant other users read or write
access to your calendars/address books
- Auto-discovery via `/.well-known/caldav` and `/.well-known/carddav`
- Optional **TLS** (or use a reverse proxy)
- Structured logging (text or JSON)
@@ -136,6 +138,28 @@ Use the GNOME Online Accounts panel:
---
## Sharing calendars and address books
A user can grant another user read or write access to one of their own
calendars or address books. Shared resources show up automatically in the
grantee's own home-set alongside their own calendars — no separate account
or extra client configuration needed.
Sharing grants are stored in a small SQLite database at
`<data_dir>/nidus.db` (not in `config.yaml`). There's no CLI or web UI for
managing shares yet — the initial backend groundwork lives in
`internal/db` (see `ShareCalendar`, `UnshareCalendar`,
`ShareAddressBook`, `UnshareAddressBook`), which a future admin CLI or web
UI will call into.
A calendar that `alice` shares with `bob` appears in bob's calendar
home-set as `/cal/home/alice~work/` (i.e. `<owner>~<calendar name>`) — the
data itself still physically lives under alice's own storage; nothing is
copied. The same scheme applies to address books under `/card/home/`.
Read-only shares reject any write (PUT/DELETE) with `403 Forbidden`.
---
## TLS / Reverse proxy
### Self-signed certificate (development)
@@ -209,6 +233,7 @@ caldav-server/
│ ├── caldav/ # CalDAV backend
│ ├── carddav/ # CardDAV backend
│ ├── config/ # YAML config loader
│ ├── db/ # SQLite store (calendar/address book shares)
│ ├── store/ # filesystem storage layer
│ └── webdav/ # WebDAV file handler
├── tools/hashpwd/ # bcrypt password hasher CLI
@@ -240,3 +265,4 @@ go test ./... -race
| `golang.org/x/crypto` | bcrypt |
| `golang.org/x/net` | `golang.org/x/net/webdav` |
| `gopkg.in/yaml.v3` | YAML config parsing |
| `modernc.org/sqlite` | Pure-Go SQLite driver (calendar/address book shares) |