Sekisho.LiveView (Sekisho v0.1.0-dev)

Copy Markdown View Source

Permissions in LiveView: events checked before your handle_event/3 runs, and pages that lose their access while they are open.

Add the hook to a live_session, after the one that sets the scope:

live_session :app,
  on_mount: [
    {MyAppWeb.UserAuth, :require_authenticated},
    {Sekisho.LiveView, MyApp.Permissions}
  ] do
  live "/documents/:id", DocumentLive
end

Then, in mount/3, say what the page needs, and which events take which permission on which assign:

def mount(%{"id" => id}, _session, socket) do
  document = Docs.get_document!(socket.assigns.current_scope, id)

  {:ok,
   socket
   |> assign(document: document)
   |> Sekisho.LiveView.watch(:read, document)
   |> Sekisho.LiveView.authorize_events(%{
     "save" => {:update, :document},
     "delete" => {:delete, :document}
   })}
end

An event of the map is refused when the scope does not have its permission on the assign (a flash, and your handle_event/3 is not called). When access to a watched record is revoked (a grant taken away, a role changed, a membership of your own tables: MyApp.Permissions.changed/0), the page goes away with a flash: to "/", or where :revoked_to says.

It needs :pubsub in use Sekisho.

Options

{Sekisho.LiveView, {MyApp.Permissions, opts}}:

  • :scope — the assign of the scope (:current_scope).
  • :revoked_to — where a page goes when its access is revoked ("/").
  • :revoked — its flash ("You no longer have access to this page.").
  • :denied — the flash of a refused event ("You are not allowed to do that.").

Flashes are your words: pass translated ones (Gettext) here.

Summary

Functions

Events checked before handle_event/3: %{"delete" => {:delete, :document}} takes :delete on @document.

The page needs the permission on the record: when it loses it, it goes away.

Functions

authorize_events(socket, events)

@spec authorize_events(Phoenix.LiveView.Socket.t(), %{
  required(String.t()) => {atom(), atom()}
}) ::
  Phoenix.LiveView.Socket.t()

Events checked before handle_event/3: %{"delete" => {:delete, :document}} takes :delete on @document.

watch(socket, permission, record)

The page needs the permission on the record: when it loses it, it goes away.