Skip to main content

deslicer_cli/ci/
local.rs

1use super::{OidcError, OidcTokenProvider};
2
3pub struct LocalProvider;
4
5#[async_trait::async_trait]
6impl OidcTokenProvider for LocalProvider {
7    async fn fetch_token(&self, _audience: &str) -> Result<String, OidcError> {
8        let token = std::env::var("DESLICER_DEV_TOKEN").map_err(|_| {
9            OidcError::MissingEnv(
10                "DESLICER_DEV_TOKEN (set DESLICER_DEV_TOKEN to a pre-issued local-dev token)"
11                    .to_string(),
12            )
13        })?;
14        Ok(token.trim().to_string())
15    }
16}
17
18#[cfg(test)]
19// ENV_LOCK only serializes env access across single-threaded #[tokio::test] cases;
20// holding it across the await is safe (no cross-task contention).
21#[allow(clippy::await_holding_lock)]
22mod tests {
23    use super::*;
24    use std::sync::Mutex;
25
26    static ENV_LOCK: Mutex<()> = Mutex::new(());
27
28    #[tokio::test]
29    async fn fetch_token_returns_trimmed_env_value() {
30        let _guard = ENV_LOCK.lock().unwrap();
31
32        std::env::set_var("DESLICER_DEV_TOKEN", "  local-dev-token  ");
33
34        let token = LocalProvider
35            .fetch_token("https://api.deslicer.ai")
36            .await
37            .unwrap();
38
39        assert_eq!(token, "local-dev-token");
40
41        std::env::remove_var("DESLICER_DEV_TOKEN");
42    }
43
44    #[tokio::test]
45    async fn fetch_token_errors_when_env_missing() {
46        let _guard = ENV_LOCK.lock().unwrap();
47
48        std::env::remove_var("DESLICER_DEV_TOKEN");
49
50        let err = LocalProvider
51            .fetch_token("https://api.deslicer.ai")
52            .await
53            .unwrap_err();
54
55        match err {
56            OidcError::MissingEnv(msg) => {
57                assert!(msg.contains("DESLICER_DEV_TOKEN"));
58                assert!(msg.contains("pre-issued local-dev token"));
59            }
60            other => panic!("expected MissingEnv, got {other:?}"),
61        }
62    }
63}