auths_cli/adapters/
system_diagnostic.rs1use auths_sdk::ports::diagnostics::{
4 CheckCategory, CheckResult, CryptoDiagnosticProvider, DiagnosticError, GitDiagnosticProvider,
5};
6use std::process::Command;
7
8pub struct PosixDiagnosticAdapter;
10
11impl GitDiagnosticProvider for PosixDiagnosticAdapter {
12 fn check_git_version(&self) -> Result<CheckResult, DiagnosticError> {
13 let output = crate::subprocess::git_command(&["--version"]).output();
14 let (passed, message) = match output {
15 Ok(out) if out.status.success() => {
16 let version = String::from_utf8_lossy(&out.stdout).trim().to_string();
17 (true, Some(version))
18 }
19 _ => (false, Some("git command not found on PATH".to_string())),
20 };
21 Ok(CheckResult {
22 name: "Git installed".to_string(),
23 passed,
24 message,
25 config_issues: vec![],
26 category: CheckCategory::Advisory,
27 })
28 }
29
30 fn get_git_config(&self, key: &str) -> Result<Option<String>, DiagnosticError> {
37 let output = crate::subprocess::git_command(&["config", "--get", key])
38 .output()
39 .map_err(|e| DiagnosticError::ExecutionFailed(e.to_string()))?;
40
41 if output.status.success() {
42 Ok(String::from_utf8(output.stdout)
43 .ok()
44 .map(|s| s.trim().to_string()))
45 } else {
46 Ok(None)
47 }
48 }
49}
50
51impl CryptoDiagnosticProvider for PosixDiagnosticAdapter {
52 fn check_ssh_keygen_available(&self) -> Result<CheckResult, DiagnosticError> {
53 let output = Command::new("ssh-keygen")
55 .arg("-?")
56 .stderr(std::process::Stdio::piped())
57 .stdout(std::process::Stdio::piped())
58 .output();
59 let (passed, message) = match output {
60 Ok(out) if !out.stderr.is_empty() || !out.stdout.is_empty() => {
61 (true, Some("ssh-keygen found on PATH".to_string()))
62 }
63 Ok(_) => (true, Some("ssh-keygen found on PATH".to_string())),
64 Err(_) => {
65 let hint = ssh_install_hint();
66 (false, Some(format!("ssh-keygen not found on PATH. {hint}")))
67 }
68 };
69 Ok(CheckResult {
70 name: "ssh-keygen installed".to_string(),
71 passed,
72 message,
73 config_issues: vec![],
74 category: CheckCategory::Advisory,
75 })
76 }
77
78 fn check_ssh_version(&self) -> Result<String, DiagnosticError> {
79 let output = Command::new("ssh")
81 .arg("-V")
82 .stderr(std::process::Stdio::piped())
83 .stdout(std::process::Stdio::piped())
84 .output()
85 .map_err(|e| DiagnosticError::ExecutionFailed(format!("ssh -V failed: {e}")))?;
86
87 let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
88 if !stderr.is_empty() {
89 return Ok(stderr);
90 }
91 let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
92 if !stdout.is_empty() {
93 return Ok(stdout);
94 }
95 Ok("unknown".to_string())
96 }
97}
98
99fn ssh_install_hint() -> &'static str {
101 if cfg!(target_os = "macos") {
102 "ssh-keygen is normally pre-installed on macOS. Check your PATH."
103 } else if cfg!(target_os = "windows") {
104 "Install OpenSSH via Settings > Apps > Optional features, or `winget install Microsoft.OpenSSH.Client`."
105 } else {
106 "Install OpenSSH: `sudo apt install openssh-client` (Debian/Ubuntu) or `sudo dnf install openssh-clients` (Fedora/RHEL)."
107 }
108}