Skip to main content

bitwarden_ipc/traits/
session_repository.rs

1use std::{collections::HashMap, fmt::Debug};
2
3use tokio::sync::RwLock;
4
5use crate::endpoint::Endpoint;
6
7/// Persists per-destination crypto sessions so they survive across sends and, where the
8/// implementation is durable, across restarts.
9pub trait SessionRepository<Session>: Send + Sync + 'static {
10    /// Error returned when a session could not be read.
11    type GetError: Debug + Send + Sync + 'static;
12    /// Error returned when a session could not be persisted.
13    type SaveError: Debug + Send + Sync + 'static;
14    /// Error returned when a session could not be removed.
15    type RemoveError: Debug + Send + Sync + 'static;
16
17    /// Load the session for the given destination, if one exists.
18    fn get(
19        &self,
20        destination: Endpoint,
21    ) -> impl std::future::Future<Output = Result<Option<Session>, Self::GetError>> + Send + Sync;
22    /// Store (or overwrite) the session for the given destination.
23    fn save(
24        &self,
25        destination: Endpoint,
26        session: Session,
27    ) -> impl std::future::Future<Output = Result<(), Self::SaveError>> + Send + Sync;
28    /// Remove the session for the given destination, if one exists.
29    fn remove(
30        &self,
31        destination: Endpoint,
32    ) -> impl std::future::Future<Output = Result<(), Self::RemoveError>> + Send + Sync;
33}
34
35/// An in-memory session repository implementation that stores sessions in a `HashMap` protected by
36/// an `RwLock`. This is a simple implementation that can be used for testing or in scenarios where
37/// persistence is not required.
38pub type InMemorySessionRepository<Session> = RwLock<HashMap<Endpoint, Session>>;
39impl<Session> SessionRepository<Session> for InMemorySessionRepository<Session>
40where
41    Session: Clone + Send + Sync + 'static,
42{
43    type GetError = ();
44    type SaveError = ();
45    type RemoveError = ();
46
47    async fn get(&self, destination: Endpoint) -> Result<Option<Session>, ()> {
48        Ok(self.read().await.get(&destination).cloned())
49    }
50
51    async fn save(&self, destination: Endpoint, session: Session) -> Result<(), ()> {
52        self.write().await.insert(destination, session);
53        Ok(())
54    }
55
56    async fn remove(&self, destination: Endpoint) -> Result<(), ()> {
57        self.write().await.remove(&destination);
58        Ok(())
59    }
60}