Skip to main content

clickup_cli/commands/
audit_log.rs

1use crate::client::ClickUpClient;
2use crate::commands::auth::resolve_token;
3use crate::commands::workspace::resolve_workspace;
4use crate::error::CliError;
5use crate::output::OutputConfig;
6use crate::Cli;
7use clap::Subcommand;
8
9#[derive(Subcommand)]
10pub enum AuditLogCommands {
11    /// Query audit logs (Enterprise only, v3)
12    Query {
13        /// Event type: AUTH, CUSTOM_FIELDS, HIERARCHY, USER, AGENT, OTHER
14        #[arg(long)]
15        r#type: String,
16        /// Filter by user ID
17        #[arg(long)]
18        user_id: Option<String>,
19        /// Start date (Unix timestamp in milliseconds)
20        #[arg(long)]
21        start_date: Option<i64>,
22        /// End date (Unix timestamp in milliseconds)
23        #[arg(long)]
24        end_date: Option<i64>,
25    },
26}
27
28const AUDIT_LOG_FIELDS: &[&str] = &["id", "type", "user_id", "date"];
29
30pub async fn execute(command: AuditLogCommands, cli: &Cli) -> Result<(), CliError> {
31    let token = resolve_token(cli)?;
32    let client = ClickUpClient::new(&token, cli.timeout)?;
33    let output = OutputConfig::from_cli(&cli.output, &cli.fields, cli.no_header, cli.quiet);
34
35    match command {
36        AuditLogCommands::Query {
37            r#type,
38            user_id,
39            start_date,
40            end_date,
41        } => {
42            let team_id = resolve_workspace(cli)?;
43            let mut body = serde_json::json!({ "type": r#type });
44            if let Some(uid) = user_id {
45                body["user_id"] = serde_json::Value::String(uid);
46            }
47            if start_date.is_some() || end_date.is_some() {
48                let mut date_filter = serde_json::Map::new();
49                if let Some(s) = start_date {
50                    date_filter.insert("start_date".into(), serde_json::Value::Number(s.into()));
51                }
52                if let Some(e) = end_date {
53                    date_filter.insert("end_date".into(), serde_json::Value::Number(e.into()));
54                }
55                body["date_filter"] = serde_json::Value::Object(date_filter);
56            }
57            let resp = client
58                .post(&format!("/v3/workspaces/{}/auditlogs", team_id), &body)
59                .await?;
60
61            if cli.output == "json" {
62                println!("{}", serde_json::to_string_pretty(&resp).unwrap());
63                return Ok(());
64            }
65
66            let logs = resp
67                .get("data")
68                .and_then(|d| d.as_array())
69                .or_else(|| resp.get("audit_logs").and_then(|d| d.as_array()))
70                .cloned()
71                .unwrap_or_default();
72            output.print_items(&logs, AUDIT_LOG_FIELDS, "id");
73            Ok(())
74        }
75    }
76}