ExDav.Storage behaviour (ExDav v0.4.10)

Copy Markdown View Source

Behaviour for DAV storage adapters (CalDAV and CardDAV).

Adapters return plain maps so the protocol layer is agnostic of any particular ORM. A reference Postgres adapter ships in ExDav.Storage.Postgres.

Both CalDAV and CardDAV use the same callbacks parameterised by kind:

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

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

Summary

Types

collection()

@type collection() :: %{
  name: String.t(),
  displayname: String.t(),
  description: String.t() | nil,
  kind: kind(),
  properties: map(),
  ctag: non_neg_integer(),
  resources: %{optional(String.t()) => resource()}
}

collection_name()

@type collection_name() :: String.t()

create_collection_opts()

@type create_collection_opts() :: [
  displayname: String.t() | nil,
  description: String.t() | nil,
  properties: map()
]

kind()

@type kind() :: :calendar | :addressbook

resource()

@type resource() :: %{
  name: String.t(),
  body: String.t(),
  content_type: String.t(),
  etag: String.t(),
  uid: String.t() | nil,
  component: String.t() | nil
}

resource_name()

@type resource_name() :: String.t()

update_props()

@type update_props() :: [displayname: String.t(), description: String.t() | nil]

username()

@type username() :: String.t()

Callbacks

create_collection(username, kind, collection_name, create_collection_opts)

@callback create_collection(
  username(),
  kind(),
  collection_name(),
  create_collection_opts()
) ::
  {:ok, collection()} | {:error, :no_user | :already_exists | :invalid}

delete_collection(username, kind, collection_name)

@callback delete_collection(username(), kind(), collection_name()) ::
  :ok | {:error, :not_found}

delete_resource(username, kind, collection_name, resource_name)

@callback delete_resource(username(), kind(), collection_name(), resource_name()) ::
  :ok | {:error, :not_found | :precondition_failed}

get_collection(username, kind, collection_name)

@callback get_collection(username(), kind(), collection_name()) :: collection() | nil

get_collection_with_resources(username, kind, collection_name)

@callback get_collection_with_resources(username(), kind(), collection_name()) ::
  collection() | nil

get_resource(username, kind, collection_name, resource_name)

@callback get_resource(username(), kind(), collection_name(), resource_name()) ::
  resource() | nil

list_collections(username, kind)

@callback list_collections(username(), kind()) :: [collection()]

put_resource(username, kind, collection_name, resource_name, body)

@callback put_resource(
  username(),
  kind(),
  collection_name(),
  resource_name(),
  body :: String.t()
) ::
  {:ok, resource()} | {:error, :not_found | :invalid}

sync_changes(username, kind, collection_name, since)

@callback sync_changes(
  username(),
  kind(),
  collection_name(),
  since :: non_neg_integer() | nil
) ::
  {[resource()], [resource_name()], non_neg_integer()} | {:error, :not_found}

update_collection(username, kind, collection_name, update_props)

@callback update_collection(username(), kind(), collection_name(), update_props()) ::
  {:ok, collection()} | {:error, :not_found | :invalid}

user_exists?(username)

@callback user_exists?(username()) :: boolean()