ValidateQuery v0.1.0 ValidateQuery View Source

A plug to validate query parameters and filter out parameters that were passed to leave only that which was allowed.

Example

This plug was made primarily for JSON-API like usage in mind. With this spec, a couple of query parameters are expected, such as include, filter and sort:

defmodule MyApp.UserController do
  plug(ValidateQuery,
    include: {["company", "profile"], :list},
    filter: [name: {:any}, only_active: {:any, :boolean, true}],
  )

  def index(conn, _params) do
    # return response
  end
end

In the above example we filter two different query parameters: include and filter.

  • include accepts a list where only company and profile are accepted as values.
  • filter accepts a map with the keys name and only_active, of which name can be any value and only_active must be boolean. If none was given only_active will default to true.

The following url is an example of a (full) valid query according to the above spec:

/users?include=company,profile&filter[name]=john&filter[only_active]=false.

Which would results in conn.params like so:

%{
  "include" => ["company", "profile"],
  "filter" => %{"name" => "john", "only_active" => false}
}

Usage

The ValidateQuery plug accepts arbitrary keys together with the options for that key. As in the example above, include and filter are the top-level keys as expected in the query parameters. Each key accepts a number of options:

  • A list of allowed values include: ["profile"]
  • A tuple with the allowed values, cast, and default value:
  include: {["profile"], :list}
  include: {:any, :list, ["profile"]}
  include: {:any}
  • A nested list of the above two:
  filter: [name: {:any}, active: {:any, :boolean, true}]
  filter: [company: ["company1", "company2"]]

If you're expecting a list of values, there are two ways of receiving this:

  • /users?include=item1,item2
  • /users?include[]=item1&include[]=item2

In order to support both of these, wrap the accepted values in a tuple with the :list cast: include: {["item1", "item2"], :list}

Casts are always performed before any of the validation.