Skip to main content

clickup_cli/commands/
user.rs

1use clap::Subcommand;
2use crate::client::ClickUpClient;
3use crate::commands::auth::resolve_token;
4use crate::commands::workspace::resolve_workspace;
5use crate::error::CliError;
6use crate::output::OutputConfig;
7use crate::Cli;
8
9#[derive(Subcommand)]
10pub enum UserCommands {
11    /// Invite a user to the workspace
12    Invite {
13        /// Email address
14        #[arg(long)]
15        email: String,
16        /// Grant admin role
17        #[arg(long)]
18        admin: bool,
19        /// Custom role ID
20        #[arg(long)]
21        custom_role_id: Option<String>,
22    },
23    /// Get a workspace member by user ID
24    Get {
25        /// User ID
26        id: String,
27    },
28    /// Update a workspace member
29    Update {
30        /// User ID
31        id: String,
32        /// New username
33        #[arg(long)]
34        username: Option<String>,
35        /// Set admin role
36        #[arg(long)]
37        admin: Option<bool>,
38        /// Custom role ID
39        #[arg(long)]
40        custom_role_id: Option<String>,
41    },
42    /// Remove a user from the workspace
43    Remove {
44        /// User ID
45        id: String,
46    },
47}
48
49const USER_FIELDS: &[&str] = &["id", "username", "email", "role"];
50
51pub async fn execute(command: UserCommands, cli: &Cli) -> Result<(), CliError> {
52    let token = resolve_token(cli)?;
53    let client = ClickUpClient::new(&token, cli.timeout)?;
54    let output = OutputConfig::from_cli(&cli.output, &cli.fields, cli.no_header, cli.quiet);
55    let ws_id = resolve_workspace(cli)?;
56
57    match command {
58        UserCommands::Invite {
59            email,
60            admin,
61            custom_role_id,
62        } => {
63            let mut body = serde_json::json!({
64                "email": email,
65                "admin": admin,
66            });
67            if let Some(r) = custom_role_id {
68                body["custom_role_id"] = serde_json::Value::String(r);
69            }
70            let resp = client
71                .post(&format!("/v2/team/{}/user", ws_id), &body)
72                .await?;
73            let member = resp.get("member").cloned().unwrap_or(resp);
74            let user = member.get("user").cloned().unwrap_or(member);
75            output.print_single(&user, USER_FIELDS, "id");
76            Ok(())
77        }
78        UserCommands::Get { id } => {
79            let resp = client
80                .get(&format!("/v2/team/{}/user/{}", ws_id, id))
81                .await?;
82            let member = resp.get("member").cloned().unwrap_or(resp);
83            let user = member.get("user").cloned().unwrap_or(member);
84            output.print_single(&user, USER_FIELDS, "id");
85            Ok(())
86        }
87        UserCommands::Update {
88            id,
89            username,
90            admin,
91            custom_role_id,
92        } => {
93            let mut body = serde_json::Map::new();
94            if let Some(u) = username {
95                body.insert("username".into(), serde_json::Value::String(u));
96            }
97            if let Some(a) = admin {
98                body.insert("admin".into(), serde_json::Value::Bool(a));
99            }
100            if let Some(r) = custom_role_id {
101                body.insert("custom_role_id".into(), serde_json::Value::String(r));
102            }
103            let resp = client
104                .put(
105                    &format!("/v2/team/{}/user/{}", ws_id, id),
106                    &serde_json::Value::Object(body),
107                )
108                .await?;
109            let member = resp.get("member").cloned().unwrap_or(resp);
110            let user = member.get("user").cloned().unwrap_or(member);
111            output.print_single(&user, USER_FIELDS, "id");
112            Ok(())
113        }
114        UserCommands::Remove { id } => {
115            client
116                .delete(&format!("/v2/team/{}/user/{}", ws_id, id))
117                .await?;
118            output.print_message(&format!("User {} removed from workspace", id));
119            Ok(())
120        }
121    }
122}