use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct Token {
pub refreshed: Instant,
pub min: u16,
pub ttl: Duration,
pub cmd: String,
pub value: Option<String>,
}
impl Token {
pub(crate) fn new(cmd: String, ttl: String, pwd: Option<String>) -> Result<Self, String> {
let min = ttl.parse::<u16>().unwrap_or(60);
let t = Token {
refreshed: Instant::now(),
ttl: Duration::from_secs(min as u64 * 60),
min,
cmd,
value: pwd,
};
#[cfg(feature="token")]
{
let mut t = t;
if !t.cmd.is_empty() {
let _ = t.refresh()?;
}
Ok(t)
}
#[cfg(not(feature="token"))]
Ok(t)
}
#[cfg(feature="token")]
pub fn refresh(&mut self) -> Result<Duration, String> {
if self.cmd.is_empty() {
return Err("Not configured".to_string());
} else {
let cmd:Vec<&str> = self.cmd.split(" ").collect();
let mut c = Command::new(cmd[0]);
if cmd.len() > 1 {
c.args(&cmd[1..]);
}
match c.output() {
Ok(out) => {
if out.status.success() {
let value = String::from_utf8(out.stdout).map_err(|e| format!("parsing output of {} {}", self.cmd, e))?;
self.value = Some(value);
self.refreshed = Instant::now();
Ok(self.ttl.clone())
} else {
let value = String::from_utf8(out.stderr).map_err(|e| format!("parsing error of {} {}", self.cmd, e))?;
Err(value)
}
}
Err(e) => {
Err(format!("[{}] {}", self.cmd, e))
}
}
}
}
}