pub struct AuthService { /* private fields */ }Expand description
The auth service. Cheap to clone: it holds a database handle, config and the event bus.
Implementations§
Source§impl AuthService
impl AuthService
Sourcepub fn new(db: Db, config: AuthConfig) -> Self
pub fn new(db: Db, config: AuthConfig) -> Self
A service announcing on a bus of its own, which nothing listens on.
AuthService::with_events hands it the application’s.
Sourcepub fn with_events(self, events: Events) -> Self
pub fn with_events(self, events: Events) -> Self
Announces on events: the bus the application’s listeners are on. See
crate::events for what is announced.
Sourcepub fn session_absolute_timeout(&self) -> Duration
pub fn session_absolute_timeout(&self) -> Duration
How long a session stays valid. A caller that persists the session in a cookie matches its lifetime to this, so the two cannot disagree.
Sourcepub async fn authenticate(
&self,
username: &str,
password: &str,
ctx: &RequestContext,
) -> Result<IssuedSession, AuthError>
pub async fn authenticate( &self, username: &str, password: &str, ctx: &RequestContext, ) -> Result<IssuedSession, AuthError>
Verifies a username and password, and on success issues a session.
Failures are throttled per username and every outcome is logged. The error deliberately does not reveal whether the username exists.
Sourcepub async fn resolve_session(
&self,
token: &str,
) -> Result<ResolvedSession, AuthError>
pub async fn resolve_session( &self, token: &str, ) -> Result<ResolvedSession, AuthError>
Resolves a raw session token to an identity and its stored data blob,
refreshing last-seen. Expired sessions, and sessions whose user was
disabled or removed, resolve to AuthError::SessionInvalid. The blob
is read in the same query as the session, adding no round-trip.
Sourcepub async fn verify_session(
&self,
token: &str,
) -> Result<AuthenticatedUser, AuthError>
pub async fn verify_session( &self, token: &str, ) -> Result<AuthenticatedUser, AuthError>
Resolves a raw session token to an identity. A thin wrapper over
AuthService::resolve_session for callers that need only the identity.
Sourcepub async fn set_session_data(
&self,
token: &str,
data: &str,
) -> Result<(), AuthError>
pub async fn set_session_data( &self, token: &str, data: &str, ) -> Result<(), AuthError>
Overwrites the opaque per-session data blob (the surface’s serialised state, e.g. CSRF token + flash). The surface writes only when its blob changed, so an unchanged request adds no write.
Sourcepub async fn issue_remember(
&self,
user_id: i64,
) -> Result<RememberCredential, AuthError>
pub async fn issue_remember( &self, user_id: i64, ) -> Result<RememberCredential, AuthError>
Issues a “stay signed in” credential for user_id, one row per device.
Sourcepub async fn consume_remember(
&self,
cookie: &str,
ctx: &RequestContext,
) -> Result<RecalledSession, AuthError>
pub async fn consume_remember( &self, cookie: &str, ctx: &RequestContext, ) -> Result<RecalledSession, AuthError>
Trades a presented remember cookie for a fresh session and a replacement credential, rotating the stored row so a cookie is single-use.
A selector that resolves with the wrong verifier means a copy of the cookie is in circulation: one of the two holders used it first and rotated it, and this is the other. Every credential the user holds is dropped, which signs out the thief at the cost of signing out the owner.
Sourcepub async fn revoke_remember(&self, cookie: &str) -> Result<(), AuthError>
pub async fn revoke_remember(&self, cookie: &str) -> Result<(), AuthError>
Drops the credential a cookie names. Unknown or malformed values are a no-op, so a stale cookie on logout is not an error.
Sourcepub async fn list_sessions(
&self,
user_id: i64,
current_token: &str,
) -> Result<Vec<ActiveSession>, AuthError>
pub async fn list_sessions( &self, user_id: i64, current_token: &str, ) -> Result<Vec<ActiveSession>, AuthError>
Lists the account’s live sessions, newest activity first, marking the one
current_token belongs to.
Sourcepub async fn revoke_session(
&self,
user_id: i64,
id: &str,
) -> Result<bool, AuthError>
pub async fn revoke_session( &self, user_id: i64, id: &str, ) -> Result<bool, AuthError>
Ends one of the account’s sessions by its public id, with a reason so the
device is told. Returns whether a session matched. Scoped to user_id, so
the worst a forged id can do is end one of the caller’s own sessions.
Sourcepub async fn sign_out_everywhere(
&self,
user_id: i64,
keep_token: &str,
) -> Result<u64, AuthError>
pub async fn sign_out_everywhere( &self, user_id: i64, keep_token: &str, ) -> Result<u64, AuthError>
Ends every session but the caller’s, and drops every stay-signed-in credential the account holds. The credentials have to go too: leaving them would let any signed-out device mint itself a new session on its next request, which is the opposite of what this asks for.
Sourcepub async fn create_operator(
&self,
new: NewOperator<'_>,
actor: &Actor,
) -> Result<i64, AuthError>
pub async fn create_operator( &self, new: NewOperator<'_>, actor: &Actor, ) -> Result<i64, AuthError>
Creates an operator who is not a superuser: the panel’s account creation,
by an administrator. The password is checked against the policy, the
creation audited as backend.user.create and credited to actor. Roles
and the temporary-password mark are set by the caller.
Sourcepub async fn reset_operator_password(
&self,
user_id: i64,
actor: &Actor,
) -> Result<String, AuthError>
pub async fn reset_operator_password( &self, user_id: i64, actor: &Actor, ) -> Result<String, AuthError>
Replaces an operator’s password with a generated temporary one, on an
administrator’s behalf: every session and stay-signed-in device ends
with the reason, the change is audited under actor, and the account
must set its own at the next sign-in. Returns the password, to be shown
once. Who may reset whom is the caller’s rule.
Sourcepub async fn is_locked_out(&self, username: &str) -> Result<bool, AuthError>
pub async fn is_locked_out(&self, username: &str) -> Result<bool, AuthError>
Whether failed sign-ins have locked the username out from any address for now.
Sourcepub async fn unlock(&self, username: &str) -> Result<u64, AuthError>
pub async fn unlock(&self, username: &str) -> Result<u64, AuthError>
Clears the failed sign-ins that locked the username out, so it can sign in again now. Returns how many attempts were cleared.
Sourcepub async fn purge_expired(&self) -> Result<Purged, AuthError>
pub async fn purge_expired(&self) -> Result<Purged, AuthError>
Removes every session and stay-signed-in credential past its expiry,
revoked ones included. The admin runs this at boot and hourly;
lat admin purge runs it on demand.
Sourcepub async fn require_password_change(
&self,
user_id: i64,
) -> Result<(), AuthError>
pub async fn require_password_change( &self, user_id: i64, ) -> Result<(), AuthError>
Marks the account as holding a temporary password: one made for it by an
administrator or the command line. Until the operator sets their own
through AuthService::change_own_password, the admin gate sends every
request to the Preferences password form.
Sourcepub async fn must_change_password(
&self,
user_id: i64,
) -> Result<bool, AuthError>
pub async fn must_change_password( &self, user_id: i64, ) -> Result<bool, AuthError>
Whether the account still holds a temporary password.
Sourcepub fn password_policy(&self) -> &PasswordPolicy
pub fn password_policy(&self) -> &PasswordPolicy
The rules a new password must meet, for a form to state them up front.
Sourcepub async fn change_password(
&self,
user_id: i64,
new_password: &str,
keep_token: Option<&str>,
actor: &Actor,
) -> Result<(), AuthError>
pub async fn change_password( &self, user_id: i64, new_password: &str, keep_token: Option<&str>, actor: &Actor, ) -> Result<(), AuthError>
Sets a new password and signs the account out everywhere else.
A password is changed because it was forgotten, shared or stolen. In the
last two cases whoever else holds it is already signed in, so every other
session is ended and every stay-signed-in credential dropped; leaving
either would make the change decorative. keep_token is the session the
change was made from, which survives so nobody is thrown out mid-edit.
The sessions ended record why, so their holders are told.
The change is written to the audit log under backend.user.password_change,
attributed to actor: the operator who made it, or the process for a
system change. The password itself is never recorded.
Refuses a password the PasswordPolicy rejects.
Sourcepub async fn change_own_password(
&self,
user_id: i64,
current_password: &str,
new_password: &str,
keep_token: &str,
ctx: &RequestContext,
) -> Result<(), AuthError>
pub async fn change_own_password( &self, user_id: i64, current_password: &str, new_password: &str, keep_token: &str, ctx: &RequestContext, ) -> Result<(), AuthError>
AuthService::change_password for the signed-in operator, after
confirming their current password.
A wrong current password is logged as a failed sign-in and counts toward
the same lockout, so a borrowed session cannot guess it freely. The session
keep_token names stays signed in.
Sourcepub async fn recent_access(
&self,
user_id: i64,
limit: u64,
) -> Result<Vec<AccessRecord>, AuthError>
pub async fn recent_access( &self, user_id: i64, limit: u64, ) -> Result<Vec<AccessRecord>, AuthError>
The account’s most recent access-log rows, newest first: sign-ins, failures, lockouts, sign-outs and its own password changes.
Sourcepub async fn password_changed_at(
&self,
user_id: i64,
) -> Result<Option<DateTime<Utc>>, AuthError>
pub async fn password_changed_at( &self, user_id: i64, ) -> Result<Option<DateTime<Utc>>, AuthError>
When the account’s password was last set, None if never recorded.
Sourcepub async fn reset_password(
&self,
username: &str,
new_password: &str,
actor: &Actor,
) -> Result<bool, AuthError>
pub async fn reset_password( &self, username: &str, new_password: &str, actor: &Actor, ) -> Result<bool, AuthError>
AuthService::change_password for an account named by username, with no
session kept: the command-line reset, run from outside every session.
Ok(false) when no such account exists.
Sourcepub async fn remember_holder(
&self,
cookie: &str,
) -> Result<Option<i64>, AuthError>
pub async fn remember_holder( &self, cookie: &str, ) -> Result<Option<i64>, AuthError>
Whose stay-signed-in credential a cookie is, without spending it: None
for one that is not current. The verifier has to match, so a stale copy
names nobody.
Sourcepub async fn remember_end(
&self,
cookie: &str,
) -> Result<Option<RevokeReason>, AuthError>
pub async fn remember_end( &self, cookie: &str, ) -> Result<Option<RevokeReason>, AuthError>
Why a presented stay-signed-in cookie no longer works, when it was ended on purpose.
Only the current holder is told: the verifier has to match, so a stale copy learns nothing. Reading the reason removes the credential, so it is told once.
Sourcepub async fn session_end(
&self,
token: &str,
) -> Result<Option<SessionEnd>, AuthError>
pub async fn session_end( &self, token: &str, ) -> Result<Option<SessionEnd>, AuthError>
Why a presented session no longer works, if it was ever issued.
A deliberately ended session is told once: reading its reason removes it, so a stale tab reloaded later is simply signed out.
Sourcepub async fn set_user_active(
&self,
actor_id: i64,
user_id: i64,
active: bool,
) -> Result<(), AuthError>
pub async fn set_user_active( &self, actor_id: i64, user_id: i64, active: bool, ) -> Result<(), AuthError>
Activates or deactivates a backend user.
Deactivating is the reversible counterpart to deleting an operator, which the panel does not offer: the account keeps its history, its audit trail and its permission overrides, and simply cannot sign in.
Two deactivations are refused, because both end with a panel somebody has
to repair from the command line: your own account, and the last active
superuser. Both return AuthError::Refused with the reason.
A deactivated account’s sessions and stay-signed-in credentials are dropped in the same call. An account that may not sign in must not remain signed in on a machine somewhere, which is the whole point of revoking it.
Sourcepub async fn logout(&self, token: &str) -> Result<(), AuthError>
pub async fn logout(&self, token: &str) -> Result<(), AuthError>
Invalidates a session. Unknown tokens are a no-op.
Sourcepub async fn set_user_timezone(
&self,
user_id: i64,
timezone: Option<&str>,
) -> Result<(), AuthError>
pub async fn set_user_timezone( &self, user_id: i64, timezone: Option<&str>, ) -> Result<(), AuthError>
Persists an operator’s own display timezone. Some(name) sets an IANA
timezone; None clears it so the operator falls back to the deployment
default. Validating that name is a real timezone is the caller’s job.
Sourcepub async fn set_user_locale(
&self,
user_id: i64,
locale: Option<&str>,
) -> Result<(), AuthError>
pub async fn set_user_locale( &self, user_id: i64, locale: Option<&str>, ) -> Result<(), AuthError>
Persists an operator’s own UI locale. Some(tag) sets a base language tag;
None clears it so the operator falls back to the deployment default.
Validating that tag is a supported locale is the caller’s job.
Sourcepub async fn user_permission_overrides(
&self,
user_id: i64,
) -> Result<HashMap<String, i64>, AuthError>
pub async fn user_permission_overrides( &self, user_id: i64, ) -> Result<HashMap<String, i64>, AuthError>
Loads a user’s per-permission overrides (code to 1 allow or -1 deny).
Sourcepub async fn set_user_permissions(
&self,
user_id: i64,
overrides: &HashMap<String, i64>,
) -> Result<(), AuthError>
pub async fn set_user_permissions( &self, user_id: i64, overrides: &HashMap<String, i64>, ) -> Result<(), AuthError>
Replaces a user’s per-permission overrides. Callers pass only 1 and -1
entries; an inherited permission is represented by its absence.
Sourcepub async fn record_audit(&self, entry: AuditEntry<'_>) -> Result<(), AuthError>
pub async fn record_audit(&self, entry: AuditEntry<'_>) -> Result<(), AuthError>
Appends an entry to the append-only audit log. Mutating admin paths call this after a successful change, so actions that affect privileges or data are recorded. Self-service preference changes are not audited.
Sourcepub async fn recent_audit(
&self,
limit: u64,
) -> Result<Vec<AuditRecord>, AuthError>
pub async fn recent_audit( &self, limit: u64, ) -> Result<Vec<AuditRecord>, AuthError>
The most recent audit entries, newest first, for the admin audit view.
Sourcepub async fn has_any_operator(&self) -> Result<bool, AuthError>
pub async fn has_any_operator(&self) -> Result<bool, AuthError>
Whether any backend operator exists yet. A fresh install with none is routed to first-run setup instead of login.
Sourcepub async fn create_superuser(
&self,
new: NewOperator<'_>,
) -> Result<i64, AuthError>
pub async fn create_superuser( &self, new: NewOperator<'_>, ) -> Result<i64, AuthError>
Creates a superuser operator: hashes the password, inserts the user, and records their timezone preference. The single account-creation path, shared by the CLI and the first-run setup screen.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for AuthService
impl !UnwindSafe for AuthService
impl Freeze for AuthService
impl Send for AuthService
impl Sync for AuthService
impl Unpin for AuthService
impl UnsafeUnpin for AuthService
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more