use crate::core::service::ServiceError;
use std::env;
use std::path::PathBuf;
#[async_trait::async_trait]
pub trait Auth: Send + Sync {
fn get_auth_header(&self) -> Result<String, ServiceError>;
fn is_configured(&self) -> bool;
}
pub struct GitHubPat {
token: Option<String>,
env_var: String,
}
impl GitHubPat {
pub fn new(env_var: String) -> Self {
let token = env::var(&env_var).ok();
Self { token, env_var }
}
}
#[async_trait::async_trait]
impl Auth for GitHubPat {
fn get_auth_header(&self) -> Result<String, ServiceError> {
let token = self.token.as_ref().ok_or_else(|| {
ServiceError::Custom(format!(
"GitHub token not found. Set {} environment variable",
self.env_var
))
})?;
Ok(format!("token {}", token))
}
fn is_configured(&self) -> bool {
self.token.is_some() || env::var(&self.env_var).is_ok()
}
}
pub struct SshKey {
key_path: PathBuf,
}
impl SshKey {
pub fn new(key_path: PathBuf) -> Self {
Self { key_path }
}
}
#[async_trait::async_trait]
impl Auth for SshKey {
fn get_auth_header(&self) -> Result<String, ServiceError> {
Err(ServiceError::Custom(
"SSH authentication is handled by git operations, not HTTP headers".to_string(),
))
}
fn is_configured(&self) -> bool {
self.key_path.exists()
}
}
pub struct ApiKey {
key: Option<String>,
env_var: String,
}
impl ApiKey {
pub fn new(env_var: String) -> Self {
let key = env::var(&env_var).ok();
Self { key, env_var }
}
}
#[async_trait::async_trait]
impl Auth for ApiKey {
fn get_auth_header(&self) -> Result<String, ServiceError> {
let key = if let Some(ref k) = self.key {
k.as_str()
} else if let Ok(k) = env::var(&self.env_var) {
return Ok(format!("Bearer {}", k));
} else {
return Err(ServiceError::Custom(format!(
"API key not found. Set {} environment variable",
self.env_var
)));
};
Ok(format!("Bearer {}", key))
}
fn is_configured(&self) -> bool {
self.key.is_some() || env::var(&self.env_var).is_ok()
}
}