Haytni v0.0.1 Haytni.RegisterablePlugin View Source

This plugin allows the user to register and edit their registration.

Change your_app/lib/your_app/user.ex to add two functions: create_registration_changeset and update_registration_changeset.

Example:

defmodule YourApp.User do
  # ...

  @attributes ~W[email password]a # add any field you'll may need
  # called when a user try to register himself
  def create_registration_changeset(%__MODULE__{} = struct, params) do
    struct
    |> cast(params, @attributes)
    |> validate_required(@attributes)
    # add any custom validation here
    |> Haytni.validate_create_registration()
  end

  # called when a user try to edit its own account (logic is completely different)
  def update_registration_changeset(%__MODULE__{} = struct, params) do
    struct
    |> cast(params, ~W[email password current_password]a)
    # /!\ email and password are not necessarily required here /!\
    # add any custom validation here
    |> Haytni.validate_update_registration()
  end

  # ...
end

Configuration:

  • password_length (default: 6..128): define min and max password length as an Elixir Range
  • email_regexp (default: ~R/^[^@\s]+@[^@\s]+$/): the Regexp that an email at registration or profile edition needs to match
  • case_insensitive_keys (default: ~W[email]a): list of fields to automatically downcase on registration. May be unneeded depending on your database (eg: citext columns for PostgreSQL or columns with a collation suffixed by “_ci” for MySQL)
  • strip_whitespace_keys (default: ~W[email]a): list of fields to automatically strip from whitespaces
  • email_index_name (default: "users_email_index"): the name of the unique index/constraint on email field

Routes:

  • registration_path (actions: new/create, edit/update, delete)

Link to this section Summary

Functions

Downcase values of a changeset to keys configured as case_insensitive_keys

Extract (early) the user from the HTTP request (http authentification, cookies/session, …)

Check if the user is in a valid state. This callback is intended to let know others plugins if we should reject the login (and why)

This callback is invoked when a user is editing its registration and change its email address. It is a facility (subset) to avoid you to handle it by yourself via validate_update_registration/1

Invoked when an authentification failed (wrong password). It receives the concerned account and a Keyword to return after updating it if any change have to be done to this user

This callback is invoked when a user (manually) log out. Its purpose is mainly to do some cleanup like removing a cookie

Invoked to accomplish a task right after user’s registration (insert). This callback allows you to do some linked changes to the database, send an email or whatever by appending it to multi

Invoked when an authentification is successful. Like on_failed_authentification/2, it receives the current user and a Keyword to return after updating it if you want to bring any change to this user to the database

Trim values of a changeset to keys configured as strip_whitespace_keys

Link to this section Functions

Link to this function case_insensitive_changes(changeset) View Source
case_insensitive_changes(changeset :: Ecto.Changeset.t()) :: Ecto.Changeset.t()

Downcase values of a changeset to keys configured as case_insensitive_keys

Link to this function case_insensitive_keys(default \\ ~W"email"a) View Source
Link to this function email_index_name(default \\ "users_email_index") View Source
Link to this function email_regexp(default \\ ~R"^[^@\s]+@[^@\s]+$") View Source

Extract (early) the user from the HTTP request (http authentification, cookies/session, …).

Returns a tuple of the form {conn, user} with user being nil if no user could be found at this early stage.

Callback implementation for Haytni.Plugin.find_user/1.

Check if the user is in a valid state. This callback is intended to let know others plugins if we should reject the login (and why).

Returns false if the user is allowed to login else {:error, reason} where reason is a string, an informative to be directly served to the end user.

For example, you may want to have some kind of ban plugin. This is the way to decline the login:

def invalid?(%{banned: true}), do: {:error, :banned} # or: {:error, dgettext("myapp", "you're banned")}
def invalid?(%{banned: _}), do: false

Callback implementation for Haytni.Plugin.invalid?/1.

Link to this function on_email_change(multi, changeset) View Source

This callback is invoked when a user is editing its registration and change its email address. It is a facility (subset) to avoid you to handle it by yourself via validate_update_registration/1.

It returns a tuple of {Ecto.Multi, Ecto.Changeset}, same as its arguments, to permit to the callback to add any operation to multi or change to changeset.

This callback is called before updating the user but the actions added to multi will be run after its update.

Callback implementation for Haytni.Plugin.on_email_change/2.

Link to this function on_failed_authentification(user, keywords) View Source

Invoked when an authentification failed (wrong password). It receives the concerned account and a Keyword to return after updating it if any change have to be done to this user.

For example, you can use it as follows to count the number of failed attempts to login:

def on_failed_authentification(user = %_{}, keyword) do
  Keyword.put(keyword, :failed_attempts, user.failed_attempts + 1)
end

Note: we choose to use and pass keyword as an accumulator to let the possibility to plugins to deal themselves on a conflict (several different plugins which want to alter a same field). Even if Keyword allows a same key to be defined several times, you’ll probably don’t want it to happen as the last defined value for a given key will (silently) override the others.

Callback implementation for Haytni.Plugin.on_failed_authentification/2.

This callback is invoked when a user (manually) log out. Its purpose is mainly to do some cleanup like removing a cookie.

Callback implementation for Haytni.Plugin.on_logout/1.

Invoked to accomplish a task right after user’s registration (insert). This callback allows you to do some linked changes to the database, send an email or whatever by appending it to multi.

Remember to comply to Ecto.Multi functions. In particular Ecto.Multi.run: the function called by it have to return {:ok, your value} or {:error, your value}. Also note that the inserted user will be passed to the function called by Ecto.Multi.run as the :user key to the map received by the last one as its (only) argument.

The following example illustrate how to send a welcome mail:

def on_registration(multi = %Ecto.Multi{}) do
  multi
  |> Ecto.Multi.run(:send_welcome_email, fn %{user: user} ->
    send_welcome_email_to(user)
    {:ok, :success}
  end)
end

Callback implementation for Haytni.Plugin.on_registration/1.

Link to this function on_successful_authentification(conn, user, keywords) View Source

Invoked when an authentification is successful. Like on_failed_authentification/2, it receives the current user and a Keyword to return after updating it if you want to bring any change to this user to the database.

To continue our example with a failed attempts counter, on a successful authentification it may be a good idea to reset it in this scenario:

def on_successful_authentification(conn = %Plug.Conn{}, user = %_{}, keywords) do
  {conn, user, Keyword.put(keywords, :failed_attempts, 0)}
end

Callback implementation for Haytni.Plugin.on_successful_authentification/3.

Link to this function password_length(default \\ 6..128) View Source
Link to this function strip_whitespace_changes(changeset) View Source
strip_whitespace_changes(changeset :: Ecto.Changeset.t()) :: Ecto.Changeset.t()

Trim values of a changeset to keys configured as strip_whitespace_keys

Link to this function strip_whitespace_keys(default \\ ~W"email"a) View Source