Rajska v0.7.0 Rajska.ObjectScopeAuthorization View Source

Absinthe Phase to perform object scoping.

Authorizes all Absinthe's objects requested in a query by checking the value of the field defined in each object meta scope.

Usage

Create your Authorization module and add it and ObjectScopeAuthorization to your Absinthe Pipeline. Then set the scope of an object:

object :user do
  meta :scope_by, :id
  meta :rule, :default

  field :id, :integer
  field :email, :string
  field :name, :string

  field :company, :company
end

object :company do
  meta :scope_by, :user_id
  meta :rule, :default

  field :id, :integer
  field :user_id, :integer
  field :name, :string
  field :wallet, :wallet
end

object :wallet do
  meta :scope_by, :id
  meta :rule, :read_only

  field :id, :integer
  field :total, :integer
end

To define custom rules for the scoping, use Rajska.Authorization.has_user_access?/4. For example:

defmodule Authorization do
  use Rajska,
    valid_roles: [:user, :admin]

  @impl true
  def has_user_access?(%{role: :admin}, _struct, {_field, _field_value}, _rule), do: true
  def has_user_access?(%{id: user_id}, User, {:id, id}, _rule) when user_id === id, do: true
  def has_user_access?(_current_user, User, {_field, _field_value}, _rule), do: false
end

Keep in mind that the field_value provided to has_user_access?/4 can be nil. This case can be handled as you wish. For example, to not raise any authorization errors and just return nil:

defmodule Authorization do
  use Rajska,
    valid_roles: [:user, :admin]

  @impl true
  def has_user_access?(_user, _scope, {_field, nil}, _rule), do: true

  def has_user_access?(%{role: :admin}, User, {_field, _field_value}, _rule), do: true
  def has_user_access?(%{id: user_id}, User, {:id, id}, _rule) when user_id === id, do: true
  def has_user_access?(_current_user, User, {_field, _field_value}, _rule), do: false
end

The rule keyword is not mandatory and will be pattern matched in has_user_access?/4:

defmodule Authorization do
  use Rajska,
    valid_roles: [:user, :admin]

  @impl true
  def has_user_access?(%{id: user_id}, Wallet, {_field, _field_value}, :read_only), do: true
  def has_user_access?(%{id: user_id}, Wallet, {_field, _field_value}, :default), do: false
end

This way different rules can be set to the same struct. See Rajska.Authorization for rule default settings.

Link to this section Summary

Link to this section Functions