Skip to main content

Db

Struct Db 

Source
pub struct Db { /* private fields */ }
Expand description

Handle to the allowthem database.

Wraps a SqlitePool and guarantees that migrations have been applied. All query code receives a &Db and calls db.pool() to access the pool.

Implementations§

Source§

impl Db

Source

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

Validate an RS256-signed access token JWT.

Steps:

  1. Decode the JWT header to extract kid.
  2. Look up the signing key by kid in the database.
  3. Verify the RS256 signature using the public key PEM.
  4. Check exp against the current time.
  5. Verify iss matches expected_issuer.
  6. Parse sub as UserId and return AccessTokenClaims.
Source§

impl Db

Source

pub async fn create_api_token( &self, user_id: UserId, name: &str, expires_at: Option<DateTime<Utc>>, metadata: Option<&str>, ) -> Result<(String, ApiTokenInfo), AuthError>

Generate and store a new API token for the user.

Returns the raw token string (shown once, never stored) and ApiTokenInfo metadata. The caller must present the raw token to the user — it cannot be retrieved again.

Source

pub async fn validate_api_token( &self, raw_token: &str, ) -> Result<Option<(UserId, ApiTokenInfo)>, AuthError>

Validate a raw bearer token.

Hashes the token and queries by hash. Tokens with a past expires_at are excluded. Returns Some((UserId, ApiTokenInfo)) if valid, None otherwise.

Source

pub async fn list_api_tokens( &self, user_id: UserId, ) -> Result<Vec<ApiTokenInfo>, AuthError>

List all API tokens for a user (metadata only, no hashes).

Source

pub async fn delete_api_token(&self, id: ApiTokenId) -> Result<bool, AuthError>

Delete a single API token by ID.

Returns true if a token was found and deleted.

Source

pub async fn delete_user_api_tokens( &self, user_id: UserId, ) -> Result<u64, AuthError>

Delete all API tokens for a user.

Returns the number of tokens deleted.

Source§

impl Db

Source

pub async fn create_application( &self, name: String, redirect_uris: Vec<String>, is_trusted: bool, created_by: Option<UserId>, logo_url: Option<String>, primary_color: Option<String>, ) -> Result<(Application, ClientSecret), AuthError>

Register a new OIDC application.

Generates a client_id and client_secret, hashes the secret, and inserts the row. Returns the persisted Application and the raw ClientSecret. The raw secret is shown once and is not recoverable — the caller must present it to the admin immediately.

Validates redirect_uris before inserting. Returns AuthError::InvalidRedirectUri if any URI fails validation.

Source

pub async fn get_application( &self, id: ApplicationId, ) -> Result<Application, AuthError>

Get an application by internal ID.

Source

pub async fn get_application_by_client_id( &self, client_id: &ClientId, ) -> Result<Application, AuthError>

Get an application by its public client_id.

Used by OAuth endpoints that receive client_id in request parameters.

Source

pub async fn get_branding_by_client_id( &self, client_id: &ClientId, ) -> Result<Option<BrandingConfig>, AuthError>

Get branding configuration for an application by client_id.

Returns None if no application with the given client_id exists or if the application is inactive. Branded pages fall back to default allowthem styling when this returns None.

Source

pub async fn list_applications(&self) -> Result<Vec<Application>, AuthError>

List all applications ordered by created_at ASC.

Source

pub async fn update_application( &self, id: ApplicationId, params: UpdateApplication, ) -> Result<(), AuthError>

Update an application’s mutable fields.

Validates redirect_uris, serializes them to JSON, and writes all six mutable fields atomically. Caller is responsible for fetching the current application and populating unchanged fields.

Returns AuthError::NotFound if no application with id exists. Returns AuthError::InvalidRedirectUri if any URI fails validation.

Source

pub async fn regenerate_client_secret( &self, id: ApplicationId, ) -> Result<(Application, ClientSecret), AuthError>

Generate a new client secret, invalidating the previous one.

Returns the updated Application and the raw ClientSecret. The new secret is the only opportunity to retrieve it — the old secret is irrecoverably invalidated on success.

Returns AuthError::NotFound if no application with id exists.

Source

pub async fn delete_application( &self, id: ApplicationId, ) -> Result<(), AuthError>

