Skip to main content

nethsm/cli/
passphrase_file.rs

1//! Handling of files containing a [`Passphrase`].
2
3use std::{
4    fs::read_to_string,
5    path::{Path, PathBuf},
6    str::FromStr,
7};
8
9use crate::Passphrase;
10
11/// A representation of a file containing a passphrase
12#[derive(Clone, Debug)]
13pub struct PassphraseFile {
14    /// The passphrase contained in the file.
15    pub passphrase: Passphrase,
16}
17
18impl PassphraseFile {
19    /// Creates a new [`PassphraseFile`] from a path.
20    ///
21    /// # Errors
22    ///
23    /// Returns an error if reading the file to string fails.
24    pub fn new(path: &Path) -> Result<Self, crate::Error> {
25        Ok(Self {
26            passphrase: Passphrase::new(read_to_string(path).map_err(crate::cli::Error::Io)?),
27        })
28    }
29}
30
31impl FromStr for PassphraseFile {
32    type Err = crate::Error;
33
34    fn from_str(s: &str) -> Result<Self, Self::Err> {
35        PassphraseFile::new(&PathBuf::from(s))
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use std::io::Write;
42
43    use log::LevelFilter;
44    use rstest::rstest;
45    use signstar_common::logging::setup_terminal_logging;
46    use tempfile::NamedTempFile;
47    use testresult::TestResult;
48
49    use super::*;
50
51    #[rstest]
52    fn passphrase_file() -> TestResult {
53        setup_terminal_logging(LevelFilter::Debug)?;
54
55        let passphrase = "this is a passphrase";
56        let mut temp_file = NamedTempFile::new()?;
57        temp_file.write_all(passphrase.as_bytes())?;
58
59        let passphrase_file = PassphraseFile::new(temp_file.path())?;
60        assert_eq!(passphrase_file.passphrase.expose_borrowed(), passphrase);
61
62        Ok(())
63    }
64}