Allow existing GPG keys with cloned stores
This commit is contained in:
1 parent
0b7c938b23
commit
a8a59d496b
3 files changed
+252
-40
No files matched your search
@@ -145,7 +145,7 @@ pub struct MobileKeyTransferService {
|
||||
impl MobileKeyTransferService {
|
||||
pub fn load() -> Result<Self, MobileKeyTransferError> {
|
||||
let config = Config::load(None)?;
|
||||
let keys = KeyStore::load(config.key_material())?;
|
||||
let keys = load_keys_or_empty(config.key_material())?;
|
||||
Ok(Self { config, keys })
|
||||
}
|
||||
|
||||
@@ -316,16 +316,24 @@ impl MobileKeyTransferImport {
|
||||
}
|
||||
|
||||
if matches!(self.destination, MobileKeyTransferDestination::LocalSetup) {
|
||||
if key.kind != MobileKeyTransferKind::Private || !make_default {
|
||||
if key.kind != MobileKeyTransferKind::Private {
|
||||
return Err(MobileKeyTransferError::PublicDefault);
|
||||
}
|
||||
let outcome = crate::mobile_onboarding::MobileOnboardingOperation::default()
|
||||
.setup_local_imported(
|
||||
let operation = crate::mobile_onboarding::MobileOnboardingOperation::default();
|
||||
let outcome = if make_default {
|
||||
operation.setup_local_imported(
|
||||
SecretBytes::new(armor.expose().to_vec()),
|
||||
passphrase,
|
||||
overwrite,
|
||||
)
|
||||
.map_err(MobileKeyTransferError::LocalSetup)?;
|
||||
} else {
|
||||
operation.stage_local_imported(
|
||||
SecretBytes::new(armor.expose().to_vec()),
|
||||
passphrase,
|
||||
overwrite,
|
||||
)
|
||||
}
|
||||
.map_err(MobileKeyTransferError::LocalSetup)?;
|
||||
return Ok(MobileKeyTransferOutcome {
|
||||
title: outcome.title().to_owned(),
|
||||
detail: outcome.detail().to_owned(),
|
||||
@@ -334,7 +342,7 @@ impl MobileKeyTransferImport {
|
||||
let MobileKeyTransferDestination::Configured(config) = &self.destination else {
|
||||
unreachable!("local setup returned above")
|
||||
};
|
||||
let existing = KeyStore::load(config.key_material())?;
|
||||
let existing = load_keys_or_empty(config.key_material())?;
|
||||
if let Some(found) = existing
|
||||
.infos()
|
||||
.find(|info| info.fingerprint().as_str() == key.fingerprint)
|
||||
@@ -389,6 +397,13 @@ impl MobileKeyTransferImport {
|
||||
}
|
||||
}
|
||||
|
||||
fn load_keys_or_empty(path: &Path) -> Result<KeyStore, CryptoError> {
|
||||
match KeyStore::load(path) {
|
||||
Err(CryptoError::NoKeyMaterial) => Ok(KeyStore::new()),
|
||||
result => result,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum MobileKeyTransferError {
|
||||
Configuration,
|
||||
@@ -640,7 +655,7 @@ fn set_private_permissions(_temporary: &TempFile<'_>) -> Result<(), MobileKeyTra
|
||||
mod tests {
|
||||
use super::{
|
||||
MobileKeyTransferError, MobileKeyTransferImport, MobileKeyTransferKind,
|
||||
MobileKeyTransferService, encode_multipart,
|
||||
MobileKeyTransferService, encode_multipart, load_keys_or_empty,
|
||||
};
|
||||
use crate::{config::Config, crypto::KeyStore, repository::SecretBytes};
|
||||
use tempfile::tempdir;
|
||||
@@ -800,6 +815,36 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cloned_store_with_empty_key_directory_can_import_its_private_key()
|
||||
-> Result<(), Box<dyn std::error::Error>> {
|
||||
let fixture = configured_key("placeholder", b"")?;
|
||||
std::fs::remove_file(fixture.key_path.join("placeholder"))?;
|
||||
let service = MobileKeyTransferService {
|
||||
keys: load_keys_or_empty(&fixture.key_path)?,
|
||||
config: fixture.config.clone(),
|
||||
};
|
||||
assert!(service.keys().is_empty());
|
||||
|
||||
let mut importer = service.importer();
|
||||
importer.add_frame(SecretBytes::new(ALICE_SECRET.to_vec()))?;
|
||||
importer.import(
|
||||
Some(SecretBytes::new(b"fixture-alice-passphrase".to_vec())),
|
||||
true,
|
||||
false,
|
||||
)?;
|
||||
|
||||
let keys = KeyStore::load(&fixture.key_path)?;
|
||||
assert!(keys.resolve(ALICE_FINGERPRINT).is_ok());
|
||||
assert_eq!(
|
||||
Config::load(Some(fixture.config.source()))?
|
||||
.default_key()
|
||||
.as_str(),
|
||||
ALICE_FINGERPRINT
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct Fixture {
|
||||
_root: tempfile::TempDir,
|
||||
config: Config,
|
||||
|
||||
Reference in new issue
Block a user