Exop v0.4.6 Exop.Operation behaviour
Provides macros for an operation’s contract definition and process/1 function.
Example
defmodule SomeOperation do
use Exop.Operation
parameter :param1, type: :integer, required: true
parameter :param2, type: :string, length: %{max: 3}, format: ~r/foo/
def process(params) do
"This is the operation's result with one of the params = " <> params[:param1]
end
end
Summary
Macros
Authorizes an action with predefined policy (see policy
macro docs).
If authorization fails, any code after (below) auth check will be postponed (an error {:error, {:auth, _reason}}
will be returned immediately)
Returns policy that was defined in an operation
Defines a parameter with name
and opts
in an operation contract.
Options could include the parameter value checks and transformations (like coercion)
Defines a policy that will be used for authorizing the possibility of a user to invoke an operation.
defmodule ReadOperation do
use Exop.Operation
Callbacks
Operation’s entry point. Takes defined contract as the single parameter.
Contract itself is a Keyword.t
list: [param_name: param_value]
Types
auth_result ::
:ok |
{:error, {:auth, :undefined_user}} |
{:error, {:auth, :undefined_policy}} |
{:error, {:auth, :undefined_action}} |
{:error, {:auth, atom}}
interrupt_result :: {:interrupt, any}
Macros
Specs
authorize(term, any, Keyword.t | nil) :: auth_result
Authorizes an action with predefined policy (see policy
macro docs).
If authorization fails, any code after (below) auth check will be postponed (an error {:error, {:auth, _reason}}
will be returned immediately)
Specs
current_policy(term) :: {Exop.Policy.t, atom}
Returns policy that was defined in an operation.
Specs
parameter(term, atom, Keyword.t) :: no_return
Defines a parameter with name
and opts
in an operation contract.
Options could include the parameter value checks and transformations (like coercion).
Example
parameter :some_param, type: :map, required: true
Available checks are:
type
Checks whether a parameter’s value is of declared type.
parameter :some_param, type: :map
required
Checks the presence of a parameter in passed params collection.
parameter :some_param, required: true
default
Checks if the parameter is missed and assigns default value to it if so.
parameter :some_param, default: "default value"
numericality
Checks whether a parameter’s value is a number and passes constraints (if constraints were defined).
parameter :some_param, numericality: %{equal_to: 10, greater_than: 0,
greater_than_or_equal_to: 10,
less_than: 20,
less_than_or_equal_to: 10}
in
Checks whether a parameter’s value is within a given list.
parameter :some_param, in: ~w(a b c)
not_in
Checks whether a parameter’s value is not within a given list.
parameter :some_param, not_in: ~w(a b c)
format
Checks wether parameter’s value matches given regex.
parameter :some_param, format: ~r/foo/
length
Checks the length of a parameter’s value.
parameter :some_param, length: %{min: 5, max: 10, is: 7, in: 5..8}
inner
Checks the inner of either Map or Keyword parameter.
parameter :some_param, type: :map, inner: %{
a: [type: :integer, required: true],
b: [type: :string, length: %{min: 1, max: 6}]
}
struct
Checks whether the given parameter is expected structure.
parameter :some_param, struct: %SomeStruct{}
func
Checks whether an item is valid over custom validation function.
parameter :some_param, func: &__MODULE__.your_validation/2
def your_validation(_params, param), do: !is_nil(param)
Coercion
It is possible to coerce a parameter before the contract validation, all validation checks
will be invoked on coerced parameter value.
Since coercion changes a parameter before any validation has been invoked,
default values are resolved (with :default
option) before the coercion.
The flow looks like: Resolve param default value -> Coerce -> Validate coerced
parameter :some_param, default: 1, numericality: %{greater_than: 0}, coerce_with: &__MODULE__.coerce/1
def coerce(x), do: x * 2
For more information and examples check out general Exop docs.
Specs
policy(term, Exop.Policy.t, atom) :: no_return
Defines a policy that will be used for authorizing the possibility of a user to invoke an operation.
defmodule ReadOperation do
use Exop.Operation
policy MyPolicy, :read
parameter :user, required: true, struct: %User{}
def process(_params) do
authorize(params[:user])
# make some reading...
end
end
A policy itself might be:
defmodule MyPolicy do
use Exop.Policy
def read(_user, _opts), do: true
def write(_user, _opts), do: false
end
Callbacks
Specs
process(Keyword.t) ::
{:ok, any} |
Exop.Validation.validation_error |
interrupt_result |
auth_result
Operation’s entry point. Takes defined contract as the single parameter.
Contract itself is a Keyword.t
list: [param_name: param_value]