use agent_first_data::value_source::SecretString;
use agent_first_data::{SourceSet, ValueSource};
use crate::shared::error::{Error, ErrorCode};
const CONTAINER: &str = "container";
pub fn set() -> SourceSet {
SourceSet::config().host_scheme(CONTAINER, "container:NAME")
}
pub fn parse(raw: &str) -> Result<ValueSource, Error> {
set().parse(raw).map_err(|error| {
Error::new(
ErrorCode::InvalidArgument,
format!("--token-secret {error}"),
)
})
}
pub fn read(source: &ValueSource) -> Result<SecretString, Error> {
match source {
ValueSource::Host { scheme, value } if scheme == CONTAINER => {
crate::cli::cmd::container::read_host_token(value)
}
other => other.read_secret().map_err(|error| {
Error::new(
ErrorCode::InvalidArgument,
format!("--token-secret {error}"),
)
}),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_container_scheme_is_afhttps_and_the_rest_is_afdatas() {
assert_eq!(
parse("container:afhttp-host").expect("container"),
ValueSource::Host {
scheme: CONTAINER.to_string(),
value: "afhttp-host".to_string(),
}
);
assert_eq!(
parse("env:AFHTTP_TOKEN_SECRET").expect("env"),
ValueSource::Env("AFHTTP_TOKEN_SECRET".to_string())
);
assert_eq!(
parse("t0ken").expect("bare"),
ValueSource::Literal("t0ken".to_string())
);
assert_eq!(
parse("literal:container:x").expect("escape hatch"),
ValueSource::Literal("container:x".to_string())
);
}
#[test]
fn a_token_does_not_come_from_a_stream() {
for raw in ["stdin", "fd:3", "prompt"] {
let error = parse(raw).expect_err(raw);
assert_eq!(error.error_code, ErrorCode::InvalidArgument, "{raw}");
assert!(error.detail.starts_with("--token-secret"), "{raw}");
}
}
#[test]
fn an_unreadable_source_names_the_flag_and_not_the_value() {
let error = read(&ValueSource::Env("AFHTTP_TEST_ABSENT_TOKEN".to_string()))
.expect_err("unset env source");
assert!(
error.detail.starts_with("--token-secret"),
"{}",
error.detail
);
assert!(
error.detail.contains("AFHTTP_TEST_ABSENT_TOKEN"),
"{}",
error.detail
);
}
}