Skip to main content

crates_docs/cli/
list_api_keys_cmd.rs

1//! List API keys command implementation
2
3use crate::config::AppConfig;
4use std::path::Path;
5
6/// List API keys from configuration file.
7///
8/// Reads the configuration file and displays all configured API key hashes.
9/// This helps operators audit which keys are currently active.
10///
11/// # Errors
12///
13/// Returns an error if the configuration file cannot be read or parsed.
14pub fn run_list_api_keys_command(config_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
15    // Check if config file exists
16    if !config_path.exists() {
17        eprintln!("Configuration file not found: {}", config_path.display());
18        eprintln!("No API keys are configured.");
19        return Ok(());
20    }
21
22    // Load configuration
23    let config = AppConfig::from_file(config_path).map_err(|e| {
24        format!(
25            "Failed to load configuration from {}: {}",
26            config_path.display(),
27            e
28        )
29    })?;
30
31    println!("API Key Configuration");
32    println!("=====================");
33    println!();
34
35    if !config.auth.api_key.enabled {
36        println!("Status: DISABLED");
37        println!();
38        println!("API key authentication is not enabled.");
39        println!("Set enabled = true in [api_key] section to enable.");
40        return Ok(());
41    }
42
43    println!("Status: ENABLED");
44    println!();
45
46    if config.auth.api_key.keys.is_empty() {
47        println!("No API keys configured.");
48        println!("Use 'crates-docs generate-api-key' to create a new key.");
49    } else {
50        println!("Configured API keys ({}):", config.auth.api_key.keys.len());
51        println!();
52
53        for (index, key_hash) in config.auth.api_key.keys.iter().enumerate() {
54            let key_type = if key_hash.starts_with("legacy:") {
55                "Legacy Hash"
56            } else if key_hash.starts_with("$argon2") {
57                "Argon2 Hash"
58            } else {
59                "Plaintext (Insecure)"
60            };
61
62            println!("  [{}] {}", index + 1, key_type);
63
64            // Show a truncated version of the hash for identification
65            let display_hash = if key_hash.len() > 60 {
66                format!("{}...{}", &key_hash[..30], &key_hash[key_hash.len() - 20..])
67            } else {
68                key_hash.clone()
69            };
70            println!("      {display_hash}");
71            println!();
72        }
73
74        println!("Configuration:");
75        println!("  Header name: {}", config.auth.api_key.header_name);
76        println!("  Query param: {}", config.auth.api_key.query_param_name);
77        println!(
78            "  Allow query param: {}",
79            config.auth.api_key.allow_query_param
80        );
81        println!("  Key prefix: {}", config.auth.api_key.key_prefix);
82    }
83
84    println!();
85    println!("File: {}", config_path.display());
86
87    Ok(())
88}