lib/abacPdp.ex

defmodule ABAC.PDP do
  require ABAC
  require BPE
  require KVS
  require Record

  def policy(request, ABAC.policy(rules: r, combining: c)) do
    fold = fn ABAC.rule_ref(id: i) -> rule(request, :erlang.element(2, :kvs.get(:rule, i, KVS.kvs(mod: :kvs_mnesia)))) end
    :erlang.apply(:lists, c, [fold, r])
  end

  def policy(_, _), do: false

  def rule(
        ABAC.request(endpoint: e, resources: resources) = request,
        ABAC.rule(api_endpoint: e, type: :permit, object: o, condition: c, resource_match: rm) = rule
      ) do
    f = fn
      ^o -> true
      _ -> false
    end

    x = :lists.filter(f, resources)
    fold = fn _ -> :erlang.apply(:"Elixir.ABAC.Condition", c, [request, rule]) end
    x != [] and :erlang.apply(:lists, rm, [fold, x])
  end

  def rule(_, _), do: false

  def match(x, acc) do
    case :kvs.index_match(x, :object, KVS.kvs(mod: :kvs_mnesia)) do
      [ABAC.policy() | _] = p -> p ++ acc
      _ -> acc
    end
  end

  # PDP
  def decision(request) do
    {new_request, policy} = ABAC.Attributes.request(request)
    x = :lists.foldl(fn x, acc -> match(x, acc) end, [], policy)
    x != [] and :lists.all(&policy(new_request, &1), x)
  end
end