The checks on a request's ids and JSON body before the body reaches a
changeset, and telling when a create-or-replace PUT /:id lost the race for
its id.
Summary
Functions
Checks body against the keys the route accepts and the id in its path.
:ok when body, a request's body params, was a JSON object. Otherwise a
400 malformed problem, for any route that takes an object.
Plug.Parsers puts any other JSON value under "_json", alone. An object
that sends a "_json" key among others is still an object.
The id in param, written out as a UUID.
Whether an insert at the path's id failed because the id's row now exists, that is, another request created it after the route looked the id up.
The value of the request's parameter name, with where it came from: the
path, the query, or else the body.
One unknown_key entry for each key of object outside accepted, in key
order, each under path.
changeset with a mismatch error on field when body names an id there
other than id.
Types
@type param() :: {LightningWeb.API.Errors.location(), term()}
A value the request sent, with where it sent it, such as
{{:path, "id"}, "a1b2..."}. param/2 reads one from a conn.
Functions
@spec check(map(), Ecto.UUID.t(), [atom()]) :: {:ok, [LightningWeb.API.Errors.entry()]} | {:error, LightningWeb.API.Problem.t()}
Checks body against the keys the route accepts and the id in its path.
id is the id the URL names, already known to be a UUID.
Returns {:error, problem} with a 400 malformed problem when the body is
not a JSON object. Otherwise returns {:ok, entries}, empty when the body
passes: one unknown_key entry for each key outside accepted, and a
mismatch entry when the body's id names another.
@spec check_object(map()) :: :ok | {:error, LightningWeb.API.Problem.t()}
:ok when body, a request's body params, was a JSON object. Otherwise a
400 malformed problem, for any route that takes an object.
Plug.Parsers puts any other JSON value under "_json", alone. An object
that sends a "_json" key among others is still an object.
@spec id(param()) :: {:ok, Ecto.UUID.t()} | {:error, {:invalid_id, LightningWeb.API.Errors.location()}}
The id in param, written out as a UUID.
Returns {:error, {:invalid_id, location}} for anything else, naming where
the request sent it. Ecto.UUID.cast/1 would also take any 16-byte string as
a raw UUID, landing the request under an id it doesn't name.
@spec id_taken?(Ecto.Changeset.t()) :: boolean()
Whether an insert at the path's id failed because the id's row now exists, that is, another request created it after the route looked the id up.
@spec param(Plug.Conn.t(), String.t()) :: param()
The value of the request's parameter name, with where it came from: the
path, the query, or else the body.
@spec unknown_keys(map(), [LightningWeb.API.Errors.segment()], [atom()]) :: [ LightningWeb.API.Errors.entry() ]
One unknown_key entry for each key of object outside accepted, in key
order, each under path.
@spec validate_matches_path(Ecto.Changeset.t(), map(), atom(), Ecto.UUID.t()) :: Ecto.Changeset.t()
changeset with a mismatch error on field when body names an id there
other than id.