carddav

package
v0.9.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 1, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package carddav implements a CardDAV server backed by the contacts store. It bridges the contacts.Store CRUD operations to the CardDAV protocol via emersion/go-webdav, enabling native contact apps (macOS Contacts.app, iOS, Thunderbird) to sync with Thane's contact directory.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Backend

type Backend struct {
	// contains filtered or unexported fields
}

Backend implements the carddav.Backend interface using the contacts store. It exposes a single read-write address book.

func NewBackend

func NewBackend(store *contacts.Store, logger *slog.Logger) *Backend

NewBackend creates a CardDAV backend backed by the given contact store.

func (*Backend) AddressBookHomeSetPath

func (b *Backend) AddressBookHomeSetPath(_ context.Context) (string, error)

AddressBookHomeSetPath returns the home set path where address books live.

func (*Backend) CreateAddressBook

func (b *Backend) CreateAddressBook(_ context.Context, _ *carddav.AddressBook) error

CreateAddressBook returns an error because Thane only supports its built-in address book.

func (*Backend) CurrentUserPrincipal

func (b *Backend) CurrentUserPrincipal(_ context.Context) (string, error)

CurrentUserPrincipal returns the principal URL for the authenticated user. Since Thane uses a single-user model, this is a fixed path.

func (*Backend) DeleteAddressBook

func (b *Backend) DeleteAddressBook(_ context.Context, _ string) error

DeleteAddressBook returns an error because the built-in address book cannot be deleted.

func (*Backend) DeleteAddressObject

func (b *Backend) DeleteAddressObject(_ context.Context, path string) error

DeleteAddressObject soft-deletes a contact.

func (*Backend) GetAddressBook

func (b *Backend) GetAddressBook(_ context.Context, path string) (*carddav.AddressBook, error)

GetAddressBook returns the address book at the given path.

func (*Backend) GetAddressObject

func (b *Backend) GetAddressObject(_ context.Context, path string, _ *carddav.AddressDataRequest) (*carddav.AddressObject, error)

GetAddressObject retrieves a single contact as a CardDAV address object.

func (*Backend) ListAddressBooks

func (b *Backend) ListAddressBooks(_ context.Context) ([]carddav.AddressBook, error)

ListAddressBooks returns the single Thane address book.

func (*Backend) ListAddressObjects

func (b *Backend) ListAddressObjects(_ context.Context, path string, _ *carddav.AddressDataRequest) ([]carddav.AddressObject, error)

ListAddressObjects returns all active contacts as CardDAV address objects.

func (*Backend) PutAddressObject

func (b *Backend) PutAddressObject(_ context.Context, path string, card vcard.Card, opts *carddav.PutAddressObjectOptions) (*carddav.AddressObject, error)

PutAddressObject creates or updates a contact from a vCard.

func (*Backend) QueryAddressObjects

func (b *Backend) QueryAddressObjects(_ context.Context, path string, query *carddav.AddressBookQuery) ([]carddav.AddressObject, error)

QueryAddressObjects filters contacts based on the CardDAV query. It loads all contacts and applies the filter in-memory.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server wraps a CardDAV handler with HTTP server lifecycle, Basic Auth middleware, and multi-listen support with dynamic rebinding.

Multiple listen addresses can be configured (e.g., localhost and a Tailscale interface). If some fail to bind at startup, the server logs warnings and continues. A background rebind loop periodically retries failed addresses so that interfaces that appear after startup (like VPN/Tailscale) are picked up automatically.

func NewServer

func NewServer(addrs []string, username, password string, backend *Backend, logger *slog.Logger) *Server

NewServer creates a CardDAV server. The server is created but not started. Call Server.Start to begin serving requests.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown gracefully stops all running listeners and the rebind loop.

func (*Server) Start

func (s *Server) Start(ctx context.Context) error

Start begins serving CardDAV requests on all configured addresses. It returns an error only if zero listeners bind successfully. For partial failures, warnings are logged and the rebind loop will retry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL