at main 209 lines 6.5 kB view raw
1#[cfg(target_arch = "wasm32")] 2use gloo_storage::{LocalStorage, SessionStorage, Storage}; 3use jacquard::client::SessionStoreError; 4use jacquard::oauth::authstore::ClientAuthStore; 5#[cfg(not(target_arch = "wasm32"))] 6use jacquard::oauth::authstore::MemoryAuthStore; 7use jacquard::oauth::session::{AuthRequestData, ClientSessionData}; 8use jacquard::types::string::Did; 9use std::future::Future; 10#[cfg(not(target_arch = "wasm32"))] 11use std::sync::LazyLock; 12 13#[cfg(target_arch = "wasm32")] 14#[derive(Clone)] 15pub struct AuthStore; 16 17#[cfg(target_arch = "wasm32")] 18impl AuthStore { 19 pub fn new() -> Self { 20 Self 21 } 22 23 fn session_key(did: &Did<'_>, session_id: &str) -> String { 24 format!("oauth_session_{}_{}", did.as_ref(), session_id) 25 } 26 27 fn auth_req_key(state: &str) -> String { 28 format!("oauth_auth_req_{}", state) 29 } 30} 31 32#[cfg(target_arch = "wasm32")] 33impl ClientAuthStore for AuthStore { 34 fn get_session( 35 &self, 36 did: &Did<'_>, 37 session_id: &str, 38 ) -> impl Future<Output = Result<Option<ClientSessionData<'_>>, SessionStoreError>> { 39 let key = Self::session_key(did, session_id); 40 async move { 41 match LocalStorage::get::<serde_json::Value>(&key) { 42 Ok(value) => { 43 let data: ClientSessionData<'static> = 44 jacquard::from_json_value::<ClientSessionData>(value).map_err(|e| { 45 SessionStoreError::Other(format!("Deserialize error: {}", e).into()) 46 })?; 47 Ok(Some(data)) 48 } 49 Err(gloo_storage::errors::StorageError::KeyNotFound(_)) => Ok(None), 50 Err(e) => Err(SessionStoreError::Other( 51 format!("LocalStorage error: {}", e).into(), 52 )), 53 } 54 } 55 } 56 57 fn upsert_session( 58 &self, 59 session: ClientSessionData<'_>, 60 ) -> impl Future<Output = Result<(), SessionStoreError>> { 61 async move { 62 use jacquard::IntoStatic; 63 64 let key = Self::session_key(&session.account_did, &session.session_id); 65 let static_session = session.into_static(); 66 67 let value = serde_json::to_value(&static_session) 68 .map_err(|e| SessionStoreError::Other(format!("Serialize error: {}", e).into()))?; 69 70 LocalStorage::set(&key, &value).map_err(|e| { 71 SessionStoreError::Other(format!("LocalStorage error: {}", e).into()) 72 })?; 73 74 Ok(()) 75 } 76 } 77 78 fn delete_session( 79 &self, 80 did: &Did<'_>, 81 session_id: &str, 82 ) -> impl Future<Output = Result<(), SessionStoreError>> { 83 let key = Self::session_key(did, session_id); 84 async move { 85 LocalStorage::delete(&key); 86 Ok(()) 87 } 88 } 89 90 fn get_auth_req_info( 91 &self, 92 state: &str, 93 ) -> impl Future<Output = Result<Option<AuthRequestData<'_>>, SessionStoreError>> { 94 let key = Self::auth_req_key(state); 95 async move { 96 match LocalStorage::get::<serde_json::Value>(&key) { 97 Ok(value) => { 98 let data: AuthRequestData<'static> = 99 jacquard::from_json_value::<AuthRequestData>(value).map_err(|e| { 100 SessionStoreError::Other(format!("Deserialize error: {}", e).into()) 101 })?; 102 Ok(Some(data)) 103 } 104 Err(gloo_storage::errors::StorageError::KeyNotFound(err)) => { 105 tracing::debug!("gloo error: {}", err); 106 Ok(None) 107 } 108 Err(e) => Err(SessionStoreError::Other( 109 format!("SessionStorage error: {}", e).into(), 110 )), 111 } 112 } 113 } 114 115 fn save_auth_req_info( 116 &self, 117 auth_req_info: &AuthRequestData<'_>, 118 ) -> impl Future<Output = Result<(), SessionStoreError>> { 119 async move { 120 use jacquard::IntoStatic; 121 122 let key = Self::auth_req_key(&auth_req_info.state); 123 let static_info = auth_req_info.clone().into_static(); 124 125 let value = serde_json::to_value(&static_info) 126 .map_err(|e| SessionStoreError::Other(format!("Serialize error: {}", e).into()))?; 127 128 LocalStorage::set(&key, &value).map_err(|e| { 129 SessionStoreError::Other(format!("SessionStorage error: {}", e).into()) 130 })?; 131 132 Ok(()) 133 } 134 } 135 136 fn delete_auth_req_info( 137 &self, 138 state: &str, 139 ) -> impl Future<Output = Result<(), SessionStoreError>> { 140 let key = Self::auth_req_key(state); 141 async move { 142 LocalStorage::delete(&key); 143 Ok(()) 144 } 145 } 146} 147#[cfg(not(target_arch = "wasm32"))] 148use std::sync::Arc; 149 150#[cfg(not(target_arch = "wasm32"))] 151pub struct AuthStore(Arc<MemoryAuthStore>); 152 153#[cfg(not(target_arch = "wasm32"))] 154static MEM_STORE: LazyLock<Arc<MemoryAuthStore>> = 155 LazyLock::new(|| Arc::new(MemoryAuthStore::new())); 156 157#[cfg(not(target_arch = "wasm32"))] 158impl AuthStore { 159 pub fn new() -> Self { 160 Self(MEM_STORE.clone()) 161 } 162} 163 164#[cfg(not(target_arch = "wasm32"))] 165impl ClientAuthStore for AuthStore { 166 fn get_session( 167 &self, 168 did: &Did<'_>, 169 session_id: &str, 170 ) -> impl Future<Output = Result<Option<ClientSessionData<'_>>, SessionStoreError>> { 171 self.0.get_session(did, session_id) 172 } 173 174 fn upsert_session( 175 &self, 176 session: ClientSessionData<'_>, 177 ) -> impl Future<Output = Result<(), SessionStoreError>> { 178 self.0.upsert_session(session) 179 } 180 181 fn delete_session( 182 &self, 183 did: &Did<'_>, 184 session_id: &str, 185 ) -> impl Future<Output = Result<(), SessionStoreError>> { 186 self.0.delete_session(did, session_id) 187 } 188 189 fn get_auth_req_info( 190 &self, 191 state: &str, 192 ) -> impl Future<Output = Result<Option<AuthRequestData<'_>>, SessionStoreError>> { 193 self.0.get_auth_req_info(state) 194 } 195 196 fn save_auth_req_info( 197 &self, 198 auth_req_info: &AuthRequestData<'_>, 199 ) -> impl Future<Output = Result<(), SessionStoreError>> { 200 self.0.save_auth_req_info(auth_req_info) 201 } 202 203 fn delete_auth_req_info( 204 &self, 205 state: &str, 206 ) -> impl Future<Output = Result<(), SessionStoreError>> { 207 self.0.delete_auth_req_info(state) 208 } 209}