grm/
auth.rs

1use std::process;
2
3use thiserror::Error;
4
5#[derive(Clone)]
6pub struct AuthToken(String);
7
8#[derive(Error, Debug)]
9pub enum Error {
10    #[error("token command failed: {0}")]
11    TokenCommandInvocationFailed(#[from] std::io::Error),
12
13    #[error("token command failed: {0}")]
14    TokenCommandInvocationInvalidUtf8(#[from] std::string::FromUtf8Error),
15
16    #[error("token command failed, stderr: {0}")]
17    TokenCommandFailed(String),
18
19    #[error("token command produced stderr: {0}")]
20    TokenCommandStderr(String),
21
22    #[error("token command output empty")]
23    TokenCommandEmptyOutput,
24
25    #[error("token command output did not contain any newline")]
26    TokenCommandNoNewlineInOutput,
27}
28
29impl AuthToken {
30    pub fn access(&self) -> &str {
31        &self.0
32    }
33}
34
35pub fn get_token_from_command(command: &str) -> Result<AuthToken, Error> {
36    let output = process::Command::new("/usr/bin/env")
37        .arg("sh")
38        .arg("-c")
39        .arg(command)
40        .output()?;
41
42    let stderr = String::from_utf8(output.stderr)?;
43    let stdout = String::from_utf8(output.stdout)?;
44
45    if !output.status.success() {
46        return Err(Error::TokenCommandFailed(stderr));
47    }
48
49    if !stderr.is_empty() {
50        return Err(Error::TokenCommandStderr(stderr));
51    }
52
53    if stdout.is_empty() {
54        return Err(Error::TokenCommandEmptyOutput);
55    }
56
57    let token = stdout
58        .split('\n')
59        .next()
60        .ok_or(Error::TokenCommandNoNewlineInOutput)?;
61
62    Ok(AuthToken(token.to_owned()))
63}