baza_core 2.8.0

The base password manager
Documentation
use crate::{r#box, BazaR, Config};
use core::fmt;
use std::cell::RefCell;
use std::process::Command;
use std::rc::Rc;
use std::sync::Arc;
use tempfile::NamedTempFile;

use self::r#box::BoxRef;

pub type BundleRef = Rc<RefCell<Bundle>>;

#[derive(Debug)]
pub(crate) struct Bundle {
    pub(crate) name: Arc<str>,
    pub(crate) ptr: Option<Vec<String>>,
    pub(crate) file: NamedTempFile,
    pub(crate) parent: Option<BoxRef>,
}

impl fmt::Display for Bundle {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.ptr().join(&Config::get().main.box_delimiter))
    }
}

impl Bundle {
    pub(crate) fn new(name: String) -> BazaR<Self> {
        let file =
            tempfile::Builder::new().tempfile_in(format!("{}/tmp", Config::get().main.datadir))?;
        let name = Arc::from(name);
        Ok(Self {
            name,
            file,
            parent: None,
            ptr: None,
        })
    }

    pub(crate) fn ptr(&self) -> Vec<String> {
        let mut pointer = self
            .parent
            .as_ref()
            .map(|parent| parent.borrow().ptr())
            .unwrap_or_default();
        pointer.push(self.name.to_string());

        pointer
    }

    pub(crate) fn create(&self, data: Option<String>) -> BazaR<()> {
        tracing::debug!("Creating bundle {:?}", &self.file);
        let editor = std::env::var("EDITOR").unwrap_or(String::from("vi"));

        let file = self.file.path().to_path_buf();

        if let Some(str) = data {
            std::fs::write(&file, str)?;
        } else {
            let status = Command::new(editor).arg(&file).status()?;
            if !status.success() {
                std::process::exit(1);
            }
        };

        crate::encrypt_file(&file)?;
        Ok(())
    }
}