#![deny(missing_docs)]
#![forbid(unsafe_code)]
#![cfg_attr(all(doc, CHANNEL_NIGHTLY), feature(doc_auto_cfg))]
mod account;
pub mod commit;
pub mod constants;
pub mod crypto;
mod date_time;
pub mod device;
pub mod encoding;
mod error;
pub mod events;
mod file;
pub mod file_identity;
mod identity;
mod origin;
mod paths;
pub use account::AccountId;
pub use date_time::UtcDateTime;
pub use encoding::{decode, encode};
pub use error::{AuthenticationError, Error, ErrorExt, StorageError};
pub use file::{ExternalFile, ExternalFileName};
pub use identity::{AccountRef, PublicIdentity};
pub use origin::{Origin, RemoteOrigins};
pub use paths::Paths;
pub use rs_merkle as merkle;
pub(crate) type Result<T> = std::result::Result<T, Error>;
use bitflags::bitflags;
use rand::{rngs::OsRng, CryptoRng, Rng};
use serde::{Deserialize, Serialize};
use std::{fmt, path::Path, str::FromStr};
use uuid::Uuid;
pub fn csprng() -> impl CryptoRng + Rng {
OsRng
}
pub type VaultId = Uuid;
pub type SecretId = Uuid;
#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
pub struct VaultEntry(pub crypto::AeadPack, pub crypto::AeadPack);
#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
pub struct VaultCommit(pub commit::CommitHash, pub VaultEntry);
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct SecretPath(pub VaultId, pub SecretId);
impl SecretPath {
pub fn folder_id(&self) -> &VaultId {
&self.0
}
pub fn secret_id(&self) -> &SecretId {
&self.1
}
}
pub fn basename(path: impl AsRef<Path>) -> String {
path.as_ref()
.file_name()
.unwrap_or_default()
.to_string_lossy()
.into_owned()
}
pub fn guess_mime(path: impl AsRef<Path>) -> Result<String> {
if let Some(extension) = path.as_ref().extension() {
let fixed = match extension.to_string_lossy().as_ref() {
"heic" => Some("image/heic".to_string()),
"heif" => Some("image/heif".to_string()),
"avif" => Some("image/avif".to_string()),
_ => None,
};
if let Some(fixed) = fixed {
return Ok(fixed);
}
}
let mime = mime_guess::from_path(&path)
.first_or(mime_guess::mime::APPLICATION_OCTET_STREAM)
.to_string();
Ok(mime)
}
bitflags! {
#[derive(Default, Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
#[serde(transparent)]
pub struct VaultFlags: u64 {
const DEFAULT = 0b0000000000000001;
const IDENTITY = 0b0000000000000010;
const ARCHIVE = 0b0000000000000100;
const AUTHENTICATOR = 0b0000000000001000;
const CONTACT = 0b0000000000010000;
const SYSTEM = 0b0000000000100000;
const DEVICE = 0b0000000001000000;
const NO_SYNC = 0b0000000010000000;
const LOCAL = 0b0000000100000000;
const SHARED = 0b0000001000000000;
}
}
impl VaultFlags {
pub fn is_default(&self) -> bool {
self.contains(VaultFlags::DEFAULT)
}
pub fn is_identity(&self) -> bool {
self.contains(VaultFlags::IDENTITY)
}
pub fn is_archive(&self) -> bool {
self.contains(VaultFlags::ARCHIVE)
}
pub fn is_authenticator(&self) -> bool {
self.contains(VaultFlags::AUTHENTICATOR)
}
pub fn is_contact(&self) -> bool {
self.contains(VaultFlags::CONTACT)
}
pub fn is_system(&self) -> bool {
self.contains(VaultFlags::SYSTEM)
}
pub fn is_device(&self) -> bool {
self.contains(VaultFlags::DEVICE)
}
pub fn is_sync_disabled(&self) -> bool {
self.contains(VaultFlags::NO_SYNC)
}
pub fn is_local(&self) -> bool {
self.contains(VaultFlags::LOCAL)
}
pub fn is_shared(&self) -> bool {
self.contains(VaultFlags::SHARED)
}
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ArchiveManifestVersion {
V1 = 1,
V2 = 2,
V3 = 3,
}
impl Default for ArchiveManifestVersion {
fn default() -> Self {
Self::V1
}
}
impl Serialize for ArchiveManifestVersion {
fn serialize<S>(
&self,
serializer: S,
) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u8(*self as u8)
}
}
impl<'de> Deserialize<'de> for ArchiveManifestVersion {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = u8::deserialize(deserializer)?;
match value {
1 => Ok(ArchiveManifestVersion::V1),
2 => Ok(ArchiveManifestVersion::V2),
3 => Ok(ArchiveManifestVersion::V3),
_ => Err(serde::de::Error::custom(
"invalid archive manifest version",
)),
}
}
}
#[derive(Debug, Clone)]
pub enum FolderRef {
Id(VaultId),
Name(String),
}
impl fmt::Display for FolderRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Id(id) => write!(f, "{}", id),
Self::Name(name) => write!(f, "{}", name),
}
}
}
impl FromStr for FolderRef {
type Err = Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
if let Ok(id) = Uuid::parse_str(s) {
Ok(Self::Id(id))
} else {
Ok(Self::Name(s.to_string()))
}
}
}
impl From<VaultId> for FolderRef {
fn from(value: VaultId) -> Self {
Self::Id(value)
}
}