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> {
31 let output = crate::subprocess::git_command(&["config", "--global", "--get", key])
32 .output()
33 .map_err(|e| DiagnosticError::ExecutionFailed(e.to_string()))?;
34
35 if output.status.success() {
36 Ok(String::from_utf8(output.stdout)
37 .ok()
38 .map(|s| s.trim().to_string()))
39 } else {
40 Ok(None)
41 }
42 }
43}
44
45impl CryptoDiagnosticProvider for PosixDiagnosticAdapter {
46 fn check_ssh_keygen_available(&self) -> Result<CheckResult, DiagnosticError> {
47 let output = Command::new("ssh-keygen")
49 .arg("-?")
50 .stderr(std::process::Stdio::piped())
51 .stdout(std::process::Stdio::piped())
52 .output();
53 let (passed, message) = match output {
54 Ok(out) if !out.stderr.is_empty() || !out.stdout.is_empty() => {
55 (true, Some("ssh-keygen found on PATH".to_string()))
56 }
57 Ok(_) => (true, Some("ssh-keygen found on PATH".to_string())),
58 Err(_) => {
59 let hint = ssh_install_hint();
60 (false, Some(format!("ssh-keygen not found on PATH. {hint}")))
61 }
62 };
63 Ok(CheckResult {
64 name: "ssh-keygen installed".to_string(),
65 passed,
66 message,
67 config_issues: vec![],
68 category: CheckCategory::Advisory,
69 })
70 }
71
72 fn check_ssh_version(&self) -> Result<String, DiagnosticError> {
73 let output = Command::new("ssh")
75 .arg("-V")
76 .stderr(std::process::Stdio::piped())
77 .stdout(std::process::Stdio::piped())
78 .output()
79 .map_err(|e| DiagnosticError::ExecutionFailed(format!("ssh -V failed: {e}")))?;
80
81 let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
82 if !stderr.is_empty() {
83 return Ok(stderr);
84 }
85 let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
86 if !stdout.is_empty() {
87 return Ok(stdout);
88 }
89 Ok("unknown".to_string())
90 }
91}
92
93fn ssh_install_hint() -> &'static str {
95 if cfg!(target_os = "macos") {
96 "ssh-keygen is normally pre-installed on macOS. Check your PATH."
97 } else if cfg!(target_os = "windows") {
98 "Install OpenSSH via Settings > Apps > Optional features, or `winget install Microsoft.OpenSSH.Client`."
99 } else {
100 "Install OpenSSH: `sudo apt install openssh-client` (Debian/Ubuntu) or `sudo dnf install openssh-clients` (Fedora/RHEL)."
101 }
102}