Packages

Elixir bindings for cedar_policy rust package

Current section

Files

Jump to
cedar_policy lib record.ex
Raw

lib/record.ex

defmodule CedarPolicy.Record do
alias CedarPolicy.RestrictedExpression
alias CedarPolicy.Entity
@datetime_regex ~r"^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])(?:T(?:[01]\d|2[0-3]):(?:[0-5]\d):(?:[0-5]\d)(?:\.\d{3})?(?:Z|[+-](?:[01]\d|2[0-3])(?:[0-5]\d)))?$"
@duration_regex ~r"^(\d+d){0,1}(\d+h){0,1}(\d+m){0,1}(\d+s){0,1}(\d+ms){0,1}$"
@type t() :: list({String.t(), RestrictedExpression.t()})
@type value() ::
atom() | integer() | float() | boolean() | String.t() | Entity.t() | DateTime.t() | t()
@spec new(
data ::
list({atom() | String.t(), value() | list(value())})
) :: t()
def new(data) do
Enum.map(data, fn {key, value} ->
{parse_key(key), parse_value(value)}
end)
end
defp parse_key(key) when is_binary(key), do: key
defp parse_key(key) when is_atom(key), do: to_string(key)
defp parse_value(value) when is_boolean(value), do: {:bool, value}
defp parse_value(value) when is_integer(value), do: {:long, value}
defp parse_value(value) when is_float(value), do: {:decimal, to_string(value)}
defp parse_value(value) when is_atom(value) or is_binary(value) do
cond do
is_atom(value) ->
{:string, to_string(value)}
String.match?(value, @datetime_regex) ->
{:date_time, value}
String.match?(value, @duration_regex) ->
{:duration, value}
is_ip?(value) ->
{:ip, value}
true ->
{:string, value}
end
end
defp parse_value(value) when is_struct(value, Entity), do: {:entity, value}
defp parse_value(value) when is_struct(value, DateTime),
do: {:date_time, DateTime.to_iso8601(value)}
defp parse_value(value) when is_list(value) do
cond do
Enum.all?(value, &is_tuple/1) -> {:record, value}
true -> {:set, Enum.map(value, &parse_value/1)}
end
end
defp is_ip?(value) do
if String.contains?(value, "/") do
[addr, prefix] = String.split(value, "/", parts: 2)
has_valid_suffix = match?({p, ""} when p in 0..128, Integer.parse(prefix))
is_ip?(addr) and has_valid_suffix
else
match?({:ok, _}, :inet.parse_address(String.to_charlist(value)))
end
end
end