Skip to main content

rusty_commit/auth/
mod.rs

1pub mod codex_oauth;
2pub mod gitlab_oauth;
3pub mod oauth;
4pub mod token_storage;
5pub mod vercel_oauth;
6
7use crate::config::accounts::{AccountConfig, AuthMethod};
8use crate::config::Config;
9use anyhow::Result;
10
11/// Check if the user is authenticated with Claude
12#[allow(dead_code)]
13pub async fn is_authenticated(config: &Config) -> bool {
14    // Check for API key first (backward compatibility)
15    if config.api_key.is_some() {
16        return true;
17    }
18
19    // Check for OAuth tokens
20    token_storage::has_valid_token()
21}
22
23/// Get the authentication header value for API requests
24#[allow(dead_code)]
25pub async fn get_auth_header(config: &Config) -> Result<String> {
26    // Prefer OAuth token if available
27    if let Some(token) = token_storage::get_access_token()? {
28        return Ok(format!("Bearer {}", token));
29    }
30
31    // Fall back to API key
32    if let Some(api_key) = &config.api_key {
33        return Ok(api_key.clone());
34    }
35
36    anyhow::bail!("Not authenticated. Please run 'rco auth login' or set RCO_API_KEY")
37}
38
39// ============================================
40// Multi-account authentication support
41// ============================================
42
43/// Check if an account is authenticated
44#[allow(dead_code)]
45pub fn is_account_authenticated(account: &AccountConfig) -> bool {
46    match &account.auth {
47        AuthMethod::ApiKey { key_id } => {
48            // Check if we have the API key stored
49            token_storage::get_api_key_for_account(key_id)
50                .ok()
51                .flatten()
52                .is_some()
53        }
54        AuthMethod::OAuth {
55            provider: _,
56            account_id,
57        } => {
58            // Check if we have valid OAuth tokens
59            if let Ok(Some(tokens)) = token_storage::get_tokens_for_account(account_id) {
60                !tokens.is_expired()
61            } else {
62                false
63            }
64        }
65        AuthMethod::EnvVar { name } => {
66            // Check if environment variable is set
67            std::env::var(name).is_ok()
68        }
69        AuthMethod::Bearer { token_id } => {
70            // Check if bearer token exists
71            token_storage::get_bearer_token_for_account(token_id)
72                .ok()
73                .flatten()
74                .is_some()
75        }
76    }
77}
78
79/// Get authentication header for an account
80#[allow(dead_code)]
81pub fn get_account_auth_header(account: &AccountConfig) -> Result<String> {
82    match &account.auth {
83        AuthMethod::ApiKey { key_id } => {
84            if let Some(api_key) = token_storage::get_api_key_for_account(key_id)? {
85                Ok(api_key)
86            } else {
87                // Try to get from environment
88                if let Ok(key_from_env) =
89                    std::env::var(format!("RCO_API_KEY_{}", key_id.to_uppercase()))
90                {
91                    return Ok(key_from_env);
92                }
93                anyhow::bail!(
94                    "API key not found for account '{}'. Run: rco config add-provider --alias {}",
95                    account.alias,
96                    account.alias
97                )
98            }
99        }
100        AuthMethod::OAuth {
101            provider: _,
102            account_id,
103        } => {
104            if let Ok(Some(tokens)) = token_storage::get_tokens_for_account(account_id) {
105                Ok(format!("Bearer {}", tokens.access_token))
106            } else {
107                anyhow::bail!(
108                    "OAuth tokens not found for account '{}'. Please re-authenticate.",
109                    account.alias
110                )
111            }
112        }
113        AuthMethod::EnvVar { name } => {
114            if let Ok(value) = std::env::var(name) {
115                Ok(value)
116            } else {
117                anyhow::bail!(
118                    "Environment variable '{}' not set for account '{}'",
119                    name,
120                    account.alias
121                )
122            }
123        }
124        AuthMethod::Bearer { token_id } => {
125            if let Some(token) = token_storage::get_bearer_token_for_account(token_id)? {
126                Ok(format!("Bearer {}", token))
127            } else {
128                anyhow::bail!("Bearer token not found for account '{}'", account.alias)
129            }
130        }
131    }
132}
133
134/// Get provider-specific auth requirements for an account
135#[allow(dead_code)]
136pub fn get_account_auth_provider(account: &AccountConfig) -> Option<&str> {
137    match &account.auth {
138        AuthMethod::OAuth { provider, .. } => Some(provider),
139        _ => None,
140    }
141}