radicle_systemd/
credential.rs1use std::env::{VarError::*, var};
2use std::ffi::OsString;
3use std::fmt;
4use std::path::{PathBuf, is_separator};
5
6const CREDENTIALS_DIRECTORY: &str = "CREDENTIALS_DIRECTORY";
7
8pub fn path(id: &str) -> Result<Option<PathBuf>, PathError> {
16 use PathError::*;
17
18 if id.contains(is_separator) {
19 return Err(InvalidCredentialId { id: id.to_owned() });
20 }
21
22 let credential = match var(CREDENTIALS_DIRECTORY) {
23 Err(NotUnicode(os)) => return Err(EnvVarNotUnicode { os }),
24 Err(NotPresent) => return Ok(None),
25 Ok(env) => PathBuf::from(env).join(id),
26 };
27
28 Ok(credential.exists().then_some(credential))
29}
30
31#[derive(Debug)]
33pub enum PathError {
34 InvalidCredentialId { id: String },
35 EnvVarNotUnicode { os: OsString },
36}
37
38impl fmt::Display for PathError {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 use PathError::*;
41 match self {
42 InvalidCredentialId { id } => write!(f, "The systemd credential ID '{id}' is invalid."),
43 EnvVarNotUnicode { os } => write!(
44 f,
45 "The value of environment variable '{CREDENTIALS_DIRECTORY}' is not valid Unicode (it lossily translates to '{}').",
46 os.to_string_lossy()
47 ),
48 }
49 }
50}