Skip to main content

AuthService

Struct AuthService 

Source
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

Source

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.

Source

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.

Source

pub fn events(&self) -> &Events

The bus this service announces on.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub async fn must_change_password( &self, user_id: i64, ) -> Result<bool, AuthError>

Whether the account still holds a temporary password.

Source

pub fn password_policy(&self) -> &PasswordPolicy

The rules a new password must meet, for a form to state them up front.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub async fn logout(&self, token: &str) -> Result<(), AuthError>

Invalidates a session. Unknown tokens are a no-op.

Source

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.

Source

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.

Source

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).

Source

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.

Source

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.

Source

pub async fn recent_audit( &self, limit: u64, ) -> Result<Vec<AuditRecord>, AuthError>

The most recent audit entries, newest first, for the admin audit view.

Source

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.

Source

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§

Source§

impl Clone for AuthService

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more