use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum SignUpFault {
AuthDisabled,
ReservedField(String),
FileField(String),
RelationshipField(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ProfileFault {
AuthDisabled,
ReservedField(String),
FileField(String),
RelationshipField(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ResetFault {
AuthDisabled,
}
impl fmt::Display for ResetFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AuthDisabled => f.write_str(
"a password reset needs auth: `Auth::disabled()` serves no sign-in to reset",
),
}
}
}
impl fmt::Display for ProfileFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AuthDisabled => {
f.write_str("a profile page needs auth: `Auth::disabled()` signs nobody in to edit")
}
Self::ReservedField(field) => write!(
f,
"the profile form declares a field named '{field}', which its POST carries \
itself: rename the field"
),
Self::FileField(field) => write!(
f,
"the profile form declares a file field '{field}', which its POST does not \
upload: edit the file on a resource's form"
),
Self::RelationshipField(field) => write!(
f,
"the profile form declares a relationship choice '{field}', whose options no \
route serves the profile page: offer static options"
),
}
}
}
impl fmt::Display for SignUpFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AuthDisabled => f.write_str(
"registration needs auth: `Auth::disabled()` serves no sign-in for a new \
account to land on",
),
Self::ReservedField(field) => write!(
f,
"the sign-up form declares a field named '{field}', which its POST carries \
itself: rename the field"
),
Self::FileField(field) => write!(
f,
"the sign-up form declares a file field '{field}', which its POST does not \
upload: ask for the file once the account signs in"
),
Self::RelationshipField(field) => write!(
f,
"the sign-up form declares a relationship choice '{field}', which would list \
records to a visitor nobody signed in: offer static options"
),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum AuthMailFault {
Unset {
feature: &'static str,
},
BaseUrl(String),
MissingMail,
}
impl fmt::Display for AuthMailFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Unset { feature } => write!(
f,
"`Auth::{feature}` sends mail, but the auth sets no sender: install one with \
`Auth::mail(AuthMail::new(..))`"
),
Self::BaseUrl(url) => write!(
f,
"the auth mail's base URL '{url}' is not an absolute http or https URL: pass the \
scheme and host the app answers on, such as `https://admin.example.com`"
),
Self::MissingMail => f.write_str(
"the panel's auth mails links, but the router registers no `Mailer`: add \
one with `.with(Mailer::new(..))` before mounting the panel",
),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum VerificationFault {
AuthDisabled,
}
impl fmt::Display for VerificationFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AuthDisabled => f.write_str(
"email verification needs auth: `Auth::disabled()` signs nobody in to verify",
),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum TenantRegistrationFault {
AuthDisabled,
ReservedField(String),
FileField(String),
RelationshipField(String),
}
impl fmt::Display for TenantRegistrationFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AuthDisabled => f.write_str(
"tenant registration needs auth: `Auth::disabled()` signs nobody in to register \
a tenant",
),
Self::ReservedField(field) => write!(
f,
"the tenant registration form declares a field named '{field}', which its POST \
carries itself: rename the field"
),
Self::FileField(field) => write!(
f,
"the tenant registration form declares a file field '{field}', which its POST \
does not upload: ask for the file on a resource's form"
),
Self::RelationshipField(field) => write!(
f,
"the tenant registration form declares a relationship choice '{field}', whose \
options no route serves the registration page: offer static options"
),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum TenantProfileFault {
AuthDisabled,
ReservedField(String),
FileField(String),
RelationshipField(String),
}
impl fmt::Display for TenantProfileFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AuthDisabled => f.write_str(
"a tenant settings page needs auth: `Auth::disabled()` signs nobody in to edit a \
tenant",
),
Self::ReservedField(field) => write!(
f,
"the tenant settings form declares a field named '{field}', which its POST \
carries itself: rename the field"
),
Self::FileField(field) => write!(
f,
"the tenant settings form declares a file field '{field}', which its POST does \
not upload: edit the file on a resource's form"
),
Self::RelationshipField(field) => write!(
f,
"the tenant settings form declares a relationship choice '{field}', whose \
options no route serves the settings page: offer static options"
),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum TwoFactorFault {
AuthDisabled,
MissingKey,
}
impl fmt::Display for TwoFactorFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AuthDisabled => f.write_str(
"two-factor sign-in needs auth: `Auth::disabled()` signs nobody in to ask a \
second factor of",
),
Self::MissingKey => f.write_str(
"two-factor sign-in seals each authenticator secret under the router's cookie \
key, and the router has none: register a `topcoat::cookie::Key` with `.with(..)`",
),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum OidcFault {
AuthDisabled,
ExternalAuth,
MissingKey,
BaseUrl(String),
NoProvider,
ProviderKey(String),
DuplicateProvider(String),
Issuer(String),
ReservedParam(String, String),
}
impl fmt::Display for OidcFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AuthDisabled => f.write_str(
"provider sign-in needs auth: `Auth::disabled()` signs nobody in to link an \
identity to",
),
Self::ExternalAuth => f.write_str(
"provider sign-in cannot sit beside `Auth::external`: the app signs every user in \
itself, so sign in through the provider there",
),
Self::MissingKey => f.write_str(
"provider sign-in seals each pending sign-in under the router's cookie key, and \
the router has none: register a `topcoat::cookie::Key` with `.with(..)`",
),
Self::BaseUrl(url) => write!(
f,
"provider sign-in's base URL '{url}' is not an absolute `https` origin: pass the \
app's public origin, such as `https://app.example.com`"
),
Self::NoProvider => {
f.write_str("provider sign-in has no provider: add one with `Oidc::provider`")
}
Self::ProviderKey(key) => write!(
f,
"provider key '{key}' cannot name a route: use lowercase ASCII letters, digits \
and `-`"
),
Self::DuplicateProvider(key) => write!(
f,
"two providers have the key '{key}': give each a distinct key"
),
Self::Issuer(key) => write!(
f,
"provider '{key}' has an issuer that is not an `https` URL, nor an `http` one on \
a loopback host"
),
Self::ReservedParam(key, name) => write!(
f,
"provider '{key}' sets the authorization parameter '{name}', which the panel \
sets itself: drop it"
),
}
}
}