use anyhow::{Context, Result};
use crate::cli::GlobalFlags;
use crate::credentials::{AuthMethod, CredentialStore};
use crate::defaults::LOCAL_SERVE_URL;
const API_KEY_ENV: &str = "BOXLITE_API_KEY";
enum Source {
EnvApiKey,
File { path_display: String },
}
struct Identity {
url: String,
source: Source,
method: Option<AuthMethod>,
expires_at: Option<chrono::DateTime<chrono::Utc>>,
}
pub fn run(global: &GlobalFlags, store: &CredentialStore) -> Result<()> {
let profile_name = global.resolved_profile();
let identity = match resolve_identity(global, store)? {
Some(id) => id,
None => {
println!("Not logged in (profile `{}`).", profile_name);
return Ok(());
}
};
let source_label = match identity.source {
Source::EnvApiKey => format!("{} env var", API_KEY_ENV),
Source::File { path_display } => format!("{} [{}]", path_display, profile_name),
};
println!("Logged in to: {}", identity.url);
let credential_label = match identity.method {
Some(AuthMethod::Oidc) => "OIDC bearer token",
Some(AuthMethod::ApiKey) | None => "API key",
};
println!(
"Credential: {} (from {})",
credential_label, source_label
);
if let Some(exp) = identity.expires_at {
println!("Expires: {}", exp.to_rfc3339());
}
Ok(())
}
fn resolve_identity(global: &GlobalFlags, store: &CredentialStore) -> Result<Option<Identity>> {
let profile_name = global.resolved_profile();
if let Ok(api_key) = std::env::var(API_KEY_ENV)
&& !api_key.is_empty()
{
let stored_url = store.load_named(&profile_name)?.map(|profile| profile.url);
let url = global
.url
.clone()
.filter(|url| !url.is_empty())
.or(stored_url)
.unwrap_or_else(|| LOCAL_SERVE_URL.to_string());
return Ok(Some(Identity {
url,
source: Source::EnvApiKey,
method: None,
expires_at: None,
}));
}
let profile = store
.load_named(&profile_name)
.context("loading stored credentials")?;
let Some(profile) = profile else {
return Ok(None);
};
let path = store.path().context("resolving credentials path")?;
Ok(Some(Identity {
url: global
.url
.clone()
.filter(|url| !url.is_empty())
.unwrap_or(profile.url),
source: Source::File {
path_display: path.display().to_string(),
},
method: Some(profile.auth_method),
expires_at: profile.expires_at,
}))
}