pub struct MemoryStorage { /* private fields */ }Expand description
The in-memory Storage: a mutexed set of maps. Reference implementation for the trait’s
contract (its take_* are atomic by construction) and the store this crate’s own tests run on.
Allocates nothing beyond its empty maps until used.
Implementations§
Source§impl MemoryStorage
impl MemoryStorage
Trait Implementations§
Source§impl Default for MemoryStorage
impl Default for MemoryStorage
Source§fn default() -> MemoryStorage
fn default() -> MemoryStorage
Source§impl Storage for MemoryStorage
impl Storage for MemoryStorage
Source§async fn compare_and_swap_client(
&self,
expected: &Client,
updated: Client,
) -> Result<bool, StorageError>
async fn compare_and_swap_client( &self, expected: &Client, updated: Client, ) -> Result<bool, StorageError>
The whole operation happens under ONE guard, which is what makes the comparison and the
write a single atomic step here. Ok(false) and no write when the record is absent or has
moved on; absence is the Storage::delete_client case and it must stay absent.
Source§async fn compare_and_swap_device_grant(
&self,
expected: &DeviceGrantState,
updated: DeviceGrant,
) -> Result<bool, StorageError>
async fn compare_and_swap_device_grant( &self, expected: &DeviceGrantState, updated: DeviceGrant, ) -> Result<bool, StorageError>
The whole operation happens under ONE guard, which is what makes it a compare-and-swap rather than a read followed by a hopeful write, and what a single-process host is entitled to expect from the reference implementation.
Both halves of the user-code index contract documented on Storage::put_device_grant are
enforced here TOO, restated rather than delegated, because a &mut guard is already held
and calling the other method would deadlock. That duplication is a hazard worth naming: an
earlier version of this doc claimed the index maintenance was delegated and therefore could
not drift, and it had already drifted, because requirement (1), refusing a user code that is
live for a DIFFERENT device code, was simply absent. A swap could hand one user code to two
grants where a put would have refused. If either method changes, change both.
One guard, so the comparison and the write cannot be separated. Absence refuses, which is what keeps a swept or cascaded code from being reinstated.
Source§async fn compare_and_swap_consent(
&self,
expected: Option<&ConsentRecord>,
updated: ConsentRecord,
) -> Result<bool, StorageError>
Available on crate feature consent only.
async fn compare_and_swap_consent( &self, expected: Option<&ConsentRecord>, updated: ConsentRecord, ) -> Result<bool, StorageError>
consent only.One guard again, and the comparison is against what find_consent would answer for the
PAIR rather than against the consent_id: a withdrawal removes the record the caller read
and any replacement has a different id, so comparing ids would miss the interleaving.
Source§async fn get_client(
&self,
client_id: &ClientId,
) -> Result<Option<Arc<Client>>, StorageError>
async fn get_client( &self, client_id: &ClientId, ) -> Result<Option<Arc<Client>>, StorageError>
Source§async fn put_client(&self, client: Client) -> Result<(), StorageError>
async fn put_client(&self, client: Client) -> Result<(), StorageError>
Source§async fn delete_client(
&self,
client_id: &ClientId,
window: RevocationWindow,
) -> Result<bool, StorageError>
async fn delete_client( &self, client_id: &ClientId, window: RevocationWindow, ) -> Result<bool, StorageError>
Source§async fn put_device_grant(&self, grant: DeviceGrant) -> Result<(), StorageError>
async fn put_device_grant(&self, grant: DeviceGrant) -> Result<(), StorageError>
device_code, maintaining the user-code index. Read moreSource§async fn get_device_grant(
&self,
device_code: &str,
) -> Result<Option<DeviceGrant>, StorageError>
async fn get_device_grant( &self, device_code: &str, ) -> Result<Option<DeviceGrant>, StorageError>
Source§async fn find_device_grant_by_user_code(
&self,
normalized_user_code: &str,
) -> Result<Option<DeviceGrant>, StorageError>
async fn find_device_grant_by_user_code( &self, normalized_user_code: &str, ) -> Result<Option<DeviceGrant>, StorageError>
Source§async fn take_device_grant(
&self,
device_code: &str,
) -> Result<Option<DeviceGrant>, StorageError>
async fn take_device_grant( &self, device_code: &str, ) -> Result<Option<DeviceGrant>, StorageError>
None. Read morepar only.request_uri. Read morepar only.request_uri single use: RFC 9126 section 4 says a client MUST use one once and section
7.3 asks the server to enforce it rather than trust that, so under concurrent authorization
requests exactly one caller receives the record and every other caller sees None. A plain
read-then-delete reintroduces the replay this is here to prevent. Read moreSource§async fn put_token(
&self,
token: IssuedToken,
) -> Result<WriteOutcome, StorageError>
async fn put_token( &self, token: IssuedToken, ) -> Result<WriteOutcome, StorageError>
Source§async fn get_token(
&self,
access_token: &str,
) -> Result<Option<Arc<IssuedToken>>, StorageError>
async fn get_token( &self, access_token: &str, ) -> Result<Option<Arc<IssuedToken>>, StorageError>
Source§async fn delete_token(&self, access_token: &str) -> Result<(), StorageError>
async fn delete_token(&self, access_token: &str) -> Result<(), StorageError>
Source§async fn put_refresh_token(
&self,
record: RefreshTokenRecord,
) -> Result<WriteOutcome, StorageError>
async fn put_refresh_token( &self, record: RefreshTokenRecord, ) -> Result<WriteOutcome, StorageError>
Source§async fn get_refresh_token(
&self,
refresh_token: &str,
) -> Result<Option<Arc<RefreshTokenRecord>>, StorageError>
async fn get_refresh_token( &self, refresh_token: &str, ) -> Result<Option<Arc<RefreshTokenRecord>>, StorageError>
Source§async fn take_refresh_token(
&self,
refresh_token: &str,
) -> Result<Option<RefreshTokenRecord>, StorageError>
async fn take_refresh_token( &self, refresh_token: &str, ) -> Result<Option<RefreshTokenRecord>, StorageError>
invalid_grant. Read moreSource§async fn revoke_token_family(
&self,
family_id: &str,
window: RevocationWindow,
) -> Result<u64, StorageError>
async fn revoke_token_family( &self, family_id: &str, window: RevocationWindow, ) -> Result<u64, StorageError>
family_id, and return how many records
were removed. Read moreSource§async fn put_consent(&self, record: ConsentRecord) -> Result<(), StorageError>
async fn put_consent(&self, record: ConsentRecord) -> Result<(), StorageError>
consent only.consent_id. Read moreSource§async fn get_consent(
&self,
consent_id: &str,
) -> Result<Option<Arc<ConsentRecord>>, StorageError>
async fn get_consent( &self, consent_id: &str, ) -> Result<Option<Arc<ConsentRecord>>, StorageError>
consent only.Source§async fn find_consent(
&self,
client_id: &ClientId,
subject: &str,
) -> Result<Option<Arc<ConsentRecord>>, StorageError>
async fn find_consent( &self, client_id: &ClientId, subject: &str, ) -> Result<Option<Arc<ConsentRecord>>, StorageError>
consent only.Source§async fn consents_for_subject(
&self,
subject: &str,
) -> Result<Vec<Arc<ConsentRecord>>, StorageError>
async fn consents_for_subject( &self, subject: &str, ) -> Result<Vec<Arc<ConsentRecord>>, StorageError>
consent only.Source§async fn revoke_consent(
&self,
consent_id: &str,
window: RevocationWindow,
) -> Result<u64, StorageError>
async fn revoke_consent( &self, consent_id: &str, window: RevocationWindow, ) -> Result<u64, StorageError>
consent only.Source§async fn claim_replay_id(
&self,
id: &str,
expires_at: SystemTime,
) -> Result<bool, StorageError>
async fn claim_replay_id( &self, id: &str, expires_at: SystemTime, ) -> Result<bool, StorageError>
client-assertion or dpop only.true when this caller is the first
to claim it and false when it has already been claimed. Read moreSource§async fn sweep_expired(&self, now: SystemTime) -> Result<u64, StorageError>
async fn sweep_expired(&self, now: SystemTime) -> Result<u64, StorageError>
now, and return how many were removed. Read more