Current section

Files

Jump to
authorize lib authorize.ex
Raw

lib/authorize.ex

# defmodule Authorize do
# defmacro __using(_options) do
# end
#
# defmacro authorize(do: block) do
# quote do
# defmodule Authorization do
# use Authorize.Authorization
#
# unquote(block)
# end
#
# def authorize(struct_or_changeset, actor, context \\ nil) do
# __MODULE__.Authorization.authorize(struct_or_changeset, actor, context)
# end
# end
# end
# end
defmodule Authorize.Inline do
defmacro __using__(_options) do
quote do
use Authorize
import unquote(__MODULE__)
end
end
defmacro authorize(do: block) do
quote do
unquote(block)
end
end
end
defmodule Authorize do
defmacro __using__(_options) do
quote do
import unquote(__MODULE__)
Module.register_attribute(__MODULE__, :rules, accumulate: true)
@before_compile unquote(__MODULE__)
end
end
def create_authorize() do
quote do
def is_changeset?(%{__struct__: :"Elixir.Ecto.Changeset"}), do: true
def is_changeset?(_), do: false
def get_struct(%{__struct__: :"Elixir.Ecto.Changeset"} = changeset), do: changeset.data
def get_struct(struct), do: struct
def authorize(struct_or_changeset, actor, context) do
@rules
|> Enum.reverse
|> Enum.filter(fn
{ctx, _, _} when is_atom(ctx) -> ctx == :all || ctx == context
{ctx, _, _} -> ctx == :all || Enum.member?(ctx, context)
end)
|> Enum.reduce(:undecided, fn
({_context, description, rule_func}, :undecided) ->
apply(__MODULE__, rule_func, [struct_or_changeset, actor])
(_fun, other) -> other
end)
|> case do
:undecided ->
{:unauthorized, struct_or_changeset, "no authorization rule found"}
other ->
other
end
end
def authorize(struct_or_changeset, actor), do: authorize(struct_or_changeset, actor, :all)
end
end
defmacro __before_compile__(_env) do
create_authorize
end
def apply_rule(description, struct_or_changeset, actor) do
apply(__MODULE__, String.to_atom(description), [struct_or_changeset, actor])
end
def create_rule(context, description, struct_or_changeset, actor, do: rule_block) do
rule_func = String.to_atom(description)
quote do
@rules {unquote(context), unquote(description), unquote(rule_func)}
def unquote(rule_func)(unquote(struct_or_changeset), unquote(actor)) do
case unquote(rule_block) do
:undecided -> :undecided
:ok -> {:ok, unquote(struct_or_changeset)}
:unauthorized -> {:unauthorized, unquote(struct_or_changeset), unquote(description)}
# make composition of authorization functions possible
{:ok, _struct_or_changeset} -> {:ok, unquote(struct_or_changeset)}
{:unauthorized, _struct_or_changeset, "no authorization rule found"} -> :undecided
{:unauthorized, _struct_or_changeset, description} -> {:unauthorized, unquote(struct_or_changeset), description}
end
end
end
end
defmacro rule(description, changeset, actor, do: rule_block), do:
create_rule(:all, description, changeset, actor, do: rule_block)
defmacro rule(context, description, changeset, actor, do: rule_block), do:
create_rule(context, description, changeset, actor, do: rule_block)
end