Present desktop OTP and sensitive outputs

This commit is contained in:
2026-08-10 20:22:59 +02:00
parent 95bb10b4a1
commit 4a54bf7b6a
13 changed files with 1881 additions and 39 deletions

View File

@@ -2,6 +2,8 @@
use std::path::PathBuf;
use ironstorage::repository::SecretBytes;
#[cfg(any(target_os = "macos", target_os = "windows"))]
pub async fn pick_folder(initial: Option<PathBuf>) -> Result<Option<PathBuf>, String> {
let mut dialog = rfd::AsyncFileDialog::new().set_title("Open Password Store");
@@ -14,6 +16,22 @@ pub async fn pick_folder(initial: Option<PathBuf>) -> Result<Option<PathBuf>, St
.map(|folder| folder.path().to_owned()))
}
#[cfg(any(target_os = "macos", target_os = "windows"))]
pub async fn pick_qr_image() -> Result<Option<SecretBytes>, String> {
let selected = rfd::AsyncFileDialog::new()
.set_title("Import OTP QR Image")
.add_filter("Image", &["png", "jpg", "jpeg", "gif"])
.pick_file()
.await;
selected
.map(|file| {
std::fs::read(file.path())
.map(SecretBytes::new)
.map_err(|error| error.to_string())
})
.transpose()
}
#[cfg(target_os = "linux")]
pub async fn pick_folder(initial: Option<PathBuf>) -> Result<Option<PathBuf>, String> {
use ashpd::{
@@ -47,6 +65,37 @@ pub async fn pick_folder(initial: Option<PathBuf>) -> Result<Option<PathBuf>, St
.map(Some)
}
#[cfg(target_os = "linux")]
pub async fn pick_qr_image() -> Result<Option<SecretBytes>, String> {
use ashpd::{
PortalError,
desktop::{file_chooser::SelectedFiles, request::ResponseError},
};
let response = SelectedFiles::open_file()
.title("Import OTP QR Image")
.accept_label("Import")
.modal(true)
.multiple(false)
.send()
.await
.and_then(|request| request.response());
let selected = match response {
Ok(selected) => selected,
Err(ashpd::Error::Response(ResponseError::Cancelled))
| Err(ashpd::Error::Portal(PortalError::Cancelled(_))) => return Ok(None),
Err(error) => return Err(error.to_string()),
};
let Some(uri) = selected.uris().first() else {
return Err("file portal returned no selection".to_owned());
};
let path = file_uri_path(uri.as_str())?;
std::fs::read(path)
.map(SecretBytes::new)
.map(Some)
.map_err(|error| error.to_string())
}
#[cfg(target_os = "linux")]
fn file_uri_path(uri: &str) -> Result<PathBuf, String> {
let uri = url::Url::parse(uri).map_err(|_| "folder portal returned an invalid URI")?;