Current section

Files

Jump to
pagantis_elixir_tools lib json_api validation_plug.ex
Raw

lib/json_api/validation_plug.ex

defmodule ElixirTools.JsonApi.ValidationPlug do
@moduledoc """
A Plug that checks whether a valid JSON API request is sent.
Also prepares the request to work together with the JsonApiController by assigning the json api
parameters to the request.
"""
use Ecto.Schema
import ElixirTools.JsonApi.Controller, only: [bad_input: 2, validate_params: 2]
alias __MODULE__
alias Plug.Conn
alias Ecto.Changeset
@body_methods ~w(POST PATCH DELETE PUT)
@allowed_fields ~w(type attributes)a
@required_fields @allowed_fields
embedded_schema do
field(:type, :string)
field(:attributes, :map)
end
@spec init(any) :: any
def init(default), do: default
@spec call(Conn.t(), any) :: Conn.t()
def call(conn = %{method: method}, _) when method in @body_methods do
changeset = validate_params(conn.params)
case changeset do
{:ok, _} -> assign_json_params(conn)
{:error, {:bad_request, errors}} -> bad_input(conn, errors)
end
end
def call(conn, _), do: conn
@spec assign_json_params(Conn.t()) :: Conn.t()
defp assign_json_params(conn) do
json_api_params = JaSerializer.Params.to_attributes(conn.params)
%{conn | assigns: Map.put(conn.assigns, :json_api_params, json_api_params)}
end
@spec validate_params(map) :: {:ok, any} | {:error, {:bad_request, String.t()}}
defp validate_params(%{"data" => data}) when is_map(data) do
validate_params(data, ValidationPlug)
end
defp validate_params(map) when map == %{}, do: {:ok, map}
defp validate_params(_), do: {:error, {:bad_request, "invalid json api"}}
@spec changeset(map) :: Changeset.t()
def changeset(params) do
%ValidationPlug{}
|> Changeset.cast(params, @allowed_fields, [])
|> Changeset.validate_required(@required_fields)
end
end