Revamp desktop usability and multiline fields

This commit is contained in:
2026-08-10 22:06:16 +02:00
parent 40b15a9713
commit aeb18b488f
12 changed files with 1283 additions and 545 deletions

View File

@@ -1,6 +1,11 @@
//! Storage-owned service boundary for the Iced desktop presentation adapter.
use std::{error::Error, fmt, path::Path};
use std::{
error::Error,
fmt,
path::Path,
sync::{Arc, OnceLock},
};
use crate::{
authentication::{
@@ -120,6 +125,7 @@ impl Error for DesktopError {}
#[derive(Clone, Debug)]
pub struct DesktopStorage {
config: Config,
keys: Arc<OnceLock<KeyStore>>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -299,9 +305,12 @@ impl DesktopMutationRequest {
impl DesktopStorage {
pub fn load(explicit: Option<&Path>) -> Result<Self, DesktopError> {
Config::load(explicit)
.map(|config| Self { config })
.map_err(|error| DesktopError::new(DesktopErrorKind::Configuration, error))
let config = Config::load(explicit)
.map_err(|error| DesktopError::new(DesktopErrorKind::Configuration, error))?;
Ok(Self {
config,
keys: Arc::new(OnceLock::new()),
})
}
pub fn system() -> Result<DesktopBootstrap, DesktopError> {
@@ -309,8 +318,7 @@ impl DesktopStorage {
}
pub fn bootstrap(self) -> Result<DesktopBootstrap, DesktopError> {
let keys = KeyStore::load(self.config.key_material())
.map_err(|error| DesktopError::new(DesktopErrorKind::KeyMaterial, error))?;
let keys = self.keys()?;
let handle = keys
.resolve(self.config.default_key().as_str())
.map_err(|error| DesktopError::new(DesktopErrorKind::KeyMaterial, error))?;
@@ -386,7 +394,10 @@ impl DesktopStorage {
.config
.with_settings(settings)
.map_err(|error| DesktopError::new(DesktopErrorKind::Configuration, error))?;
let storage = Self { config };
let storage = Self {
config,
keys: Arc::clone(&self.keys),
};
let keys = storage.keys()?;
keys.resolve(storage.config.default_key().as_str())
.map_err(|error| DesktopError::new(DesktopErrorKind::KeyMaterial, error))?;
@@ -411,7 +422,7 @@ impl DesktopStorage {
pub fn tree(&self) -> Result<TreeModel, DesktopError> {
let repository = self.repository()?;
let keys = self.keys()?;
VaultReader::new(&repository, &keys)
VaultReader::new(&repository, keys)
.list(&DirectoryPath::root())
.map_err(|error| DesktopError::new(DesktopErrorKind::Read, error))
}
@@ -505,7 +516,7 @@ impl DesktopStorage {
pub fn find(&self, request: &FindRequest) -> Result<FindResults, DesktopError> {
let repository = self.repository()?;
let keys = self.keys()?;
VaultReader::new(&repository, &keys)
VaultReader::new(&repository, keys)
.find(&request.terms)
.map_err(|error| DesktopError::new(DesktopErrorKind::Read, error))
}
@@ -529,7 +540,7 @@ impl DesktopStorage {
) -> Result<GrepResults, DesktopError> {
let repository = self.repository()?;
let keys = self.keys()?;
VaultReader::new(&repository, &keys)
VaultReader::new(&repository, keys)
.grep(request, provider)
.map_err(|error| DesktopError::new(DesktopErrorKind::Read, error))
}
@@ -557,7 +568,7 @@ impl DesktopStorage {
) -> Result<DesktopOtpCode, DesktopError> {
let repository = self.repository()?;
let keys = self.keys()?;
let service = OtpService::new(&repository, &keys);
let service = OtpService::new(&repository, keys);
let uri = service
.uri(entry, provider)
.map_err(|error| DesktopError::new(DesktopErrorKind::Otp, error))?;
@@ -582,7 +593,7 @@ impl DesktopStorage {
let tree = changed.then(|| self.tree()).transpose()?;
let document = changed
.then(|| {
EntryDocumentService::new(&repository, &keys)
EntryDocumentService::new(&repository, keys)
.open(entry, provider)
.map_err(DesktopError::document)
})
@@ -617,7 +628,7 @@ impl DesktopStorage {
) -> Result<DesktopOtpUri, DesktopError> {
let repository = self.repository()?;
let keys = self.keys()?;
let uri = OtpService::new(&repository, &keys)
let uri = OtpService::new(&repository, keys)
.uri(entry, provider)
.map_err(|error| DesktopError::new(DesktopErrorKind::Otp, error))?;
let payload = SecretBytes::new(uri.encoded().expose().to_vec());
@@ -680,11 +691,11 @@ impl DesktopStorage {
let encoded = parsed.encoded().expose().to_vec();
let repository = self.repository()?;
let keys = self.keys()?;
let exists = VaultWriter::new(&repository, &keys)
let exists = VaultWriter::new(&repository, keys)
.entry_exists(entry)
.map_err(|error| DesktopError::new(DesktopErrorKind::Otp, error))?;
if exists {
let mut document = EntryDocumentService::new(&repository, &keys)
let mut document = EntryDocumentService::new(&repository, keys)
.open(entry, provider)
.map_err(DesktopError::document)?;
if let Some(field) = otp_field(&document)? {
@@ -708,7 +719,7 @@ impl DesktopStorage {
.map_err(DesktopError::document)?;
}
self.save_document(&document)?;
let document = EntryDocumentService::new(&repository, &keys)
let document = EntryDocumentService::new(&repository, keys)
.open(entry, provider)
.map_err(DesktopError::document)?;
return Ok(DesktopOtpMutation {
@@ -725,7 +736,7 @@ impl DesktopStorage {
};
let input = OtpInput::line(encoded)
.map_err(|error| DesktopError::new(DesktopErrorKind::Otp, error))?;
let service = OtpService::new(&repository, &keys);
let service = OtpService::new(&repository, keys);
let plan = service
.prepare_insert(&request, input)
.map_err(|error| DesktopError::new(DesktopErrorKind::Otp, error))?;
@@ -741,7 +752,7 @@ impl DesktopStorage {
&mut committer,
)
.map_err(|error| DesktopError::new(DesktopErrorKind::Otp, error))?;
let document = EntryDocumentService::new(&repository, &keys)
let document = EntryDocumentService::new(&repository, keys)
.open(entry, provider)
.map_err(DesktopError::document)?;
Ok(DesktopOtpMutation {
@@ -770,7 +781,7 @@ impl DesktopStorage {
) -> Result<DesktopOtpMutation, DesktopError> {
let repository = self.repository()?;
let keys = self.keys()?;
let mut document = EntryDocumentService::new(&repository, &keys)
let mut document = EntryDocumentService::new(&repository, keys)
.open(entry, provider)
.map_err(DesktopError::document)?;
let field = otp_field(&document)?.ok_or_else(|| {
@@ -781,7 +792,7 @@ impl DesktopStorage {
})?;
document.remove(field).map_err(DesktopError::document)?;
self.save_document(&document)?;
let document = EntryDocumentService::new(&repository, &keys)
let document = EntryDocumentService::new(&repository, keys)
.open(entry, provider)
.map_err(DesktopError::document)?;
Ok(DesktopOtpMutation {
@@ -818,7 +829,7 @@ impl DesktopStorage {
GitIdentity::ironstorage(),
)
.map_err(|error| DesktopError::new(DesktopErrorKind::Git, error))?;
let mutator = TreeMutator::new(&repository, &keys);
let mutator = TreeMutator::new(&repository, keys);
match request {
DesktopMutationRequest::Remove(request) => {
mutator.remove(request, overwrite, &mut committer)
@@ -892,7 +903,7 @@ impl DesktopStorage {
replacement: &replacement.config,
persisted: false,
};
let outcome = RecipientPolicyManager::new(&repository, &keys)
let outcome = RecipientPolicyManager::new(&repository, keys)
.apply_init(request, None, provider, &mut committer)
.map_err(|error| DesktopError::new(DesktopErrorKind::Repository, error))?;
if !committer.persisted {
@@ -922,7 +933,7 @@ impl DesktopStorage {
) -> Result<EntryDocument, DesktopError> {
let repository = self.repository()?;
let keys = self.keys()?;
if VaultWriter::new(&repository, &keys)
if VaultWriter::new(&repository, keys)
.entry_exists(entry)
.map_err(|error| DesktopError::new(DesktopErrorKind::Document, error))?
{
@@ -931,7 +942,7 @@ impl DesktopStorage {
format!("password-store entry already exists: {entry}"),
));
}
EntryDocumentService::new(&repository, &keys)
EntryDocumentService::new(&repository, keys)
.open(entry, provider)
.map_err(DesktopError::document)
}
@@ -943,7 +954,7 @@ impl DesktopStorage {
) -> Result<EntryDocument, DesktopError> {
let repository = self.repository()?;
let keys = self.keys()?;
EntryDocumentService::new(&repository, &keys)
EntryDocumentService::new(&repository, keys)
.open(entry, secrets)
.map_err(DesktopError::document)
}
@@ -955,7 +966,7 @@ impl DesktopStorage {
let mut committer =
AutomaticEntryCommitter::for_entry(&repository, &entry, GitIdentity::ironstorage())
.map_err(|error| DesktopError::new(DesktopErrorKind::Git, error))?;
EntryDocumentService::new(&repository, &keys)
EntryDocumentService::new(&repository, keys)
.save_recoverable(document, None, &mut committer)
.map_err(DesktopError::document)
}
@@ -976,9 +987,17 @@ impl DesktopStorage {
.map_err(|error| DesktopError::new(DesktopErrorKind::Repository, error))
}
fn keys(&self) -> Result<KeyStore, DesktopError> {
KeyStore::load(self.config.key_material())
.map_err(|error| DesktopError::new(DesktopErrorKind::KeyMaterial, error))
fn keys(&self) -> Result<&KeyStore, DesktopError> {
if let Some(keys) = self.keys.get() {
return Ok(keys);
}
let keys = KeyStore::load(self.config.key_material())
.map_err(|error| DesktopError::new(DesktopErrorKind::KeyMaterial, error))?;
let _already_initialized = self.keys.set(keys);
Ok(self
.keys
.get()
.expect("the key store was initialized by this or another caller"))
}
}