Permanently delete an application and all associated grants.

Cascade deletes: authorization_codes, refresh_tokens, consents. Returns AuthError::NotFound if no application with id exists.

Source§

impl Db

Source

pub async fn log_audit( &self, event_type: AuditEvent, user_id: Option<&UserId>, target_id: Option<&str>, ip_address: Option<&str>, user_agent: Option<&str>, detail: Option<&str>, ) -> Result<(), AuthError>

Record an audit event.

user_id may be None for events where no authenticated user is involved (e.g. a failed login attempt against an unknown email).

Source

pub async fn get_audit_log( &self, user_id: Option<&UserId>, limit: u32, offset: u32, ) -> Result<Vec<AuditEntry>, AuthError>

Retrieve audit log entries, optionally filtered by user.

Results are ordered by created_at descending (newest first).

Source

pub async fn get_audit_log_by_event( &self, event_type: AuditEvent, limit: u32, offset: u32, ) -> Result<Vec<AuditEntry>, AuthError>

Retrieve audit log entries filtered by event type.

Results are ordered by created_at descending (newest first).

Source

pub async fn last_login_at( &self, user_id: UserId, ) -> Result<Option<DateTime<Utc>>, AuthError>

Get the most recent login timestamp for a user, if any.

Returns None if the user has never logged in (no audit entry with event_type = ‘login’ for this user_id).

Source

