Skip to main content

codewhale_config/
auth_source.rs

1use anyhow::{Result, bail};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
5#[serde(rename_all = "snake_case")]
6pub enum AuthSourceKind {
7    Command,
8    Secret,
9}
10
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(deny_unknown_fields)]
13pub struct ProviderAuthSourceToml {
14    #[serde(alias = "type")]
15    pub source: AuthSourceKind,
16    #[serde(default, skip_serializing_if = "Vec::is_empty")]
17    pub command: Vec<String>,
18    #[serde(default, skip_serializing_if = "Option::is_none")]
19    pub timeout_ms: Option<u64>,
20    #[serde(default, skip_serializing_if = "Option::is_none")]
21    pub secret_id: Option<String>,
22}
23
24impl ProviderAuthSourceToml {
25    pub fn validate(&self) -> Result<()> {
26        match self.source {
27            AuthSourceKind::Command => {
28                if self.command.is_empty() || self.command.iter().all(|part| part.trim().is_empty())
29                {
30                    bail!(
31                        "provider auth source command must include at least one non-empty argv item"
32                    );
33                }
34            }
35            AuthSourceKind::Secret => {
36                if self
37                    .secret_id
38                    .as_deref()
39                    .is_none_or(|secret_id| secret_id.trim().is_empty())
40                {
41                    bail!("provider auth source secret must include secret_id");
42                }
43            }
44        }
45        Ok(())
46    }
47
48    #[must_use]
49    pub fn source_class(&self) -> &'static str {
50        match self.source {
51            AuthSourceKind::Command => "command",
52            AuthSourceKind::Secret => "secret",
53        }
54    }
55}