oauth2_broker/store/
memory.rs1use crate::{
5 _prelude::*,
6 auth::{ScopeSet, TokenFamily, TokenRecord, token::secret::TokenSecret},
7 store::{BrokerStore, CompareAndSwapOutcome, StoreError, StoreFuture, StoreKey},
8};
9
10type StoreMap = Arc<RwLock<HashMap<StoreKey, TokenRecord>>>;
11
12#[derive(Clone, Debug, Default)]
14pub struct MemoryStore(StoreMap);
15impl MemoryStore {
16 fn save_now(map: StoreMap, record: TokenRecord) -> Result<(), StoreError> {
17 let key = StoreKey::new(&record.family, &record.scope);
18
19 map.write().insert(key, record);
20
21 Ok(())
22 }
23
24 fn fetch_now(map: StoreMap, family: TokenFamily, scope: ScopeSet) -> Option<TokenRecord> {
25 let key = StoreKey::new(&family, &scope);
26
27 map.read().get(&key).cloned()
28 }
29
30 fn cas_now(
31 map: StoreMap,
32 family: TokenFamily,
33 scope: ScopeSet,
34 expected_refresh: Option<&str>,
35 replacement: TokenRecord,
36 ) -> CompareAndSwapOutcome {
37 let key = StoreKey::new(&family, &scope);
38 let mut guard = map.write();
39 let outcome = match guard.get(&key) {
40 Some(existing)
41 if Self::refresh_matches(existing.refresh_token.as_ref(), expected_refresh) =>
42 CompareAndSwapOutcome::Updated,
43 Some(_) => CompareAndSwapOutcome::RefreshMismatch,
44 None => CompareAndSwapOutcome::Missing,
45 };
46
47 if matches!(outcome, CompareAndSwapOutcome::Updated) {
48 guard.insert(key, replacement);
49 }
50
51 outcome
52 }
53
54 fn refresh_matches(current: Option<&TokenSecret>, expected: Option<&str>) -> bool {
55 match (current.map(TokenSecret::expose), expected) {
56 (None, None) => true,
57 (Some(cur), Some(exp)) => cur == exp,
58 _ => false,
59 }
60 }
61
62 fn revoke_now(
63 map: StoreMap,
64 family: TokenFamily,
65 scope: ScopeSet,
66 instant: OffsetDateTime,
67 ) -> Option<TokenRecord> {
68 let key = StoreKey::new(&family, &scope);
69 let mut guard = map.write();
70
71 match guard.get_mut(&key) {
72 Some(record) => {
73 record.revoke(instant);
74
75 Some(record.clone())
76 },
77 None => None,
78 }
79 }
80}
81impl BrokerStore for MemoryStore {
82 fn save(&self, record: TokenRecord) -> StoreFuture<'_, ()> {
83 let map = self.0.clone();
84
85 Box::pin(async move { Self::save_now(map, record) })
86 }
87
88 fn fetch<'a>(
89 &'a self,
90 family: &'a TokenFamily,
91 scope: &'a ScopeSet,
92 ) -> StoreFuture<'a, Option<TokenRecord>> {
93 let map = self.0.clone();
94 let family = family.to_owned();
95 let scope = scope.to_owned();
96
97 Box::pin(async move { Ok(Self::fetch_now(map, family, scope)) })
98 }
99
100 fn compare_and_swap_refresh<'a>(
101 &'a self,
102 family: &'a TokenFamily,
103 scope: &'a ScopeSet,
104 expected_refresh: Option<&'a str>,
105 replacement: TokenRecord,
106 ) -> StoreFuture<'a, CompareAndSwapOutcome> {
107 let map = self.0.clone();
108 let family = family.to_owned();
109 let scope = scope.to_owned();
110
111 Box::pin(
112 async move { Ok(Self::cas_now(map, family, scope, expected_refresh, replacement)) },
113 )
114 }
115
116 fn revoke<'a>(
117 &'a self,
118 family: &'a TokenFamily,
119 scope: &'a ScopeSet,
120 instant: OffsetDateTime,
121 ) -> StoreFuture<'a, Option<TokenRecord>> {
122 let map = self.0.clone();
123 let family = family.to_owned();
124 let scope = scope.to_owned();
125
126 Box::pin(async move { Ok(Self::revoke_now(map, family, scope, instant)) })
127 }
128}