use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum AuthMethod {
None,
Basic { username: String, password: String },
Bearer { token: String },
ApiKey {
key: String,
header_name: Option<String>,
query_param: Option<String>,
},
OAuth2 {
client_id: String,
client_secret: Option<String>,
access_token: Option<String>,
refresh_token: Option<String>,
token_url: String,
scopes: Vec<String>,
expires_at: Option<DateTime<Utc>>,
grant_type: OAuth2GrantType,
},
SshKey {
username: String,
private_key_path: String,
passphrase: Option<String>,
},
SshPassword { username: String, password: String },
MutualTls {
cert_path: String,
key_path: String,
ca_path: Option<String>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum OAuth2GrantType {
AuthorizationCode,
ClientCredentials,
RefreshToken,
DeviceCode,
}
impl AuthMethod {
pub fn has_expiry(&self) -> bool {
matches!(self, AuthMethod::OAuth2 { .. })
}
pub fn is_expired(&self) -> bool {
match self {
AuthMethod::OAuth2 { expires_at, .. } => {
expires_at.map_or(false, |exp| exp < Utc::now())
}
_ => false,
}
}
pub fn needs_refresh(&self) -> bool {
match self {
AuthMethod::OAuth2 {
expires_at,
refresh_token,
..
} => {
refresh_token.is_some()
&& expires_at.map_or(false, |exp| {
exp - chrono::Duration::minutes(5) < Utc::now()
})
}
_ => false,
}
}
pub fn method_name(&self) -> &'static str {
match self {
AuthMethod::None => "none",
AuthMethod::Basic { .. } => "basic",
AuthMethod::Bearer { .. } => "bearer",
AuthMethod::ApiKey { .. } => "api_key",
AuthMethod::OAuth2 { .. } => "oauth2",
AuthMethod::SshKey { .. } => "ssh_key",
AuthMethod::SshPassword { .. } => "ssh_password",
AuthMethod::MutualTls { .. } => "mtls",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredCredential {
pub id: uuid::Uuid,
pub name: String,
pub auth: AuthMethod,
pub created_at: DateTime<Utc>,
pub last_rotated: Option<DateTime<Utc>>,
pub tags: Vec<String>,
}