authority_ecto v0.1.1 Authority.Ecto.Changeset
Convenient authentication-related functions for Ecto.Changeset
s.
Link to this section Summary
Functions
Hashes the value stored in the source
field, and puts the resulting
hash in the destination
field. The source
field will be removed
from the changeset
Generates a random token value into the given field if it is nil
Based on the token’s purpose
, assign an expiration DateTime
in the
given field
Validates that a change does not contain consecutive characters such as “abc” or “123”
Validates that a change does not contain repetitive characters such as “aaa” or “111”
Validate that a password field has a confirmation and complies with NIST’s Digital Identity Guidelines
Link to this section Types
Link to this section Functions
Hashes the value stored in the source
field, and puts the resulting
hash in the destination
field. The source
field will be removed
from the changeset.
By default, the password will be hashed using Comeonin.Bcrypt
. See
put_encrypted_password/4
to use a different algorithm. Valid options
are :bcrypt
, :argon2
, or :pbkdf2
.
Examples
iex> changeset = change(%User{}, %{password: "testing123", password_confirmation: "testing123"})
...> changeset = put_encrypted_password(changeset, :password, :encrypted_password)
...> Comeonin.Bcrypt.checkpw("testing123", get_change(changeset, :encrypted_password))
true
iex> changeset = change(%User{}, %{password: "testing123", password_confirmation: "testing123"})
...> changeset = put_encrypted_password(changeset, :password, :encrypted_password, :argon2)
...> Comeonin.Argon2.checkpw("testing123", get_change(changeset, :encrypted_password))
true
put_token(Ecto.Changeset.t(), field()) :: Ecto.Changeset.t()
Generates a random token value into the given field if it is nil.
Best when paired with Authority.Ecto.HMAC
or
Cloak encryption to prevent
leaking the tokens if the database is compromised.
Examples
It will set a random value if no value is present:
iex> changeset = %Token{} |> change() |> put_token(:token)
...> is_binary(get_change(changeset, :token))
true
If the field already has a value, it will not be changed:
iex> changeset = %Token{} |> change(token: "existing-value") |> put_token(:token)
...> get_field(changeset, :token)
"existing-value"
iex> changeset = %Token{token: "existing-value"} |> change() |> put_token(:token)
...> get_field(changeset, :token)
"existing-value"
Based on the token’s purpose
, assign an expiration DateTime
in the
given field.
The value of the purpose
field should correspond to a key in the config
list. The following formats are supported:
{n, :days}
{n, :hours}
{n, :minutes}
{n, :seconds}
Examples
iex> changeset = %Token{} |> change(purpose: :recovery)
...> changeset = put_token_expiration(changeset, :expires_at, :purpose, recovery: {24, :hours})
...> expires_at = get_change(changeset, :expires_at)
...> expires_at.__struct__
DateTime
validate_nonconsecutive(Ecto.Changeset.t(), field(), [max: integer(), message: String.t()]) :: Ecto.Changeset.t()
Validates that a change does not contain consecutive characters such as “abc” or “123”.
Options
:max
- the maximum number of consecutive characters, defaults to3
:message
- the message on failure, defaults tocontains more than %{max} consecutive characters
Examples
iex> changeset = change(%User{}, %{password: "abc"})
...> changeset = validate_nonconsecutive(changeset, :password)
...> changeset.errors[:password]
{"contains more than %{max} consecutive characters", [validation: :nonconsecutive, max: 3]}
iex> changeset = change(%User{}, %{password: "abc"})
...> changeset = validate_nonconsecutive(changeset, :password, max: 4)
...> changeset.errors[:password]
nil
validate_nonrepetitive(Ecto.Changeset.t(), field(), [max: integer(), message: String.t()]) :: Ecto.Changeset.t()
Validates that a change does not contain repetitive characters such as “aaa” or “111”.
Options
:max
- the maximum number of repeating characters, defaults to3
:message
- the message on failure, defaults tocontains more than %{max} repeating characters
Examples
iex> changeset = change(%User{}, %{password: "aaa"})
...> changeset = validate_nonrepetitive(changeset, :password)
...> changeset.errors[:password]
{"contains more than %{max} repeating characters", [validation: :nonrepetitive, max: 3]}
iex> changeset = change(%User{}, %{password: "aaa"})
...> changeset = validate_nonrepetitive(changeset, :password, max: 4)
...> changeset.errors[:password]
nil
validate_secure_password(Ecto.Changeset.t(), field()) :: Ecto.Changeset.t()
Validate that a password field has a confirmation and complies with NIST’s Digital Identity Guidelines.
Examples
Must be greater than 8 characters:
iex> changeset = change(%User{}, %{password: "a", password_confirmation: "a"})
...> changeset = validate_secure_password(changeset, :password)
...> changeset.errors[:password]
{"should be at least %{count} character(s)", [count: 8, validation: :length, min: 8]}
Must have a confirmation field:
iex> changeset = cast(%User{}, %{password: "pa$$word"}, [:password])
...> changeset = validate_secure_password(changeset, :password)
...> changeset.errors[:password_confirmation]
{"can't be blank", [validation: :required]}
Must have a matching confirmation field:
iex> changeset = cast(%User{}, %{password: "pa$$word", password_confirmation: "foobar"}, [:password, :password_confirmation])
...> changeset = validate_secure_password(changeset, :password)
...> changeset.errors[:password_confirmation]
{"does not match confirmation", [validation: :confirmation]}
Must not have more than 2 repeating characters (e.g. “aaa” or “111”):
iex> changeset = change(%User{}, %{password: "passsword", password_confirmation: "passsword"})
...> changeset = validate_secure_password(changeset, :password)
...> changeset.errors[:password]
{"contains more than %{max} repeating characters", [validation: :nonrepetitive, max: 3]}
Must not have more than 2 consecutive characters (e.g. “abc” or “123”):
iex> changeset = change(%User{}, %{password: "testing123", password_confirmation: "testing123"})
...> changeset = validate_secure_password(changeset, :password)
...> changeset.errors[:password]
{"contains more than %{max} consecutive characters", [validation: :nonconsecutive, max: 3]}
Must not be one of the 1,000 most common passwords:
iex> changeset = change(%User{}, %{password: "spiderman", password_confirmation: "spiderman"})
...> changeset = validate_secure_password(changeset, :password)
...> changeset.errors[:password]
{"is too common", [validation: :exclusion]}