lib/step_flow/models/rights/right.ex

defmodule StepFlow.Rights.Right do
  @moduledoc """
  The Right context.
  """

  require Logger
  import EctoEnum

  defenum(RightEnum, [
    "abort",
    "create",
    "delete",
    "retry",
    "stop",
    "update",
    "view"
  ])

  defenum(EndpointEnum, [
    "endpoint::jobs",
    "endpoint::live_workers",
    "endpoint::metrics",
    "endpoint::notification_endpoint",
    "endpoint::notification_template",
    "endpoint::statistics",
    "endpoint::workers",
    "endpoint::worker_definitions",
    "endpoint::workflow",
    "endpoint::workflow_definition"
  ])

  @enforce_keys [:entity, :action]
  @derive {Jason.Encoder, only: [:entity, :action]}
  defstruct [:entity, action: []]

  use Ecto.Type

  def type, do: :map

  def cast(%{"entity" => entity, "action" => action})
      when is_binary(entity) and is_list(action) do
    {:ok, struct!(__MODULE__, %{entity: entity, action: action})}
  end

  def cast(%__MODULE__{} = right), do: {:ok, right}
  def cast(_), do: :error

  def load(%{"entity" => entity, "action" => action}) do
    {:ok, struct!(__MODULE__, %{entity: entity, action: action})}
  end

  def load(data) when is_map(data) do
    entity =
      for {key, val} <- data.entity do
        {String.to_existing_atom(key), val}
      end
      |> Enum.into(%{})

    action =
      for {key, val} <- data.action do
        {String.to_existing_atom(key), val}
      end
      |> Enum.into(%{})

    {:ok, struct!(__MODULE__, %{entity: entity, action: action})}
  end

  def dump(%__MODULE__{} = right), do: Ecto.Type.dump(:map, right)
  def dump(_), do: :error
end