A better Rust ATProto crate
at main 3.9 kB view raw
1use std::sync::Arc; 2 3use dashmap::DashMap; 4use jacquard_common::{ 5 IntoStatic, 6 session::{SessionStore, SessionStoreError}, 7 types::did::Did, 8}; 9use smol_str::{SmolStr, ToSmolStr, format_smolstr}; 10 11use crate::session::{AuthRequestData, ClientSessionData}; 12 13#[async_trait::async_trait] 14pub trait ClientAuthStore { 15 async fn get_session( 16 &self, 17 did: &Did<'_>, 18 session_id: &str, 19 ) -> Result<Option<ClientSessionData<'_>>, SessionStoreError>; 20 21 async fn upsert_session(&self, session: ClientSessionData<'_>) 22 -> Result<(), SessionStoreError>; 23 24 async fn delete_session( 25 &self, 26 did: &Did<'_>, 27 session_id: &str, 28 ) -> Result<(), SessionStoreError>; 29 30 async fn get_auth_req_info( 31 &self, 32 state: &str, 33 ) -> Result<Option<AuthRequestData<'_>>, SessionStoreError>; 34 35 async fn save_auth_req_info( 36 &self, 37 auth_req_info: &AuthRequestData<'_>, 38 ) -> Result<(), SessionStoreError>; 39 40 async fn delete_auth_req_info(&self, state: &str) -> Result<(), SessionStoreError>; 41} 42 43pub struct MemoryAuthStore { 44 sessions: DashMap<SmolStr, ClientSessionData<'static>>, 45 auth_reqs: DashMap<SmolStr, AuthRequestData<'static>>, 46} 47 48impl MemoryAuthStore { 49 pub fn new() -> Self { 50 Self { 51 sessions: DashMap::new(), 52 auth_reqs: DashMap::new(), 53 } 54 } 55} 56 57#[async_trait::async_trait] 58impl ClientAuthStore for MemoryAuthStore { 59 async fn get_session( 60 &self, 61 did: &Did<'_>, 62 session_id: &str, 63 ) -> Result<Option<ClientSessionData<'_>>, SessionStoreError> { 64 let key = format_smolstr!("{}_{}", did, session_id); 65 Ok(self.sessions.get(&key).map(|v| v.clone())) 66 } 67 68 async fn upsert_session( 69 &self, 70 session: ClientSessionData<'_>, 71 ) -> Result<(), SessionStoreError> { 72 let key = format_smolstr!("{}_{}", session.account_did, session.session_id); 73 self.sessions.insert(key, session.into_static()); 74 Ok(()) 75 } 76 77 async fn delete_session( 78 &self, 79 did: &Did<'_>, 80 session_id: &str, 81 ) -> Result<(), SessionStoreError> { 82 let key = format_smolstr!("{}_{}", did, session_id); 83 self.sessions.remove(&key); 84 Ok(()) 85 } 86 87 async fn get_auth_req_info( 88 &self, 89 state: &str, 90 ) -> Result<Option<AuthRequestData<'_>>, SessionStoreError> { 91 Ok(self.auth_reqs.get(state).map(|v| v.clone())) 92 } 93 94 async fn save_auth_req_info( 95 &self, 96 auth_req_info: &AuthRequestData<'_>, 97 ) -> Result<(), SessionStoreError> { 98 self.auth_reqs.insert( 99 auth_req_info.state.clone().to_smolstr(), 100 auth_req_info.clone().into_static(), 101 ); 102 Ok(()) 103 } 104 105 async fn delete_auth_req_info(&self, state: &str) -> Result<(), SessionStoreError> { 106 self.auth_reqs.remove(state); 107 Ok(()) 108 } 109} 110 111#[async_trait::async_trait] 112impl<T: ClientAuthStore + Send + Sync> 113 SessionStore<(Did<'static>, SmolStr), ClientSessionData<'static>> for Arc<T> 114{ 115 /// Get the current session if present. 116 async fn get(&self, key: &(Did<'static>, SmolStr)) -> Option<ClientSessionData<'static>> { 117 let (did, session_id) = key; 118 self.as_ref() 119 .get_session(did, session_id) 120 .await 121 .ok() 122 .flatten() 123 .into_static() 124 } 125 /// Persist the given session. 126 async fn set( 127 &self, 128 _key: (Did<'static>, SmolStr), 129 session: ClientSessionData<'static>, 130 ) -> Result<(), SessionStoreError> { 131 self.as_ref().upsert_session(session).await 132 } 133 /// Delete the given session. 134 async fn del(&self, key: &(Did<'static>, SmolStr)) -> Result<(), SessionStoreError> { 135 let (did, session_id) = key; 136 self.as_ref().delete_session(did, session_id).await 137 } 138}