howdy/auth/field
Small facts an application keeps about a user or a group: a username, a plan, a billing id. Declare a field once and use it to write and to read:
pub fn username() { field.text("username") |> field.unique }
users.update(identity, id, [field.set(username(), "mike")], by: actor)
use data <- result.try(users.fields(identity, id))
field.get(data, username())
Write them with howdy/auth/users and howdy/auth/groups. A value is at
most 1024 bytes once encoded. Anything relational, or that you query by
range, belongs in application tables keyed by the id.
Types
A write, for users.update, groups.update and the _with constructors.
pub opaque type Change
Values
pub fn check(
field: Field(a),
with check: fn(a) -> Result(Nil, String),
) -> Field(a)
Refuse values with rejects; its message reaches the caller as Invalid.
pub fn custom(
name: String,
encode encode: fn(a) -> String,
decode decode: fn(String) -> Result(a, Nil),
) -> Field(a)
A field of your own type. Uniqueness and find compare the encoded text,
so equal values must encode the same.
pub fn get(from: Fields, field: Field(a)) -> Result(a, Nil)
The value held, or an error when the field is unset or what is stored no longer decodes.
pub fn text(name: String) -> Field(String)
A field under name: 1 to 64 lowercase letters, digits and underscores.
User fields and group fields are named separately.
pub fn time(name: String) -> Field(timestamp.Timestamp)
An instant, kept as RFC 3339 text in UTC.
pub fn to_list(fields: Fields) -> List(#(String, String))
Every field held as encoded text, by name: for an export or a debug page.
pub fn unique(field: Field(a)) -> Field(a)
At most one holder of each value across the installation, enforced by the database. Declare it before the field is first written: values stored while it was not unique are not checked against.