Implement biometric-protected GPG unlock

This commit is contained in:
2026-08-11 18:32:53 +02:00
parent 3295761bcf
commit 873db91204
15 changed files with 2043 additions and 59 deletions

View File

@@ -35,6 +35,7 @@ pub struct Config {
editor: Option<EditorCommand>,
clipboard_timeout: ClipboardTimeout,
authentication_timeout: AuthenticationTimeout,
biometric_unlock_enabled: bool,
mobile_tab: MobileTab,
mobile_home_refreshed_at: Option<i64>,
git_remotes: Vec<GitRemote>,
@@ -122,6 +123,10 @@ impl Config {
self.authentication_timeout
}
pub fn biometric_unlock_enabled(&self) -> bool {
self.biometric_unlock_enabled
}
pub fn mobile_tab(&self) -> MobileTab {
self.mobile_tab
}
@@ -203,6 +208,31 @@ impl Config {
validate_config(self.source.clone(), document, raw)?.persist()
}
pub fn update_biometric_unlock(&self, enabled: bool) -> Result<(), ConfigError> {
let mut document = self.document.clone();
let root = document
.as_table_mut()
.ok_or_else(|| ConfigError::Malformed {
path: self.source.clone(),
})?;
let security = root
.entry("security")
.or_insert_with(|| toml::Value::Table(toml::Table::new()))
.as_table_mut()
.ok_or(ConfigError::InvalidField { field: "security" })?;
security.insert(
"biometric_unlock_enabled".to_owned(),
toml::Value::Boolean(enabled),
);
let raw = document
.clone()
.try_into::<RawConfig>()
.map_err(|_| ConfigError::Malformed {
path: self.source.clone(),
})?;
validate_config(self.source.clone(), document, raw)?.persist()
}
pub(crate) fn create_mobile_clone(
source: PathBuf,
vault: &Path,
@@ -835,6 +865,7 @@ struct RawConfig {
#[serde(deny_unknown_fields)]
struct RawSecurity {
inactivity_timeout_seconds: Option<u64>,
biometric_unlock_enabled: Option<bool>,
}
#[derive(Default, Deserialize)]
@@ -916,6 +947,7 @@ fn validate_config(
.map_err(|_| ConfigError::InvalidField {
field: "security.inactivity_timeout_seconds",
})?;
let biometric_unlock_enabled = raw.security.biometric_unlock_enabled.unwrap_or(false);
let mobile_tab = raw
.ui
.selected_mobile_tab
@@ -943,6 +975,7 @@ fn validate_config(
editor,
clipboard_timeout,
authentication_timeout,
biometric_unlock_enabled,
mobile_tab,
mobile_home_refreshed_at,
git_remotes,
@@ -1113,7 +1146,11 @@ fn validate_known_fields(value: &toml::Value, source: &Path) -> Result<(), Confi
let security = security.as_table().ok_or_else(|| ConfigError::Malformed {
path: source.to_owned(),
})?;
validate_table(security, "security", &["inactivity_timeout_seconds"])?;
validate_table(
security,
"security",
&["inactivity_timeout_seconds", "biometric_unlock_enabled"],
)?;
}
if let Some(ui) = root.get("ui") {
let ui = ui.as_table().ok_or_else(|| ConfigError::Malformed {