bitwarden_ipc/wasm/
generic_session_repository.rs

1//! Generic session repository abstraction allowing IPC clients to choose between
2//! SDK-managed (in-memory) and client-managed (JavaScript-backed) session storage.
3//!
4//! This is a workaround because wasm-bindgen does not handle generics.
5//!
6//! Use SDK-managed when state providers might not make sense, for example if they
7//! will use insecure IPC to save the data, defeating the whole point of a secure session.
8
9use std::sync::Arc;
10
11use crate::{
12    traits::{InMemorySessionRepository, SessionRepository},
13    wasm::JsSessionRepository,
14};
15
16// TODO: Change session type when implementing encryption
17type Session = ();
18
19pub enum GenericSessionRepository {
20    InMemory(Arc<InMemorySessionRepository<Session>>),
21    JsSessionRepository(Arc<JsSessionRepository>),
22}
23
24impl SessionRepository<Session> for GenericSessionRepository {
25    type GetError = String;
26    type SaveError = String;
27    type RemoveError = String;
28
29    async fn get(
30        &self,
31        endpoint: crate::endpoint::Endpoint,
32    ) -> Result<Option<Session>, Self::GetError> {
33        match self {
34            GenericSessionRepository::InMemory(repo) => repo
35                .get(endpoint)
36                .await
37                .map_err(|_| "InMemorySessionRepository::get should never fail".to_owned()),
38            GenericSessionRepository::JsSessionRepository(repo) => {
39                <JsSessionRepository as SessionRepository<Session>>::get(repo.as_ref(), endpoint)
40                    .await
41            }
42        }
43    }
44
45    async fn save(
46        &self,
47        endpoint: crate::endpoint::Endpoint,
48        session: Session,
49    ) -> Result<(), Self::SaveError> {
50        match self {
51            GenericSessionRepository::InMemory(repo) => repo
52                .save(endpoint, session)
53                .await
54                .map_err(|_| "InMemorySessionRepository::save should never fail".to_owned()),
55            GenericSessionRepository::JsSessionRepository(repo) => {
56                <JsSessionRepository as SessionRepository<Session>>::save(
57                    repo.as_ref(),
58                    endpoint,
59                    session,
60                )
61                .await
62            }
63        }
64    }
65
66    async fn remove(&self, endpoint: crate::endpoint::Endpoint) -> Result<(), Self::RemoveError> {
67        match self {
68            GenericSessionRepository::InMemory(repo) => repo
69                .remove(endpoint)
70                .await
71                .map_err(|_| "InMemorySessionRepository::remove should never fail".to_owned()),
72            GenericSessionRepository::JsSessionRepository(repo) => {
73                <JsSessionRepository as SessionRepository<Session>>::remove(repo.as_ref(), endpoint)
74                    .await
75            }
76        }
77    }
78}