ex_dav

⚠️ Beta / heavy WIP. APIs are unstable and may change between releases. Not yet recommended for production use.

CalDAV server library for Elixir. Mounts as a Plug under any host application. Ships with a Postgres-backed reference adapter and an in-memory adapter; bring your own for arbitrary backends.

Passes 57/57 of the caldav_client integration suite as of v0.3.0.

plug ExDav.CalDav.Plug,
storage: ExDav.Storage.Postgres,
authenticator: {ExDav.Authenticator.Basic,
verify: {ExDav.Storage.Postgres, :authenticate}}

What you get

Usage in a Phoenix app

# config/config.exs
config :ex_dav, repo: MyApp.Repo
# lib/my_app_web/endpoint.ex
plug ExDav.CalDav.Plug,
storage: ExDav.Storage.Postgres,
authenticator: {ExDav.Authenticator.Basic,
verify: {ExDav.Storage.Postgres, :authenticate}}

The Postgres adapter ships migrations in priv/repo/migrations of this package. Either copy them into your host app's migrations directory, or point Ecto at them via --migrations-path:

mix ecto.migrate --migrations-path deps/ex_dav/priv/repo/migrations

It creates four tables prefixed caldav_* (caldav_users, caldav_calendars, caldav_calendar_objects, caldav_calendar_object_tombstones) so they don't clash with host-app tables.

Breaking change in v0.2.0: tables were renamed from users, calendars, calendar_objects, calendar_object_tombstones to caldav_* for namespacing. Drop and re-run migrations, or rename manually.

Custom storage adapter

defmodule MyApp.CalDavStorage do
@behaviour ExDav.Storage
@impl true
def list_calendars(username) do
# return [%{name:, displayname:, description:, components:, ctag:, objects:}]
end
@impl true
def put_object(username, cal_name, obj_name, ical), do: ...
# ...all 11 callbacks
end

Then mount:

plug ExDav.CalDav.Plug,
storage: MyApp.CalDavStorage,
authenticator: {MyApp.CalDavAuth, []}

Custom authenticator

defmodule MyApp.CalDavAuth do
@behaviour ExDav.Authenticator
@impl true
def authenticate(conn, _opts) do
case extract_token(conn) do
{:ok, principal} -> {:ok, conn, principal}
:error -> :unauth
end
end
end

Standalone

For a runnable reference deployment, see apps/ex_dav_server in this repository — a minimal Phoenix app that wires the library to Postgres and ships an admin LiveView for managing CalDAV principals.

License

GNU General Public License v3.0 or later (GPL-3.0-or-later). See LICENSE.