sos_vault/
lib.rs

1#![deny(missing_docs)]
2#![forbid(unsafe_code)]
3#![cfg_attr(all(doc, CHANNEL_NIGHTLY), feature(doc_auto_cfg))]
4//! Vault encrypted storage and access.
5mod access_point;
6mod builder;
7mod change_password;
8mod encoding;
9mod error;
10pub mod secret;
11mod vault;
12
13pub use access_point::{AccessPoint, SecretAccess};
14pub use builder::{BuilderCredentials, VaultBuilder};
15pub use change_password::ChangePassword;
16pub use error::Error;
17pub use vault::{
18    Contents, EncryptedEntry, Header, SharedAccess, Summary, Vault, VaultMeta,
19};
20
21pub(crate) type Result<T> = std::result::Result<T, Error>;
22pub(crate) use vault::Auth;
23
24use sos_core::{constants::VAULT_EXT, Paths, PublicIdentity};
25use sos_vfs as vfs;
26use std::{
27    path::{Path, PathBuf},
28    sync::Arc,
29};
30
31/// List account information for the identity vaults.
32#[doc(hidden)]
33pub async fn list_accounts(
34    paths: Option<&Paths>,
35) -> Result<Vec<PublicIdentity>> {
36    let mut identities = Vec::new();
37    let paths = if let Some(paths) = paths {
38        Arc::new(paths.clone())
39    } else {
40        Paths::new_client(Paths::data_dir()?)
41    };
42
43    if !vfs::try_exists(paths.identity_dir()).await? {
44        return Ok(Vec::new());
45    }
46
47    let mut dir = vfs::read_dir(paths.identity_dir()).await?;
48    while let Some(entry) = dir.next_entry().await? {
49        if let Some(ident) = read_public_identity(entry.path()).await? {
50            identities.push(ident);
51        }
52    }
53    identities.sort_by(|a, b| a.label().cmp(b.label()));
54    Ok(identities)
55}
56
57/// Read the public identity from an identity vault file.
58#[doc(hidden)]
59pub async fn read_public_identity(
60    path: impl AsRef<Path>,
61) -> Result<Option<PublicIdentity>> {
62    if let (Some(extension), Some(file_stem)) =
63        (path.as_ref().extension(), path.as_ref().file_stem())
64    {
65        if extension == VAULT_EXT {
66            let summary = Header::read_summary_file(path.as_ref()).await?;
67            return Ok(Some(PublicIdentity::new(
68                file_stem.to_string_lossy().parse()?,
69                summary.name().to_owned(),
70            )));
71        } else {
72            Ok(None)
73        }
74    } else {
75        Ok(None)
76    }
77}
78
79/// List the folders in an account by inspecting
80/// the vault files in the vaults directory.
81#[doc(hidden)]
82pub async fn list_local_folders(
83    paths: &Paths,
84) -> Result<Vec<(Summary, PathBuf)>> {
85    let vaults_dir = paths.vaults_dir();
86    let mut vaults = Vec::new();
87    let mut dir = vfs::read_dir(vaults_dir).await?;
88    while let Some(entry) = dir.next_entry().await? {
89        if let Some(extension) = entry.path().extension() {
90            if extension == VAULT_EXT {
91                let summary = Header::read_summary_file(entry.path()).await?;
92                vaults.push((summary, entry.path().to_path_buf()));
93            }
94        }
95    }
96    Ok(vaults)
97}