use vta_sdk::credentials::CredentialBundle;
use vta_sdk::session::{SessionStore, TokenStatus};
pub use vta_sdk::session::SessionInfo;
const SERVICE_NAME: &str = "cnm-cli";
const LEGACY_KEYRING_KEY: &str = "session";
fn store() -> SessionStore {
SessionStore::new(
SERVICE_NAME,
crate::config::config_dir().expect("could not determine config directory"),
)
}
pub fn has_legacy_session() -> bool {
store().has_session(LEGACY_KEYRING_KEY)
}
pub async fn login(
credential: &CredentialBundle,
base_url: &str,
keyring_key: &str,
) -> Result<(), Box<dyn std::error::Error>> {
#[cfg(all(feature = "config-session", not(feature = "keyring")))]
eprintln!(
"Warning: sessions are stored unprotected on disk (~/.config/cnm/sessions.json).\n \
Do not use config-session in production."
);
let result = store().login(credential, base_url, keyring_key).await?;
println!("Credential imported:");
println!(" Client DID: {}", result.client_did);
println!(
" VTA DID: {}",
result.vta_did.as_deref().unwrap_or("(unset)")
);
println!("\nAuthentication successful.");
Ok(())
}
pub fn store_session_direct(
keyring_key: &str,
did: &str,
private_key: &str,
vta_did: &str,
) -> Result<(), Box<dyn std::error::Error>> {
store().store_direct(keyring_key, did, private_key, vta_did)
}
pub fn logout(keyring_key: &str) {
store().logout(keyring_key);
println!("Logged out. Credentials and tokens removed.");
}
pub fn loaded_session(keyring_key: &str) -> Option<SessionInfo> {
store().loaded_session(keyring_key)
}
pub fn status(keyring_key: &str) {
match store().session_status(keyring_key) {
Some(status) => {
println!("Client DID: {}", status.client_did);
println!(
"VTA DID: {}",
status.vta_did.as_deref().unwrap_or("(pending setup)")
);
match status.token_status {
TokenStatus::Valid { expires_in_secs } => {
println!("Token: valid (expires in {expires_in_secs}s)");
}
TokenStatus::Expired => {
println!("Token: expired");
}
TokenStatus::None => {
println!("Token: none (will authenticate on next request)");
}
}
}
None => {
println!("Not authenticated.");
println!(
"\nTo authenticate, import a sealed credential bundle from your VTA administrator:"
);
println!(" cnm auth login --credential-bundle <bundle.armored>");
println!(" [--expect-digest <sha256-hex>] # recommended; OOB-supplied digest");
}
}
}
pub async fn ensure_authenticated(
base_url: &str,
keyring_key: &str,
) -> Result<String, Box<dyn std::error::Error>> {
store().ensure_authenticated(base_url, keyring_key).await
}
pub async fn connect(
url_override: Option<&str>,
keyring_key: &str,
) -> Result<vta_sdk::client::VtaClient, Box<dyn std::error::Error>> {
store().connect(keyring_key, url_override).await
}