pub struct PasswordAuth;Expand description
Shipped default authenticator: Argon2id verification against AdminUser.
An unknown email costs the same work as a wrong password, and every failure shows the same
message. It stores an email trimmed and lowercased and looks it up the same way, so
Ada@Example.com and ada@example.com are one account; a resource that edits an admin’s
email stores it the same way. A row stored with capitals cannot sign in or reset its password:
list the accounts that differ only in case with SELECT LOWER(TRIM(email)) FROM admin_users GROUP BY 1 HAVING COUNT(*) > 1, merge or delete them, then run
UPDATE admin_users SET email = LOWER(TRIM(email)). SQLite’s LOWER folds ASCII letters
only, so lowercase any other capital by hand.
Trait Implementations§
Source§impl Authenticator for PasswordAuth
impl Authenticator for PasswordAuth
Source§async fn find_by_id(&self, cx: &Cx, id: &str) -> Result<Option<AdminUser>>
async fn find_by_id(&self, cx: &Cx, id: &str) -> Result<Option<AdminUser>>
PanelUser::user_id, with everything the request
reads from it — its tenants included. Read moreSource§fn confirm_password(
&self,
cx: &Cx,
user: &Self::User,
password: &str,
) -> impl Future<Output = Result<bool>> + Send
fn confirm_password( &self, cx: &Cx, user: &Self::User, password: &str, ) -> impl Future<Output = Result<bool>> + Send
password is user’s current password: what a page asks before a change a stolen
session must not make, such as turning two-factor sign-in on. Read moreSource§fn store_locale(
&self,
cx: &Cx,
user: &Self::User,
locale: &Locale,
) -> impl Future<Output = Result<()>> + Send
fn store_locale( &self, cx: &Cx, user: &Self::User, locale: &Locale, ) -> impl Future<Output = Result<()>> + Send
locale as user’s after they pick it from the shell’s language menu, so their
locale reads it on the next request, in another browser, and in the
mail a job sends them. It runs only when the pick differs from that locale, and never
while someone impersonates the user. Read moreSource§impl Clone for PasswordAuth
impl Clone for PasswordAuth
impl Copy for PasswordAuth
Source§impl Debug for PasswordAuth
impl Debug for PasswordAuth
Source§impl Default for PasswordAuth
impl Default for PasswordAuth
Source§impl EmailVerifier for PasswordAuth
Verifies an AdminUser’s address, storing the one the link proved. Install it with
Auth::email_verification.
impl EmailVerifier for PasswordAuth
Verifies an AdminUser’s address, storing the one the link proved. Install it with
Auth::email_verification.
Source§type User = AdminUser
type User = AdminUser
Authenticator
loads, which mounting checks.Source§fn is_verified(&self, admin: &AdminUser) -> bool
fn is_verified(&self, admin: &AdminUser) -> bool
user proved it reads the address PanelUser::email answers. A user who has
not reaches only the page that asks for the proof.Source§async fn store_verified_email(
&self,
_cx: &Cx,
user_id: &str,
email: &str,
ex: &mut dyn Executor,
) -> Result<()>
async fn store_verified_email( &self, _cx: &Cx, user_id: &str, email: &str, ex: &mut dyn Executor, ) -> Result<()>
ex, which commits when it returns Ok, that the account
PanelUser::user_id user_id names proved it reads email: store email as the
address it signs in with, which an email change makes new, and mark it verified. An id
that names no account is an error, not a success: the link is spent either way. It may run
again for one link when the database aborts the transaction for a concurrent one, so it
writes only through ex.Source§impl PasswordResetter for PasswordAuth
Resets an AdminUser’s password, mailing the link to the email the account stores.
Install it with Auth::password_reset.
impl PasswordResetter for PasswordAuth
Resets an AdminUser’s password, mailing the link to the email the account stores.
Install it with Auth::password_reset.
Source§type User = AdminUser
type User = AdminUser
Authenticator
loads, which mounting checks.Source§async fn find_by_email(&self, cx: &Cx, email: &str) -> Result<Option<AdminUser>>
async fn find_by_email(&self, cx: &Cx, email: &str) -> Result<Option<AdminUser>>
email signs in as, or None. The address arrives trimmed, as the visitor
typed it.Source§async fn reset_password(
&self,
_cx: &Cx,
user_id: &str,
password: &str,
ex: &mut dyn Executor,
) -> Result<()>
async fn reset_password( &self, _cx: &Cx, user_id: &str, password: &str, ex: &mut dyn Executor, ) -> Result<()>
PanelUser::user_id user_id names to password,
through the reset’s transaction ex, which commits when it returns Ok. The panel’s
authenticator still loads the account and it may enter the panel; the password is at
least MIN_PASSWORD_CHARS long and was typed twice. It may
run again for one reset when the database aborts the transaction for a concurrent one, so
it writes only through ex.Source§impl ProfileEditor for PasswordAuth
Edits the signed-in AdminUser’s name, email and password through a Profile. Changing
the email or the password asks for the current password, and refuses a new password
new_password_errors refuses and, once the current password
verifies, an email another account holds. A changed password is a
ProfileUpdate::Credentials. A new email goes through request_email_change: on a panel
with Auth::email_verification it waits for its link,
elsewhere it is stored at once, as a credential change. Install it with
Auth::profile.
impl ProfileEditor for PasswordAuth
Edits the signed-in AdminUser’s name, email and password through a Profile. Changing
the email or the password asks for the current password, and refuses a new password
new_password_errors refuses and, once the current password
verifies, an email another account holds. A changed password is a
ProfileUpdate::Credentials. A new email goes through request_email_change: on a panel
with Auth::email_verification it waits for its link,
elsewhere it is stored at once, as a credential change. Install it with
Auth::profile.
Source§type Input = Profile
type Input = Profile
Profile, or the app’s own
#[derive(FormInput)] struct.Source§type User = AdminUser
type User = AdminUser
Authenticator
loads, which mounting checks.Source§fn fill(&self, _cx: &Cx, admin: &AdminUser) -> Profile
fn fill(&self, _cx: &Cx, admin: &AdminUser) -> Profile
user. The page renders what
FormInput::write writes, so an input that never writes its passwords shows them
empty.