wiremux_auth/providers/
static_token.rs1use crate::TokenProvider;
4use crate::error::AuthError;
5
6#[derive(Clone)]
8pub struct StaticToken {
9 key: String,
10}
11
12impl std::fmt::Debug for StaticToken {
13 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14 f.debug_struct("StaticToken")
15 .field("key", &"[REDACTED]")
16 .finish()
17 }
18}
19
20impl StaticToken {
21 #[must_use]
23 pub fn new(key: impl Into<String>) -> Self {
24 Self { key: key.into() }
25 }
26
27 pub fn from_env(var: &str) -> Result<Self, AuthError> {
29 let missing = || AuthError::MissingField(format!("env `{var}`"));
30 let value = std::env::var(var).map_err(|_| missing())?;
31 if value.trim().is_empty() {
32 return Err(missing());
33 }
34 Ok(Self::new(value))
35 }
36}
37
38impl TokenProvider for StaticToken {
39 async fn get_token(&self) -> Result<String, AuthError> {
40 Ok(self.key.clone())
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use crate::isolated_home::IsolatedHome;
48
49 #[tokio::test]
50 async fn static_token_returns_key() {
51 let provider = StaticToken::new("sk-test-key");
52 assert_eq!(provider.get_token().await.unwrap(), "sk-test-key");
53 }
54
55 #[tokio::test]
56 async fn static_wake_is_noop() {
57 let provider = StaticToken::new("sk-test-key");
58 provider.wake();
59 assert_eq!(provider.get_token().await.unwrap(), "sk-test-key");
60 }
61
62 #[test]
63 fn debug_redacts_key() {
64 let provider = StaticToken::new("sk-secret-123");
65 let debug = format!("{provider:?}");
66 assert!(!debug.contains("sk-secret"));
67 assert!(debug.contains("[REDACTED]"));
68 }
69
70 #[tokio::test]
71 async fn from_env_reads_set_var() {
72 let home = IsolatedHome::with_extra_envs(&["WIREMUX_TEST_STATIC_KEY"]);
73 home.set_env("WIREMUX_TEST_STATIC_KEY", "sk-static-issue59");
74 let token = StaticToken::from_env("WIREMUX_TEST_STATIC_KEY").expect("set key");
75 assert_eq!(
76 token.get_token().await.expect("static key"),
77 "sk-static-issue59"
78 );
79 let debug = format!("{token:?}");
80 assert!(debug.contains("[REDACTED]"), "{debug}");
81 assert!(!debug.contains("sk-static-issue59"), "{debug}");
82 let _ = home;
83 }
84
85 #[test]
86 fn from_env_missing_var_is_error() {
87 let home = IsolatedHome::with_extra_envs(&["WIREMUX_TEST_STATIC_KEY"]);
88 let err = StaticToken::from_env("WIREMUX_TEST_STATIC_KEY").expect_err("missing");
89 match err {
90 AuthError::MissingField(name) => {
91 assert!(
92 name.contains("WIREMUX_TEST_STATIC_KEY") && name.contains("env"),
93 "MissingField must name the env var, got {name}"
94 );
95 }
96 other => panic!("expected MissingField, got {other}"),
97 }
98 let _ = home;
99 }
100
101 #[test]
102 fn from_env_whitespace_only_is_error() {
103 let home = IsolatedHome::with_extra_envs(&["WIREMUX_TEST_STATIC_KEY"]);
104 home.set_env("WIREMUX_TEST_STATIC_KEY", " \t");
105 let err = StaticToken::from_env("WIREMUX_TEST_STATIC_KEY").expect_err("whitespace");
106 match err {
107 AuthError::MissingField(name) => {
108 assert!(
109 name.contains("WIREMUX_TEST_STATIC_KEY") && name.contains("env"),
110 "MissingField must name the env var, got {name}"
111 );
112 }
113 other => panic!("expected MissingField, got {other}"),
114 }
115 let _ = home;
116 }
117}