sos_backend/
vault_writer.rs

1use crate::{BackendTarget, Error, Result};
2use async_trait::async_trait;
3use sos_core::{
4    commit::CommitHash,
5    crypto::AeadPack,
6    events::{ReadEvent, WriteEvent},
7    SecretId, VaultCommit, VaultEntry, VaultFlags, VaultId,
8};
9use sos_database::VaultDatabaseWriter;
10use sos_filesystem::VaultFileWriter;
11use sos_vault::{EncryptedEntry, Summary, Vault};
12use std::borrow::Cow;
13
14/// Backend vault writer.
15pub enum VaultWriter {
16    /// Vault backed by a database table.
17    Database(VaultDatabaseWriter<Error>),
18    /// Vault backed by a file on disc.
19    FileSystem(VaultFileWriter<Error>),
20}
21
22impl VaultWriter {
23    /// Create a new vault writer.
24    pub fn new(target: BackendTarget, folder_id: &VaultId) -> Self {
25        match target {
26            BackendTarget::FileSystem(paths) => {
27                let path = paths.vault_path(folder_id);
28                Self::FileSystem(VaultFileWriter::<Error>::new(path))
29            }
30            BackendTarget::Database(_, client) => Self::Database(
31                VaultDatabaseWriter::<Error>::new(client, *folder_id),
32            ),
33        }
34    }
35}
36
37#[async_trait]
38impl EncryptedEntry for VaultWriter {
39    type Error = Error;
40
41    async fn summary(&self) -> Result<Summary> {
42        Ok(match self {
43            Self::Database(inner) => inner.summary().await?,
44            Self::FileSystem(inner) => inner.summary().await?,
45        })
46    }
47
48    async fn vault_name(&self) -> Result<Cow<'_, str>> {
49        Ok(match self {
50            Self::Database(inner) => inner.vault_name().await?,
51            Self::FileSystem(inner) => inner.vault_name().await?,
52        })
53    }
54
55    async fn set_vault_name(&mut self, name: String) -> Result<WriteEvent> {
56        Ok(match self {
57            Self::Database(inner) => inner.set_vault_name(name).await?,
58            Self::FileSystem(inner) => inner.set_vault_name(name).await?,
59        })
60    }
61
62    async fn set_vault_flags(
63        &mut self,
64        flags: VaultFlags,
65    ) -> Result<WriteEvent> {
66        Ok(match self {
67            Self::Database(inner) => inner.set_vault_flags(flags).await?,
68            Self::FileSystem(inner) => inner.set_vault_flags(flags).await?,
69        })
70    }
71
72    async fn set_vault_meta(&mut self, meta: AeadPack) -> Result<WriteEvent> {
73        Ok(match self {
74            Self::Database(inner) => inner.set_vault_meta(meta).await?,
75            Self::FileSystem(inner) => inner.set_vault_meta(meta).await?,
76        })
77    }
78
79    async fn create_secret(
80        &mut self,
81        commit: CommitHash,
82        secret: VaultEntry,
83    ) -> Result<WriteEvent> {
84        self.insert_secret(SecretId::new_v4(), commit, secret).await
85    }
86
87    async fn insert_secret(
88        &mut self,
89        secret_id: SecretId,
90        commit: CommitHash,
91        secret: VaultEntry,
92    ) -> Result<WriteEvent> {
93        Ok(match self {
94            Self::Database(inner) => {
95                inner.insert_secret(secret_id, commit, secret).await?
96            }
97            Self::FileSystem(inner) => {
98                inner.insert_secret(secret_id, commit, secret).await?
99            }
100        })
101    }
102
103    async fn read_secret<'a>(
104        &'a self,
105        secret_id: &SecretId,
106    ) -> Result<Option<(Cow<'a, VaultCommit>, ReadEvent)>> {
107        Ok(match self {
108            Self::Database(inner) => inner.read_secret(secret_id).await?,
109            Self::FileSystem(inner) => inner.read_secret(secret_id).await?,
110        })
111    }
112
113    async fn update_secret(
114        &mut self,
115        secret_id: &SecretId,
116        commit: CommitHash,
117        secret: VaultEntry,
118    ) -> Result<Option<WriteEvent>> {
119        Ok(match self {
120            Self::Database(inner) => {
121                inner.update_secret(secret_id, commit, secret).await?
122            }
123            Self::FileSystem(inner) => {
124                inner.update_secret(secret_id, commit, secret).await?
125            }
126        })
127    }
128
129    async fn delete_secret(
130        &mut self,
131        secret_id: &SecretId,
132    ) -> Result<Option<WriteEvent>> {
133        Ok(match self {
134            Self::Database(inner) => inner.delete_secret(secret_id).await?,
135            Self::FileSystem(inner) => inner.delete_secret(secret_id).await?,
136        })
137    }
138
139    async fn replace_vault(&mut self, vault: &Vault) -> Result<()> {
140        Ok(match self {
141            Self::Database(inner) => inner.replace_vault(vault).await?,
142            Self::FileSystem(inner) => inner.replace_vault(vault).await?,
143        })
144    }
145}