auths_cli/commands/
whoami.rs1use anyhow::{Result, anyhow};
2use auths_sdk::ports::IdentityStorage;
3use auths_sdk::storage::RegistryIdentityStorage;
4use auths_sdk::storage_layout as layout;
5use clap::Parser;
6use serde::Serialize;
7
8use crate::config::CliConfig;
9use crate::ux::format::{JsonResponse, Output, is_json_mode};
10
11#[derive(Parser, Debug, Clone)]
13#[command(
14 name = "whoami",
15 about = "Show the current identity on this machine",
16 after_help = "Examples:
17 auths whoami # Show the current identity
18 auths whoami --json # JSON output
19
20Related:
21 auths status — Show full identity and device status
22 auths init — Initialize a new identity"
23)]
24pub struct WhoamiCommand {}
25
26#[derive(Debug, Serialize)]
27struct WhoamiResponse {
28 identity_did: String,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 label: Option<String>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 device_did: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none")]
36 public_key_hex: Option<String>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 curve: Option<String>,
39}
40
41fn current_key_hex(repo_path: &std::path::Path, did: &str) -> Option<(String, String)> {
44 let registry = auths_sdk::storage::GitRegistryBackend::from_config_unchecked(
45 auths_sdk::storage::RegistryConfig::single_tenant(repo_path),
46 );
47 let (pk, curve) = auths_sdk::keri::resolve_current_public_key(®istry, did).ok()?;
48 Some((hex::encode(pk), format!("{curve:?}").to_lowercase()))
49}
50
51fn local_device_did(repo_path: &std::path::Path) -> Option<String> {
53 let env_config = auths_sdk::core_config::EnvironmentConfig::from_env();
54 let ctx = crate::factories::storage::build_auths_context(repo_path, &env_config, None).ok()?;
55 auths_sdk::domains::identity::local::resolve_local_signer(&ctx)
56 .ok()
57 .map(|signer| signer.signer_did.to_string())
58}
59
60pub fn handle_whoami(_cmd: WhoamiCommand, repo: Option<std::path::PathBuf>) -> Result<()> {
61 let repo_path = layout::resolve_repo_path(repo).map_err(|e| anyhow!(e))?;
62
63 if crate::factories::storage::open_git_repo(&repo_path).is_err() {
64 if is_json_mode() {
65 JsonResponse::<()>::error(
66 "whoami",
67 "No identity found. Run `auths init` to get started.",
68 )
69 .print()?;
70 } else {
71 let out = Output::new();
72 out.print_error("No identity found. Run `auths init` to get started.");
73 }
74 return Ok(());
75 }
76
77 let storage = RegistryIdentityStorage::new(&repo_path);
78 match storage.load_identity() {
79 Ok(identity) => {
80 let identity_did = identity.controller_did.to_string();
81 let key = current_key_hex(&repo_path, &identity_did);
82 let response = WhoamiResponse {
83 identity_did,
84 label: None,
85 device_did: local_device_did(&repo_path),
86 public_key_hex: key.as_ref().map(|(hex, _)| hex.clone()),
87 curve: key.as_ref().map(|(_, curve)| curve.clone()),
88 };
89
90 if is_json_mode() {
91 JsonResponse::success("whoami", &response).print()?;
92 } else {
93 let out = Output::new();
94 out.println(&format!("Identity: {}", out.info(&response.identity_did)));
95 if let Some(ref device) = response.device_did {
96 out.println(&format!("Device: {}", out.dim(device)));
97 }
98 }
99 }
100 Err(_) => {
101 if is_json_mode() {
102 JsonResponse::<()>::error(
103 "whoami",
104 "No identity found. Run `auths init` to get started.",
105 )
106 .print()?;
107 } else {
108 let out = Output::new();
109 out.print_error("No identity found. Run `auths init` to get started.");
110 }
111 }
112 }
113
114 Ok(())
115}
116
117impl crate::commands::executable::ExecutableCommand for WhoamiCommand {
118 fn execute(&self, ctx: &CliConfig) -> Result<()> {
119 handle_whoami(self.clone(), ctx.repo_path.clone())
120 }
121}