Skip to main content

dbx_tools_auth/storage/
mod.rs

1mod file;
2mod memory;
3
4use crate::{Result, Token};
5use async_trait::async_trait;
6use std::{path::PathBuf, sync::Arc, time::Duration};
7
8pub use file::FileStore;
9pub use memory::MemoryStore;
10
11#[async_trait]
12/// Exclusive refresh lease; RAII locks can use the default consuming release.
13pub trait StorageLock: Send + Sync {
14    /// Release explicitly; dropping the consumed lock also releases RAII resources.
15    async fn release(self: Box<Self>) -> Result<()> {
16        Ok(())
17    }
18}
19
20#[async_trait]
21/// Credential persistence with exclusive refresh coordination.
22pub trait CredentialStore: Send + Sync {
23    /// Load the credential for exactly one key.
24    async fn load(&self, key: &str) -> Result<Option<Token>>;
25    /// Preflight writes before token rotation; stores needing no probe inherit the no-op.
26    async fn prepare_write(&self) -> Result<()> {
27        Ok(())
28    }
29    /// Persist a credential while preserving unrelated keys.
30    async fn save(&self, key: &str, token: &Token) -> Result<()>;
31    /// Delete a credential, succeeding if it is already absent.
32    async fn delete(&self, key: &str) -> Result<()>;
33    /// Acquire an exclusive refresh lease or fail within the timeout.
34    async fn lock(&self, key: &str, timeout: Duration) -> Result<Box<dyn StorageLock>>;
35    /// Return the backend identifier used by session status.
36    fn name(&self) -> &'static str;
37}
38
39#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, uniffi::Enum)]
40pub enum Storage {
41    #[default]
42    Auto,
43    Memory,
44    File,
45}
46
47pub type StoreBackend = Storage;
48
49#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, uniffi::Enum)]
50pub enum FileLayout {
51    #[default]
52    Single,
53    PerCredential,
54}
55
56pub async fn open_store(
57    backend: Storage,
58    directory: PathBuf,
59    layout: FileLayout,
60) -> Result<Arc<dyn CredentialStore>> {
61    match backend {
62        Storage::Memory => Ok(Arc::new(MemoryStore::new())),
63        Storage::Auto | Storage::File => Ok(Arc::new(FileStore::with_layout(directory, layout)?)),
64    }
65}