pub const USER_TOML: &str = r#"
[resource]
name = "user"
scope = "global"
timestamps = true
[permissions]
list = "member" # people you share an organisation with
read = "member"
create = "public" # registration
update = "owner"
delete = "private"
[auth]
identity_field = "email"
password_field = "password_hash"
oauth_providers = []
[fields.email]
type = "string"
required = true
unique = true
max_length = 320
[fields.password_hash]
type = "string"
hidden = true
# When the address was confirmed. Null means unconfirmed — which only *stops*
# anyone when `[auth] require_email_verification` is on, so an app with no
# mailer carries the column and never looks at it.
[fields.email_verified_at]
type = "timestamp"
[fields.email_verified_at.admin]
visible = false
# What to call somebody, and what to show beside their name.
#
# Both are ordinary nullable columns nothing requires — an app that has no use
# for either can leave them empty or drop them by replacing this resource. They are
# here because they are what almost every app wants and what every identity
# provider hands over: a sign-in through [`[oauth]`](crate::config::OAuthConfig)
# fills them in, so an account that arrives that way arrives with a name and a
# picture rather than an email address and a blank.
#
# The picture is a `file` field: a provider fills it with the URL it gave us,
# and somebody changing it in the dashboard uploads one into `[storage]` or
# types a URL of their own. Both are the same string in the same column.
[fields.display_name]
type = "string"
[fields.avatar_url]
type = "file"
max_length = 1024
# True when the address above is one apiplant invented rather than one somebody
# gave it.
#
# A sign-in through a provider that releases no address — X, today — still has
# to put *something* in the identity column, which is required and unique. It
# writes `<provider>_<id>@oauth.invalid`, at a TLD RFC 2606 reserves so that it
# can never resolve.
#
# This flag is here, in every app, because the framework is the one inventing
# that value: fabricating an address and not recording that it was fabricated
# leaves an app to find out by watching mail bounce. With it, "we have an
# address for this person" stops being the same question as "there is a string
# in the email column" — which is the question a welcome email, a newsletter
# and a CSV export all actually mean to ask.
[fields.email_placeholder]
type = "boolean"
default = false
[fields.email_placeholder.admin]
visible = false
"#;Expand description
The default user: global (users are shared across organisations) with
email + password auth. Extend via resources/users.toml.