pub trait UserStore: Send + Sync {
// Required methods
fn get<'life0, 'life1, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
) -> Pin<Box<dyn Future<Output = Result<Option<User>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn find_by_provider<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
provider: &'life1 ProviderKey,
subject: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Option<User>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn create<'life0, 'async_trait>(
&'life0 self,
new_user: NewUser,
) -> Pin<Box<dyn Future<Output = Result<User, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn link_provider<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
provider: &'life2 ProviderKey,
subject: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait;
fn list_devices<'life0, 'life1, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
) -> Pin<Box<dyn Future<Output = Result<Vec<DeviceId>, StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn revoke_device<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
device_id: &'life2 DeviceId,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
}Expand description
User identity + provider-link persistence.
One User may be reachable through multiple (ProviderKey, subject)
pairs — that’s what link_provider is for. list_devices and
revoke_device are the session-management surface: products surface them
to end-users on an /account/sessions page (P12).
Required Methods§
Sourcefn get<'life0, 'life1, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
) -> Pin<Box<dyn Future<Output = Result<Option<User>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get<'life0, 'life1, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
) -> Pin<Box<dyn Future<Output = Result<Option<User>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Look up a user by its UserId. None if no such user exists.
This is the accessor a service reaches for when it already holds a
verified bearer: Claims::sub is a UserId, so everything past
authentication has the id and nothing else. Without this, recovering the
record behind a token meant re-deriving it from (provider, subject) —
which the token doesn’t carry — or keying downstream state on email,
which is nullable on User and not the identity.
A revoked device does not hide the user: revocation is per-device
(revoke_device), and the user row outlives it. None here means the
id names no user at all.
Sourcefn find_by_provider<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
provider: &'life1 ProviderKey,
subject: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Option<User>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn find_by_provider<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
provider: &'life1 ProviderKey,
subject: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Option<User>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Look up the user reachable via (provider, subject). None if no
such link exists.
Sourcefn create<'life0, 'async_trait>(
&'life0 self,
new_user: NewUser,
) -> Pin<Box<dyn Future<Output = Result<User, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn create<'life0, 'async_trait>(
&'life0 self,
new_user: NewUser,
) -> Pin<Box<dyn Future<Output = Result<User, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Create a fresh user (no provider linked yet). Returns the user with
its newly minted UserId.
Sourcefn link_provider<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
provider: &'life2 ProviderKey,
subject: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn link_provider<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
provider: &'life2 ProviderKey,
subject: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Link (provider, subject) to an existing user. Returns
StoreError::Conflict if the link already exists for a different
user; idempotent if it matches.
Sourcefn list_devices<'life0, 'life1, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
) -> Pin<Box<dyn Future<Output = Result<Vec<DeviceId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn list_devices<'life0, 'life1, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
) -> Pin<Box<dyn Future<Output = Result<Vec<DeviceId>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Enumerate every device this user has signed in from (and not revoked).
Sourcefn revoke_device<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
device_id: &'life2 DeviceId,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn revoke_device<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
user_id: &'life1 UserId,
device_id: &'life2 DeviceId,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Revoke a device. The two halves of “revoked” are first-class (R019-F4):
block new sessions by revoking the device’s refresh chains
(RefreshStore::revoke_chain), and kill an in-flight access token by
its jti via RevocationWriter::revoke;
the edge enforces the latter through
RevocationReader. This method records
the device-level intent; composing those calls is
SessionAuthority’s job.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".