sopass 0.5.0

command line password manager using SOP
Documentation
//! The `export` sub-command.

use std::{
    fs::{read, write},
    path::PathBuf,
};

use clap::Parser;
use log::info;

use crate::{
    store::{EncryptedStore, EncryptedStoreError, Store, StoreError},
    Config, LeafCommand,
};

/// Export store in cleartext as JSON to the named file.
#[derive(Debug, Parser)]
pub struct ExportCommand {
    /// Write exported data to this file.
    filename: PathBuf,
}

impl LeafCommand for ExportCommand {
    type Error = ExportError;
    fn run(&self, config: &Config) -> Result<(), ExportError> {
        let store = EncryptedStore::new(config.sop(), config.store()).read_store()?;
        info!("loaded store OK");
        let json = serde_json::to_string_pretty(&store).map_err(ExportError::ToJson)?;
        write(&self.filename, &json)
            .map_err(|err| ExportError::WriteFile(self.filename.clone(), err))?;
        Ok(())
    }
}

/// Import data from an exported file.
///
/// This adds data to from the exported file without removing any. If
/// a value name is in both, the import replaces the existing value in
/// the store.
#[derive(Debug, Parser)]
pub struct ImportCommand {
    /// Read exported data from this file.
    filename: PathBuf,
}

impl LeafCommand for ImportCommand {
    type Error = ExportError;
    fn run(&self, config: &Config) -> Result<(), ExportError> {
        let encrypted = EncryptedStore::new(config.sop(), config.store());
        let mut store = encrypted.read_store()?;

        let data = read(&self.filename)
            .map_err(|err| ExportError::ReadFile(self.filename.clone(), err))?;
        let imported: Store = serde_json::from_slice(&data).map_err(ExportError::FromJson)?;
        store.import(&imported);

        encrypted.write_store(&store)?;

        Ok(())
    }
}

/// Possible errors from `export` sub-command.
#[derive(Debug, thiserror::Error)]
pub enum ExportError {
    /// Error from handling encrypted store.
    #[error(transparent)]
    Encrypted(#[from] EncryptedStoreError),

    /// Error from using cleartext store.
    #[error(transparent)]
    Store(#[from] StoreError),

    /// Can't serialize store as JSON.
    #[error("failed to serialize store as JSON")]
    ToJson(#[source] serde_json::Error),

    /// Can't de-serialize store from JSON.
    #[error("failed to parse exported data as JSON")]
    FromJson(#[source] serde_json::Error),

    /// Can't read file.
    #[error("failed to read exported data from file {0}")]
    ReadFile(PathBuf, #[source] std::io::Error),

    /// Can't write file.
    #[error("failed to write exported data to file {0}")]
    WriteFile(PathBuf, #[source] std::io::Error),
}