1use crate::{AccessPoint, BackendTarget, Error, FolderEventLog, Result};
3use sos_core::{
4 commit::{CommitHash, CommitState},
5 crypto::AccessKey,
6 encode,
7 events::{EventLog, EventRecord, ReadEvent, WriteEvent},
8 AccountId, VaultFlags, VaultId,
9};
10use sos_core::{constants::EVENT_LOG_EXT, decode, VaultCommit};
11use sos_database::{
12 entity::{FolderEntity, FolderRecord, SecretRecord},
13 VaultDatabaseWriter,
14};
15use sos_filesystem::VaultFileWriter;
16use sos_reducers::FolderReducer;
17use sos_vault::{
18 secret::{Secret, SecretId, SecretMeta, SecretRow},
19 AccessPoint as VaultAccessPoint, EncryptedEntry, SecretAccess, Vault,
20 VaultMeta,
21};
22use sos_vfs as vfs;
23use std::{path::Path, sync::Arc};
24use tokio::sync::{Mutex, RwLock};
25
26#[derive(Clone)]
28pub struct Folder {
29 access_point: Arc<Mutex<AccessPoint>>,
30 events: Arc<RwLock<FolderEventLog>>,
31}
32
33impl Folder {
34 pub async fn new(
38 target: BackendTarget,
39 account_id: &AccountId,
40 folder_id: &VaultId,
41 ) -> Result<Self> {
42 match target {
43 BackendTarget::FileSystem(paths) => {
44 Self::from_path(
45 paths.with_account_id(account_id).vault_path(folder_id),
46 )
47 .await
48 }
49 BackendTarget::Database(paths, client) => {
50 let folder_id = *folder_id;
51 let folder_row = client
52 .conn(move |conn| {
53 let folder = FolderEntity::new(&conn);
54 Ok(folder.find_one(&folder_id)?)
55 })
56 .await
57 .map_err(sos_database::Error::from)?;
58 let folder_record =
59 FolderRecord::from_row(folder_row).await?;
60 let mut vault = folder_record.into_vault()?;
61
62 let secrets = client
63 .conn_and_then(move |conn| {
64 let folder = FolderEntity::new(&conn);
65 let secrets =
66 folder.load_secrets(folder_record.row_id)?;
67 Ok::<_, sos_database::Error>(secrets)
68 })
69 .await?;
70
71 for secret in secrets {
72 let record = SecretRecord::from_row(secret).await?;
73 let VaultCommit(commit, entry) = record.commit;
74 vault
75 .insert_secret(record.secret_id, commit, entry)
76 .await?;
77 }
78
79 let mut event_log = FolderEventLog::new_folder(
80 BackendTarget::Database(paths, client.clone()),
81 &account_id,
82 &folder_id,
83 )
84 .await?;
85
86 event_log.load_tree().await?;
87
88 if event_log.tree().len() == 0 {
89 let buffer = encode(&vault).await?;
90 let event = WriteEvent::CreateVault(buffer);
91 event_log.apply(&[event]).await?;
92 }
93
94 let mirror =
95 VaultDatabaseWriter::<Error>::new(client, folder_id);
96 let access_point = VaultAccessPoint::<Error>::new_mirror(
97 vault,
98 Box::new(mirror),
99 );
100
101 Ok(Self::init(AccessPoint::wrap(access_point), event_log))
102 }
103 }
104 }
105
106 pub async fn from_vault_event_log(
108 target: &BackendTarget,
109 vault: Vault,
110 event_log: FolderEventLog,
111 ) -> Result<Self> {
112 let access_point = match target {
113 BackendTarget::FileSystem(paths) => {
114 let path = paths.vault_path(vault.id());
115 let mirror = VaultFileWriter::<Error>::new(path);
116 VaultAccessPoint::<Error>::new_mirror(vault, Box::new(mirror))
117 }
118 BackendTarget::Database(_, client) => {
119 let mirror = VaultDatabaseWriter::<Error>::new(
120 client.clone(),
121 *vault.id(),
122 );
123 VaultAccessPoint::<Error>::new_mirror(vault, Box::new(mirror))
124 }
125 };
126 Ok(Self::init(AccessPoint::wrap(access_point), event_log))
127 }
128
129 pub async fn from_path(path: impl AsRef<Path>) -> Result<Self> {
136 let mut events_path = path.as_ref().to_owned();
137 events_path.set_extension(EVENT_LOG_EXT);
138
139 let mut event_log =
140 sos_filesystem::FolderEventLog::<Error>::new_folder(events_path)
141 .await?;
142 event_log.load_tree().await?;
143 let needs_init = event_log.tree().root().is_none();
144
145 let vault = if needs_init {
146 let vault = if vfs::try_exists(path.as_ref()).await? {
147 let buffer = vfs::read(path.as_ref()).await?;
152 let vault: Vault = decode(&buffer).await?;
153 vault
154 } else {
155 Default::default()
157 };
158
159 let (_, events) =
160 FolderReducer::split::<Error>(vault.clone()).await?;
161 event_log.apply(events.as_slice()).await?;
162
163 vault
164 } else {
165 let buffer = vfs::read(path.as_ref()).await?;
166 let vault: Vault = decode(&buffer).await?;
167 vault
168 };
169
170 let mirror = VaultFileWriter::<Error>::new(path.as_ref());
171 let access_point =
172 VaultAccessPoint::<Error>::new_mirror(vault, Box::new(mirror));
173
174 Ok(Self::init(
175 AccessPoint::wrap(access_point),
176 FolderEventLog::FileSystem(event_log),
177 ))
178 }
179
180 fn init(access_point: AccessPoint, events: FolderEventLog) -> Self {
182 Self {
183 access_point: Arc::new(Mutex::new(access_point)),
184 events: Arc::new(RwLock::new(events)),
185 }
186 }
187
188 pub async fn id(&self) -> VaultId {
190 let access_point = self.access_point.lock().await;
191 *access_point.id()
192 }
193
194 pub fn access_point(&self) -> Arc<Mutex<AccessPoint>> {
196 self.access_point.clone()
197 }
198
199 pub fn event_log(&self) -> Arc<RwLock<FolderEventLog>> {
201 Arc::clone(&self.events)
202 }
203
204 pub async fn unlock(
206 &mut self,
207 key: &AccessKey,
208 ) -> crate::Result<VaultMeta> {
209 let mut access_point = self.access_point.lock().await;
210 Ok(access_point.unlock(key).await?)
211 }
212
213 pub async fn lock(&mut self) {
215 let mut access_point = self.access_point.lock().await;
216 access_point.lock();
217 }
218
219 pub async fn create_secret(
221 &mut self,
222 secret_data: &SecretRow,
223 ) -> crate::Result<WriteEvent> {
224 let mut access_point = self.access_point.lock().await;
225 let event = access_point.create_secret(secret_data).await?;
226 let mut events = self.events.write().await;
227 events.apply(&[event.clone()]).await?;
228 Ok(event)
229 }
230
231 pub async fn read_secret(
233 &self,
234 id: &SecretId,
235 ) -> crate::Result<Option<(SecretMeta, Secret, ReadEvent)>> {
236 let access_point = self.access_point.lock().await;
237 Ok(access_point.read_secret(id).await?)
238 }
239
240 pub async fn raw_secret(
242 &self,
243 id: &SecretId,
244 ) -> crate::Result<Option<(VaultCommit, ReadEvent)>> {
245 let access_point = self.access_point.lock().await;
246 Ok(access_point.raw_secret(id).await?)
247 }
248
249 pub async fn update_secret(
251 &mut self,
252 id: &SecretId,
253 secret_meta: SecretMeta,
254 secret: Secret,
255 ) -> crate::Result<Option<WriteEvent>> {
256 let mut access_point = self.access_point.lock().await;
257 if let Some(event) =
258 access_point.update_secret(id, secret_meta, secret).await?
259 {
260 let mut events = self.events.write().await;
261 events.apply(&[event.clone()]).await?;
262 Ok(Some(event))
263 } else {
264 Ok(None)
265 }
266 }
267
268 pub async fn delete_secret(
270 &mut self,
271 id: &SecretId,
272 ) -> Result<Option<WriteEvent>> {
273 let mut access_point = self.access_point.lock().await;
274 if let Some(event) = access_point.delete_secret(id).await? {
275 let mut events = self.events.write().await;
276 events.apply(&[event.clone()]).await?;
277 Ok(Some(event))
278 } else {
279 Ok(None)
280 }
281 }
282
283 pub async fn rename_folder(
285 &mut self,
286 name: impl AsRef<str>,
287 ) -> Result<WriteEvent> {
288 let mut access_point = self.access_point.lock().await;
289 access_point
290 .set_vault_name(name.as_ref().to_owned())
291 .await?;
292 let event = WriteEvent::SetVaultName(name.as_ref().to_owned());
293 let mut events = self.events.write().await;
294 events.apply(&[event.clone()]).await?;
295 Ok(event)
296 }
297
298 pub async fn update_folder_flags(
300 &mut self,
301 flags: VaultFlags,
302 ) -> Result<WriteEvent> {
303 let mut access_point = self.access_point.lock().await;
304 access_point.set_vault_flags(flags.clone()).await?;
305 let event = WriteEvent::SetVaultFlags(flags);
306 let mut events = self.events.write().await;
307 events.apply(&[event.clone()]).await?;
308 Ok(event)
309 }
310
311 pub async fn description(&self) -> Result<String> {
313 let access_point = self.access_point.lock().await;
314 let meta = access_point.vault_meta().await?;
315 Ok(meta.description().to_owned())
316 }
317
318 pub async fn set_description(
320 &mut self,
321 description: impl AsRef<str>,
322 ) -> Result<WriteEvent> {
323 let mut meta = {
324 let access_point = self.access_point.lock().await;
325 access_point.vault_meta().await?
326 };
327 meta.set_description(description.as_ref().to_owned());
328 self.set_meta(&meta).await
329 }
330
331 pub async fn set_meta(&mut self, meta: &VaultMeta) -> Result<WriteEvent> {
333 let mut access_point = self.access_point.lock().await;
334 let event = access_point.set_vault_meta(meta).await?;
335 let mut events = self.events.write().await;
336 events.apply(&[event.clone()]).await?;
337 Ok(event)
338 }
339
340 pub async fn commit_state(&self) -> Result<CommitState> {
342 let event_log = self.events.read().await;
343 Ok(event_log.tree().commit_state()?)
344 }
345
346 pub async fn root_hash(&self) -> Result<CommitHash> {
348 let event_log = self.events.read().await;
349 Ok(event_log
350 .tree()
351 .root()
352 .ok_or(sos_core::Error::NoRootCommit)?)
353 }
354
355 pub async fn apply(&mut self, events: &[WriteEvent]) -> Result<()> {
357 let mut event_log = self.events.write().await;
358 event_log.apply(events).await?;
359 Ok(())
360 }
361
362 pub async fn apply_records(
364 &mut self,
365 records: Vec<EventRecord>,
366 ) -> Result<()> {
367 let mut event_log = self.events.write().await;
368 event_log.apply_records(records).await?;
369 Ok(())
370 }
371
372 pub async fn clear(&mut self) -> Result<()> {
374 let mut event_log = self.events.write().await;
375 event_log.clear().await?;
376 Ok(())
377 }
378}
379
380impl From<Folder> for Vault {
381 fn from(value: Folder) -> Self {
382 let mutex = Arc::into_inner(value.access_point).unwrap();
383 let access_point = mutex.into_inner();
384 access_point.into()
385 }
386}