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}