Skip to main content

dsc/commands/
api_key.rs

1use crate::api::DiscourseClient;
2use crate::cli::ListFormat;
3use crate::commands::common::{ensure_api_credentials, select_discourse};
4use crate::config::Config;
5use anyhow::Result;
6
7pub fn api_key_list(config: &Config, discourse_name: &str, format: ListFormat) -> Result<()> {
8    let discourse = select_discourse(config, Some(discourse_name))?;
9    ensure_api_credentials(discourse)?;
10    let client = DiscourseClient::new(discourse)?;
11    let keys = client.list_api_keys()?;
12
13    match format {
14        ListFormat::Text => {
15            if keys.is_empty() {
16                println!("No API keys found.");
17                return Ok(());
18            }
19            let desc_width = keys
20                .iter()
21                .map(|k| k.description.as_deref().unwrap_or("-").len())
22                .max()
23                .unwrap_or(0)
24                .max(11);
25            for k in &keys {
26                let desc = k.description.as_deref().unwrap_or("-");
27                let user = k.username.as_deref().unwrap_or("(all-users)");
28                let last = k.last_used_at.as_deref().unwrap_or("never");
29                let status = if k.revoked_at.is_some() {
30                    "revoked"
31                } else {
32                    "active"
33                };
34                println!(
35                    "id:{:<5} {:<width$}  user:{:<20}  last:{:<25}  {}",
36                    k.id,
37                    desc,
38                    user,
39                    last,
40                    status,
41                    width = desc_width
42                );
43            }
44        }
45        ListFormat::Json => println!("{}", serde_json::to_string_pretty(&keys)?),
46        ListFormat::Yaml => println!("{}", serde_yaml::to_string(&keys)?),
47    }
48    Ok(())
49}
50
51pub fn api_key_create(
52    config: &Config,
53    discourse_name: &str,
54    description: &str,
55    username: Option<&str>,
56    format: ListFormat,
57    dry_run: bool,
58) -> Result<()> {
59    let discourse = select_discourse(config, Some(discourse_name))?;
60    ensure_api_credentials(discourse)?;
61    let client = DiscourseClient::new(discourse)?;
62
63    if dry_run {
64        println!(
65            "[dry-run] {}: would create api key \"{}\" for user {}",
66            discourse.name,
67            description,
68            username.unwrap_or("(all-users)")
69        );
70        return Ok(());
71    }
72
73    let created = client.create_api_key(description, username)?;
74
75    match format {
76        ListFormat::Text => {
77            println!("New API key (shown only this once — copy it now):");
78            println!();
79            println!("  {}", created.key);
80            println!();
81            println!("id:          {}", created.id);
82            if let Some(d) = &created.description {
83                println!("description: {}", d);
84            }
85            println!(
86                "username:    {}",
87                created.username.as_deref().unwrap_or("(all-users)")
88            );
89            if let Some(c) = &created.created_at {
90                println!("created_at:  {}", c);
91            }
92        }
93        ListFormat::Json => println!("{}", serde_json::to_string_pretty(&created)?),
94        ListFormat::Yaml => println!("{}", serde_yaml::to_string(&created)?),
95    }
96    Ok(())
97}
98
99pub fn api_key_revoke(
100    config: &Config,
101    discourse_name: &str,
102    key_id: u64,
103    dry_run: bool,
104) -> Result<()> {
105    let discourse = select_discourse(config, Some(discourse_name))?;
106    ensure_api_credentials(discourse)?;
107    let client = DiscourseClient::new(discourse)?;
108
109    if dry_run {
110        println!(
111            "[dry-run] {}: would revoke api key id:{}",
112            discourse.name, key_id
113        );
114        return Ok(());
115    }
116
117    client.revoke_api_key(key_id)?;
118    println!("Revoked api key id:{}", key_id);
119    Ok(())
120}