Sekisho behaviour (Sekisho v0.1.0-dev)

Copy Markdown View Source

Permissions for Phoenix.

Your app has one permissions module, which lists its policies:

defmodule MyApp.Permissions do
  use Sekisho,
    repo: MyApp.Repo,
    policies: [MyApp.Blog.PostPolicy, MyApp.Docs.DocumentPolicy, MyApp.Orgs.OrgPolicy],
    sources: MyApp.Permissions.Sources,
    groups: [MyApp.Teams.Team]

  @impl Sekisho
  def actor(%MyApp.Accounts.Scope{user: user}), do: user
  def actor(nil), do: nil
end

and every question goes through it, with your scope (Phoenix's %Scope{}) first:

MyApp.Permissions.allowed?(scope, :update, post)        # true | false
MyApp.Permissions.authorize(scope, :update, post)       # :ok | {:error, %Sekisho.Denied{}}
MyApp.Permissions.authorize!(scope, :update, post)      # raises Sekisho.Denied, a 403

Post |> MyApp.Permissions.where_allowed(scope, :read) |> Repo.all()
MyApp.Permissions.with_permissions(posts, scope, [:update, :delete])

MyApp.Permissions.allowed_fields(scope, user)
MyApp.Permissions.redact(scope, user)
MyApp.Permissions.explain(scope, :update, document)

MyApp.Permissions.grant(scope, ana, :editor, on: document)
MyApp.Permissions.grant(scope, :link, :viewer, on: document)
MyApp.Permissions.revoke(scope, ana, :editor, on: document)
MyApp.Permissions.grants(scope, document)

{:ok, support} = MyApp.Permissions.create_role(scope, org, "Support", [:"investigations.view"])
MyApp.Permissions.grant(scope, ana, "Support", on: org)

The rules are in policies (Sekisho.Policy), and roles held in your own tables in sources (Sekisho.Sources).

Options

  • :repo: your Ecto repo (required).
  • :policies: your policies (required). They are read when the module is first asked, not when it compiles, so a change to one recompiles no other; validate!/0 checks them together (in a test, or at boot).
  • :sources: your Sekisho.Sources module.
  • :groups: the schemas of groups that may be granted roles (teams); their members come from Sekisho.Sources.members/1.
  • :pubsub: your Phoenix.PubSub, on which grants and revocations are broadcast (topic "sekisho").
  • :deny_as: :forbidden (403, the default) or :not_found (404).

Checks of a record

A check of a record asks the database: the record as it is there, with one query on its primary key. A rule about the actor alone (true, false) needs none. To ask about many records at once, use with_permissions/3.

Summary

Callbacks

The actor your scope is: a user struct, or nil for a visitor.

The link tokens your scope holds (from a link a visitor followed): [] by default.

Callbacks

actor(scope)

@callback actor(scope :: term()) :: struct() | nil

The actor your scope is: a user struct, or nil for a visitor.