ironflow_cli/commands/
delegation.rs1use anyhow::{Context, Result};
4use chrono::{DateTime, Utc};
5use clap::{Args, Subcommand};
6use comfy_table::{ContentArrangement, Table};
7use ironflow_sdk::IronflowClient;
8use ironflow_sdk::client::ListApprovalDelegationsFilter;
9use ironflow_sdk::types::{ApprovalDelegationResponse, CreateApprovalDelegationRequest};
10use uuid::Uuid;
11
12use crate::confirm::confirm;
13use crate::output;
14
15#[derive(Debug, Args)]
17pub struct DelegationArgs {
18 #[command(subcommand)]
20 pub command: DelegationCommands,
21}
22
23#[derive(Debug, Subcommand)]
25pub enum DelegationCommands {
26 List {
28 #[arg(long)]
30 from_user: Option<Uuid>,
31 #[arg(long)]
33 to_user: Option<Uuid>,
34 #[arg(long)]
36 page: Option<u32>,
37 #[arg(long)]
39 per_page: Option<u32>,
40 },
41 Create {
43 to_user: Uuid,
45 #[arg(long)]
47 until: String,
48 #[arg(long)]
50 from: Option<String>,
51 #[arg(long)]
53 workflow: Option<String>,
54 },
55 Delete {
57 id: Uuid,
59 #[arg(long)]
61 yes: bool,
62 },
63}
64
65fn parse_timestamp(raw: &str, flag: &str) -> Result<DateTime<Utc>> {
67 DateTime::parse_from_rfc3339(raw)
68 .map(|d| d.with_timezone(&Utc))
69 .with_context(|| format!("--{flag} must be an RFC 3339 timestamp, got '{raw}'"))
70}
71
72fn delegations_table(items: &[ApprovalDelegationResponse]) -> Table {
73 let mut table = Table::new();
74 table.set_content_arrangement(ContentArrangement::Dynamic);
75 table.set_header(vec![
76 "ID",
77 "FROM",
78 "TO",
79 "FROM DATE",
80 "UNTIL",
81 "WORKFLOW FILTER",
82 ]);
83 for d in items {
84 let filter = d.workflow_filter.as_deref().unwrap_or("-");
85 table.add_row(vec![
86 d.id.to_string(),
87 d.from_user_id.to_string(),
88 d.to_user_id.to_string(),
89 d.valid_from.to_string(),
90 d.valid_until.to_string(),
91 filter.to_string(),
92 ]);
93 }
94 table
95}
96
97pub async fn execute(
104 client: &IronflowClient,
105 args: &DelegationArgs,
106 json_mode: bool,
107) -> Result<()> {
108 match &args.command {
109 DelegationCommands::List {
110 from_user,
111 to_user,
112 page,
113 per_page,
114 } => {
115 let filter = ListApprovalDelegationsFilter {
116 from_user_id: *from_user,
117 to_user_id: *to_user,
118 page: *page,
119 per_page: *per_page,
120 };
121 let response = client.list_approval_delegations_filtered(&filter).await?;
122 output::print_output(json_mode, &response, || delegations_table(&response.data))
123 }
124 DelegationCommands::Create {
125 to_user,
126 until,
127 from,
128 workflow,
129 } => {
130 let valid_until = parse_timestamp(until, "until")?;
131 let valid_from = from
132 .as_deref()
133 .map(|raw| parse_timestamp(raw, "from"))
134 .transpose()?;
135 let response = client
136 .create_approval_delegation(&CreateApprovalDelegationRequest {
137 to_user_id: *to_user,
138 valid_from,
139 valid_until,
140 workflow_filter: workflow.clone(),
141 })
142 .await?;
143 if json_mode {
144 output::print_json(&response)?;
145 } else {
146 println!("Delegation {} created", response.data.id);
147 }
148 Ok(())
149 }
150 DelegationCommands::Delete { id, yes } => {
151 let prompt = format!("Revoke delegation {id}?");
152 confirm(&prompt, *yes)?;
153 client.delete_approval_delegation(*id).await?;
154 output::report_deletion(json_mode, "delegation", id.to_string())
155 }
156 }
157}