pub async fn search_audit_log( &self, params: SearchAuditParams<'_>, ) -> Result<SearchAuditResult, AuthError>

Search and filter audit log entries with pagination.

Builds a dynamic query with optional filters for user, event type, outcome, and date range. LEFT JOINs allowthem_users for email resolution. Follows the same dynamic-SQL pattern as search_users.

Source§

impl Db

Check whether the user has an existing consent that covers all requested scopes.

Record or update user consent for an application.

Stored scopes become the union of existing and new scopes (consent is additive).

Get the consent record for a user and application, if any.

Source

pub async fn create_authorization_code( &self, application_id: ApplicationId, user_id: UserId, code_hash: &TokenHash, redirect_uri: &str, scopes: &[String], code_challenge: &str, code_challenge_method: &str, nonce: Option<&str>, ) -> Result<AuthorizationCode, AuthError>

Create an authorization code record. Expires after 10 minutes.

Source

pub async fn get_authorization_code_by_hash( &self, code_hash: &TokenHash, ) -> Result<Option<AuthorizationCode>, AuthError>

Look up an authorization code by its hash.

Source

pub async fn mark_authorization_code_used( &self, id: AuthorizationCodeId, ) -> Result<(), AuthError>

Mark an authorization code as used.

Source§

impl Db

Source

pub async fn new(pool: SqlitePool) -> Result<Self, AuthError>

Create a Db from an integrator-provided pool and run migrations.

This is the embedded-mode constructor. The caller is responsible for configuring PRAGMA foreign_keys = ON on their pool’s SqliteConnectOptions — this constructor cannot set per-connection pragmas on a pool it did not create.

Migrations are idempotent: safe to call on a pool that has already been migrated. SQLx tracks applied migrations in _sqlx_migrations and CREATE TABLE IF NOT EXISTS in the SQL is a no-op on existing tables.

ignore_missing is set so that migrations from the integrating application already recorded in _sqlx_migrations do not cause an error — those are the integrator’s own migrations, not allowthem’s.

Source

pub async fn connect(url: &str) -> Result<Self, AuthError>

Create a pool from a URL, apply pragmas, run migrations, and return a Db.

Configures the pool with:

  • PRAGMA foreign_keys = ON — FK constraint enforcement
  • PRAGMA journal_mode = WAL — concurrent reads (silently ignored for :memory:)
  • PRAGMA busy_timeout = 5000 — wait under contention instead of immediate SQLITE_BUSY
Source

pub fn pool(&self) -> &SqlitePool

Return a reference to the underlying connection pool.

Source§

impl Db

Source

pub async fn create_email_verification( &self, user_id: UserId, ) -> Result<String, AuthError>

Source

pub async fn verify_email(&self, raw_token: &str) -> Result<bool, AuthError>

Source

pub async fn send_verification_email( &self, user_id: UserId, email: &Email, base_url: &str, sender: &dyn EmailSender, ) -> Result<(), AuthError>

Source§

impl Db

Source

pub async fn create_invitation( &self, email: Option<&Email>, metadata: Option<&str>, invited_by: Option<UserId>, expires_at: DateTime<Utc>, ) -> Result<(String, Invitation), AuthError>

Create an invitation. Returns the raw token (shown once) and the Invitation record.

If email is Some, the invitation is targeted at that address. If email is None, it is an open invitation usable by anyone.

Source

pub async fn consume_invitation( &self, id: InvitationId, ) -> Result<(), AuthError>

Mark an invitation as consumed.

Uses consumed_at IS NULL as a concurrency guard. Returns Ok(()) on success. Returns Err(AuthError::NotFound) if the ID does not exist. Returns Err(AuthError::Gone) if already consumed — the caller should treat this as a race loss.

Source

pub async fn list_pending_invitations( &self, ) -> Result<Vec<Invitation>, AuthError>

List unconsumed, non-expired invitations, newest first.

Source

pub async fn delete_invitation(&self, id: InvitationId) -> Result<(), AuthError>

Delete an invitation outright, whether pending or consumed.

Source

pub async fn validate_invitation( &self, raw_token: &str, ) -> Result<Option<Invitation>, AuthError>

Validate a raw invitation token.

Returns Some(Invitation) if the token exists, is not expired, and has not been consumed. Returns None otherwise. The caller is responsible for checking email match on targeted invitations.

Source§

impl Db

Source

pub async fn create_oauth_state( &self, provider: &str, redirect_uri: &str, pkce_verifier: &str, post_login_redirect: Option<&str>, linking_user_id: Option<UserId>, ) -> Result<String, AuthError>

Create an OAuth state record. Returns the raw state value (for the authorize URL).

linking_user_id is Some when initiating the account-linking flow (the user is already authenticated and wants to add a provider). It is None for the standard login/register flow.

Source

pub async fn validate_oauth_state( &self, raw_state: &str, ) -> Result<Option<OAuthStateInfo>, AuthError>

Validate and consume an OAuth state. Returns the stored info or None if invalid/expired. Atomically deletes to prevent reuse.

Source

pub async fn create_oauth_user( &self, email: Email, provider: &str, provider_user_id: &str, ) -> Result<User, AuthError>

Create a user via OAuth – no password.

Creates the user (password_hash = NULL) and the oauth_accounts row in a single transaction. Returns the created User.

Link an OAuth identity to an existing user.

Source

pub async fn find_user_by_oauth( &self, provider: &str, provider_user_id: &str, ) -> Result<Option<User>, AuthError>

Find an allowthem user by provider + provider_user_id.

Source

pub async fn get_user_oauth_accounts( &self, user_id: UserId, ) -> Result<Vec<OAuthAccountInfo>, AuthError>

List all OAuth accounts linked to a user.

Remove an OAuth account link for a user + provider.

Returns true if a row was deleted, false if no link existed.

Source§

impl Db

Source

pub async fn create_password_reset( &self, email: &Email, ) -> Result<Option<String>, AuthError>

Create a password reset token for the user with the given email.

Looks up the user by email. If found, inserts a new reset token record (hashed) and returns the raw token for inclusion in the reset URL. Returns None if no user exists for that email (caller should not reveal this to prevent email enumeration).

Source

pub async fn validate_reset_token( &self, raw_token: &str, ) -> Result<Option<(ResetTokenId, UserId)>, AuthError>

Validate a raw reset token.

Hashes the token and looks it up in the database. Returns the associated UserId and token record ID if the token exists, has not expired, and has not been used. Returns None if the token is invalid or expired.

Source

pub async fn execute_reset( &self, raw_token: &str, new_password: &str, ) -> Result<bool, AuthError>

Execute a password reset: update the password and mark the token used.

Runs atomically in a transaction:

  1. Validate the token (not expired, not used).
  2. Mark the token as used (used_at = now).
  3. Hash the new password.
  4. Update the user’s password_hash and updated_at.

Returns Ok(true) on success, Ok(false) if the token was invalid.

Source

pub async fn send_password_reset( &self, email: &Email, base_url: &str, sender: &dyn EmailSender, ) -> Result<(), AuthError>

Send a password reset email for the given address.

Calls create_password_reset to generate a token. If the email exists, constructs a reset URL using base_url and delivers it via sender. If the email does not exist, returns Ok(()) silently (no enumeration).

Source§

impl Db

Source

pub async fn create_permission( &self, name: &PermissionName, description: Option<&str>, ) -> Result<Permission, AuthError>

Create a permission with a unique name and optional description.

Source

pub async fn get_permission( &self, id: &PermissionId, ) -> Result<Option<Permission>, AuthError>

Get a permission by ID. Returns None if not found.

Source

pub async fn get_permission_by_name( &self, name: &PermissionName, ) -> Result<Option<Permission>, AuthError>

Get a permission by name. Returns None if not found.

Source

pub async fn list_permissions(&self) -> Result<Vec<Permission>, AuthError>

List all permissions, ordered by creation time.

Source

pub async fn delete_permission( &self, id: &PermissionId, ) -> Result<bool, AuthError>

Delete a permission by ID. Returns true if a row was deleted, false if not found.

Cascades to allowthem_role_permissions and allowthem_user_permissions.

Source

pub async fn assign_permission_to_role( &self, role_id: &RoleId, permission_id: &PermissionId, ) -> Result<(), AuthError>

Assign a permission to a role. Idempotent — silently succeeds if already assigned.

Source

pub async fn assign_permission_to_user( &self, user_id: &UserId, permission_id: &PermissionId, ) -> Result<(), AuthError>

Assign a permission directly to a user. Idempotent — silently succeeds if already assigned.

Source

pub async fn unassign_permission_from_role( &self, role_id: &RoleId, permission_id: &PermissionId, ) -> Result<bool, AuthError>

Unassign a permission from a role. Returns true if removed, false if not found.

Source

pub async fn unassign_permission_from_user( &self, user_id: &UserId, permission_id: &PermissionId, ) -> Result<bool, AuthError>

Unassign a permission from a user. Returns true if removed, false if not found.

Source

pub async fn has_permission( &self, user_id: &UserId, perm_name: &PermissionName, ) -> Result<bool, AuthError>

Check whether a user has a permission by name via either path: direct user assignment or any of the user’s roles.

Source

pub async fn get_user_permissions( &self, user_id: &UserId, ) -> Result<Vec<Permission>, AuthError>

Return all permissions for a user — both directly assigned and via roles — deduplicated and ordered by name.

Source§

impl Db

Source

pub async fn create_role( &self, name: &RoleName, description: Option<&str>, ) -> Result<Role, AuthError>

Create a role with a unique name and optional description.

Source

pub async fn get_role(&self, id: &RoleId) -> Result<Option<Role>, AuthError>

Get a role by ID. Returns None if not found.

Source

pub async fn get_role_by_name( &self, name: &RoleName, ) -> Result<Option<Role>, AuthError>

Get a role by name. Returns None if not found.

Source

pub async fn list_roles(&self) -> Result<Vec<Role>, AuthError>

List all roles, ordered by creation time.

Source

pub async fn delete_role(&self, id: &RoleId) -> Result<bool, AuthError>

Delete a role by ID. Returns true if a row was deleted, false if not found.

Cascades to allowthem_user_roles and allowthem_role_permissions.

Source

pub async fn assign_role( &self, user_id: &UserId, role_id: &RoleId, ) -> Result<(), AuthError>

Assign a role to a user. Silently succeeds if already assigned (idempotent).

Source

pub async fn unassign_role( &self, user_id: &UserId, role_id: &RoleId, ) -> Result<bool, AuthError>

Unassign a role from a user. Returns true if removed, false if the assignment did not exist.

Source

pub async fn has_role( &self, user_id: &UserId, role_name: &RoleName, ) -> Result<bool, AuthError>

Check whether a user has a specific role by name.

Source

pub async fn get_user_roles( &self, user_id: &UserId, ) -> Result<Vec<Role>, AuthError>

Return all roles assigned to a user, ordered by creation time.

Source

pub async fn bootstrap_roles( &self, names: &[&str], ) -> Result<Vec<Role>, AuthError>

Create each named role if it does not already exist.

Returns roles in the same order as names. Idempotent: existing roles are fetched, not re-created. Duplicates within names are allowed; each name is resolved independently.

Source

pub async fn resolve_highest_role( &self, user_id: &UserId, hierarchy: &[&str], ) -> Result<Option<String>, AuthError>

Return the name of the first role in hierarchy that the user holds.

hierarchy[0] is treated as the highest role. Returns None if the user holds none of the listed roles. An empty hierarchy always returns None.

Source§

impl Db

Source

pub async fn create_session( &self, user_id: UserId, token_hash: TokenHash, ip_address: Option<&str>, user_agent: Option<&str>, expires_at: DateTime<Utc>, ) -> Result<Session, AuthError>

Insert a new session record and return it.

The caller is responsible for hashing the token before calling this function via hash_token(). The raw token must never be passed here.

Source

pub async fn lookup_session( &self, token: &SessionToken, ) -> Result<Option<Session>, AuthError>

Look up a session by raw token.

Hashes the token internally and queries by hash. Expired sessions (where expires_at is in the past) are excluded. Returns None when no matching active session is found.

Source

pub async fn validate_session( &self, token: &SessionToken, ttl: Duration, ) -> Result<Option<Session>, AuthError>

Validate a session token and optionally extend it.

Fetches the active session by token hash. If the session is past the halfway point of its TTL (now > expires_at - ttl/2), it is renewed by setting expires_at = now + ttl. Returns the session with the updated expiry, or None if no active session was found.

Source

pub async fn delete_session( &self, token: &SessionToken, ) -> Result<bool, AuthError>

Delete a single session by raw token.

Returns true if a session was found and deleted, false if no matching session existed.

Source

pub async fn delete_user_sessions( &self, user_id: &UserId, ) -> Result<u64, AuthError>

Delete all sessions for a user.

Returns the number of sessions that were deleted.

Source

pub async fn list_user_sessions( &self, user_id: UserId, ) -> Result<Vec<Session>, AuthError>

List all active (non-expired) sessions for a user.

Returns sessions ordered by created_at descending (newest first).

Source

pub async fn list_all_sessions( &self, params: ListSessionsParams, ) -> Result<ListSessionsResult, AuthError>

List all active sessions with user email, for admin session viewer.

Joins sessions with users. Filters to non-expired sessions only. Optional user_id filter. Two static query variants (no dynamic SQL).

Source

pub async fn delete_session_by_id( &self, id: SessionId, ) -> Result<bool, AuthError>

Delete a single session by primary key.

Used by the admin session viewer to revoke individual sessions. Returns true if a session was found and deleted, false if not.

Source§

impl Db

Source

pub async fn create_signing_key( &self, encryption_key: &[u8; 32], ) -> Result<SigningKey, AuthError>

Generate an RS256 key pair, encrypt the private key, and store both in the database.

The new key is NOT automatically marked active — call activate_signing_key separately.

Source

pub async fn activate_signing_key( &self, key_id: SigningKeyId, ) -> Result<(), AuthError>

Mark a key as the active signing key. Deactivates all other keys in a single transaction.

Returns AuthError::NotFound if the key ID does not exist.

Source

pub async fn rotate_signing_key( &self, encryption_key: &[u8; 32], ) -> Result<SigningKey, AuthError>

Generate a new key and activate it, deactivating the current active key.

Combines creation and activation in a single transaction.

Source

pub async fn get_active_signing_key(&self) -> Result<SigningKey, AuthError>

Get the currently active signing key.

Returns AuthError::NotFound if no key is active.

Source

pub async fn get_all_signing_keys(&self) -> Result<Vec<SigningKey>, AuthError>

Get all signing keys ordered by creation date descending.

Used by the JWKS endpoint to serve all public keys (active + rotated-out).

Source

pub async fn get_signing_key( &self, id: SigningKeyId, ) -> Result<SigningKey, AuthError>

Get a specific signing key by ID.

Returns AuthError::NotFound if no key matches the ID.

Source§

impl Db

Source§

impl Db

Source

pub async fn create_refresh_token( &self, application_id: ApplicationId, user_id: UserId, token_hash: &TokenHash, scopes: &[String], authorization_code_id: Option<AuthorizationCodeId>, ) -> Result<RefreshToken, AuthError>

Create a refresh token record. Expires after 30 days.

Source

pub async fn revoke_refresh_tokens_by_auth_code( &self, authorization_code_id: AuthorizationCodeId, ) -> Result<u64, AuthError>

Revoke all refresh tokens issued from a specific authorization code.

Used for code-reuse detection (RFC 6749 Section 10.5).

Source

pub async fn get_refresh_token_by_hash( &self, token_hash: &TokenHash, ) -> Result<Option<RefreshToken>, AuthError>

Look up a refresh token by its SHA-256 hash.

Returns Ok(None) if no token matches. The caller must hash the raw token before calling this method.

Source

pub async fn revoke_refresh_token( &self, id: RefreshTokenId, ) -> Result<(), AuthError>

Revoke a single refresh token by setting revoked_at to now.

Used during token rotation: the old refresh token is revoked before the new one is issued.

Source§

impl Db

Source

pub async fn get_pending_mfa_secret( &self, user_id: UserId, mfa_key: &[u8; 32], ) -> Result<Option<String>, AuthError>

Retrieve a pending (non-enabled) MFA secret for a user.

Returns Some(base32_secret) if a non-enabled secret exists, None otherwise. Used by the setup page to avoid regenerating the secret on every page load.

Source

pub async fn create_mfa_secret( &self, user_id: UserId, mfa_key: &[u8; 32], ) -> Result<String, AuthError>

Generate a new TOTP secret for a user and store it (encrypted, not yet enabled).

Returns the plaintext base32-encoded secret for display to the user during the setup flow. The caller must present this secret (or a QR code derived from it) and require the user to confirm with a valid code before calling enable_mfa.

Fails with MfaAlreadyEnabled if the user already has an enabled MFA secret. If a non-enabled secret exists (abandoned setup attempt), it is replaced.

Source

pub async fn enable_mfa( &self, user_id: UserId, code: &str, mfa_key: &[u8; 32], ) -> Result<Vec<String>, AuthError>

Enable MFA for a user after verifying a TOTP code.

Decrypts the stored secret, validates the provided code against it, and if valid, sets enabled = 1 and inserts 10 hashed recovery codes. Returns the plaintext recovery codes (this is the only time they are visible).

Runs in a transaction to ensure MFA is never enabled without recovery codes.

Source

pub async fn verify_totp( &self, user_id: UserId, code: &str, mfa_key: &[u8; 32], ) -> Result<bool, AuthError>

Validate a TOTP code against a user’s enabled MFA secret.

Returns Ok(true) if the code is valid, Ok(false) if invalid. Returns Err(MfaNotEnabled) if the user has no enabled MFA.

Source

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

Check whether a user has MFA enabled.

Source

pub async fn disable_mfa(&self, user_id: UserId) -> Result<(), AuthError>

Disable MFA for a user. Deletes the secret and all recovery codes.

Uses a transaction to ensure both deletes are atomic.

Source

pub async fn verify_recovery_code( &self, user_id: UserId, code: &str, ) -> Result<bool, AuthError>

Verify a recovery code. If valid, marks it as used (one-time use).

Uses atomic UPDATE ... RETURNING to prevent race conditions. Returns Ok(true) if the code was valid and consumed, Ok(false) if no matching unused code was found.

Source

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

Count remaining unused recovery codes for a user.

Source

pub async fn regenerate_recovery_codes( &self, user_id: UserId, ) -> Result<Vec<String>, AuthError>

Replace all recovery codes with a fresh set of 10.

Deletes all existing codes (used and unused) and inserts 10 new ones. Returns the plaintext codes. Runs in a transaction.

Source

pub async fn create_mfa_challenge( &self, user_id: UserId, ) -> Result<String, AuthError>

Create a short-lived MFA challenge token after password verification.

The integrator calls this when a user with MFA enabled passes password verification. Returns the raw token string to send to the client. The client presents this token along with a TOTP code to complete login. Challenge tokens expire after 5 minutes.

Source

pub async fn validate_mfa_challenge( &self, raw_token: &str, ) -> Result<Option<UserId>, AuthError>

Validate an MFA challenge token without consuming it.

Returns Some(user_id) if the token is valid and not expired, None otherwise. Does not consume the token so the user can retry if they mistype the TOTP code.

Source

pub async fn consume_mfa_challenge( &self, raw_token: &str, ) -> Result<(), AuthError>

Consume an MFA challenge token after successful TOTP verification.

Uses DELETE ... RETURNING for atomicity.

Source§

impl Db

Source

pub async fn create_user( &self, email: Email, password: &str, username: Option<Username>, custom_data: Option<&Value>, ) -> Result<User, AuthError>

Create a user with email, plaintext password, optional username, and optional custom data.

Hashes the password with Argon2id (via password::hash_password). Returns the created User (without password_hash in the returned struct).

Source

pub async fn create_user_with_hash( &self, email: Email, password_hash: &str, username: Option<Username>, custom_data: Option<&Value>, ) -> Result<User, AuthError>

Import a user with a pre-existing password hash (for migration from external systems). The hash must be a valid Argon2 PHC string. No validation is performed on it.

Source

pub async fn get_user(&self, id: UserId) -> Result<User, AuthError>

Look up a user by ID. Returns User with password_hash = None.

Source

pub async fn get_user_by_email(&self, email: &Email) -> Result<User, AuthError>

Look up a user by email. Returns User with password_hash = None.

Source

pub async fn get_user_by_username( &self, username: &Username, ) -> Result<User, AuthError>

Look up a user by username. Returns User with password_hash = None.

Source

pub async fn find_for_login(&self, identifier: &str) -> Result<User, AuthError>

Look up a user by email OR username for login.

Returns User WITH password_hash populated. The caller is responsible for calling verify_password() to check the password.

Source

pub async fn update_user_email( &self, id: UserId, email: Email, ) -> Result<(), AuthError>

Update a user’s email. Also updates updated_at.

Source

pub async fn update_user_username( &self, id: UserId, username: Option<Username>, ) -> Result<(), AuthError>

Update a user’s username (set or clear). Also updates updated_at.

Source

pub async fn update_user_active( &self, id: UserId, is_active: bool, ) -> Result<(), AuthError>

Update a user’s is_active flag. Also updates updated_at.

Source

pub async fn delete_user(&self, id: UserId) -> Result<(), AuthError>

Delete a user by ID. Cascades to sessions, user_roles, user_permissions.

Source

pub async fn list_users(&self) -> Result<Vec<User>, AuthError>

List all users ordered by created_at ASC. Returns User with password_hash = None.

Source

pub async fn search_users( &self, params: SearchUsersParams<'_>, ) -> Result<SearchUsersResult, AuthError>

Search and filter users with pagination.

Builds a dynamic query with optional search term (matched against email and username via LIKE), status filter, and MFA filter. Returns matching users with their MFA enrollment status.

Source

pub async fn update_user_password( &self, id: UserId, new_password: &str, ) -> Result<(), AuthError>

Update a user’s password. Hashes new_password with Argon2id and stores it.

Returns AuthError::NotFound if no user with id exists.

Source

pub async fn clear_password_hash(&self, id: UserId) -> Result<(), AuthError>

Set a user’s password hash to NULL.

Used by admin force-password-reset to invalidate the current password. The login flow falls back to a dummy hash when password_hash is NULL, so verify_password will always fail.

Source

pub async fn get_custom_data( &self, id: &UserId, ) -> Result<Option<Value>, AuthError>

Get a user’s custom data.

Returns Err(NotFound) if no user with id exists. Returns Ok(None) if the user exists but has no custom data.

Source

pub async fn set_custom_data( &self, id: &UserId, data: &Value, ) -> Result<(), AuthError>

Set a user’s custom data. Also updates updated_at.

Returns Err(NotFound) if no user with id exists.

Source

pub async fn delete_custom_data(&self, id: &UserId) -> Result<(), AuthError>

Delete (clear) a user’s custom data by setting it to NULL. Also updates updated_at.

Idempotent – succeeds even if custom data is already NULL.

Auto Trait Implementations§

§

impl Freeze for Db

§

impl !RefUnwindSafe for Db

§

impl Send for Db

§

impl Sync for Db

§

impl Unpin for Db

§

impl UnsafeUnpin for Db

§

impl !UnwindSafe for Db

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<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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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