Issho.Policy behaviour (Issho v0.1.0)

Copy Markdown View Source

Your app's answer to "may this actor do this here?", and to "what is this document?". Issho has no roles and no user model: it asks, and your app answers with whatever it already uses.

defmodule MyApp.Collaboration do
  @behaviour Issho.Policy

  @impl true
  def authorize(%Issho.Identity{} = who, "board:" <> id, action) do
    if MyApp.Boards.allowed?(who.claims["user_id"], id, action),
      do: :ok,
      else: {:error, :forbidden}
  end

  @impl true
  def document(_who, "board:" <> id) do
    board = MyApp.Boards.get!(id)
    {:ok, %{engine: Issho.Engine.Map, initial: board.content}}
  end
end

Actions

authorize/3 gets the room (the topic, such as "board:42") and one of:

  • :join: to enter the room, see its people and their places;
  • :read: to receive its documents and their changes, asked again for the changes others make, so that a person whose access you take away stops receiving them;
  • :write: to change its documents;
  • :lock: to hold an advisory lock on a place.

Issho asks on join and on every message in both directions, so keep it fast: put what it needs in the identity's claims when you sign the token (Issho.Token.sign/4), or cache.

Documents

document/2 says what a document is when it opens for the first time on a node: its engine (Issho.Engine), its initial content from your server (a browser never seeds a document), and the engine's options. A room's documents are the room itself ("board:42") and paths under it ("board:42/n7/body"), so the nested documents of a canvas share the room's people and authorization.

Summary

Types

What a document is: its engine, its initial content (given to the engine's Issho.Engine.init/2 when the store has nothing), and the engine's options.

Callbacks

Whether the actor may do the action in the room.

What a document is, when it opens for the first time on a node.

Types

action()

@type action() :: :join | :read | :write | :lock

document()

@type document() :: %{
  :engine => module(),
  optional(:initial) => term(),
  optional(:opts) => keyword()
}

What a document is: its engine, its initial content (given to the engine's Issho.Engine.init/2 when the store has nothing), and the engine's options.

Callbacks

authorize(t, room, action)

@callback authorize(Issho.Identity.t(), room :: String.t(), action()) ::
  :ok | {:error, term()}

Whether the actor may do the action in the room.

document(arg1, document_id)

(optional)
@callback document(Issho.Identity.t() | nil, document_id :: String.t()) ::
  {:ok, document()} | {:error, term()}

What a document is, when it opens for the first time on a node.