Skip to main content

fastskill_core/core/registry/
auth.rs

1//! Authentication for registry access
2
3use crate::core::service::ServiceError;
4use std::env;
5use std::path::PathBuf;
6
7/// Authentication trait for registry access
8#[async_trait::async_trait]
9pub trait Auth: Send + Sync {
10    /// Get authentication header value
11    fn get_auth_header(&self) -> Result<String, ServiceError>;
12
13    /// Check if authentication is configured
14    fn is_configured(&self) -> bool;
15}
16
17/// GitHub Personal Access Token authentication
18pub struct GitHubPat {
19    token: Option<String>,
20    env_var: String,
21}
22
23impl GitHubPat {
24    pub fn new(env_var: String) -> Self {
25        let token = env::var(&env_var).ok();
26        Self { token, env_var }
27    }
28}
29
30#[async_trait::async_trait]
31impl Auth for GitHubPat {
32    fn get_auth_header(&self) -> Result<String, ServiceError> {
33        let token = self.token.as_ref().ok_or_else(|| {
34            ServiceError::Custom(format!(
35                "GitHub token not found. Set {} environment variable",
36                self.env_var
37            ))
38        })?;
39        Ok(format!("token {}", token))
40    }
41
42    fn is_configured(&self) -> bool {
43        self.token.is_some() || env::var(&self.env_var).is_ok()
44    }
45}
46
47/// SSH key authentication
48pub struct SshKey {
49    key_path: PathBuf,
50}
51
52impl SshKey {
53    pub fn new(key_path: PathBuf) -> Self {
54        Self { key_path }
55    }
56}
57
58#[async_trait::async_trait]
59impl Auth for SshKey {
60    fn get_auth_header(&self) -> Result<String, ServiceError> {
61        // SSH keys are used for git operations, not HTTP headers
62        // This is a placeholder - actual SSH auth is handled by git2
63        Err(ServiceError::Custom(
64            "SSH authentication is handled by git operations, not HTTP headers".to_string(),
65        ))
66    }
67
68    fn is_configured(&self) -> bool {
69        self.key_path.exists()
70    }
71}
72
73/// API key authentication
74pub struct ApiKey {
75    key: Option<String>,
76    env_var: String,
77}
78
79impl ApiKey {
80    pub fn new(env_var: String) -> Self {
81        let key = env::var(&env_var).ok();
82        Self { key, env_var }
83    }
84}
85
86#[async_trait::async_trait]
87impl Auth for ApiKey {
88    fn get_auth_header(&self) -> Result<String, ServiceError> {
89        let key = if let Some(ref k) = self.key {
90            k.as_str()
91        } else if let Ok(k) = env::var(&self.env_var) {
92            // Store in self for future use (but we can't mutate, so just use the value)
93            return Ok(format!("Bearer {}", k));
94        } else {
95            return Err(ServiceError::Custom(format!(
96                "API key not found. Set {} environment variable",
97                self.env_var
98            )));
99        };
100        Ok(format!("Bearer {}", key))
101    }
102
103    fn is_configured(&self) -> bool {
104        self.key.is_some() || env::var(&self.env_var).is_ok()
105    }
106}