use anyhow::{Context, Result};
use chrono::{DateTime, Utc};
use clap::{Args, Subcommand};
use comfy_table::{ContentArrangement, Table};
use ironflow_sdk::IronflowClient;
use ironflow_sdk::client::ListApprovalDelegationsFilter;
use ironflow_sdk::types::{ApprovalDelegationResponse, CreateApprovalDelegationRequest};
use uuid::Uuid;
use crate::confirm::confirm;
use crate::output;
#[derive(Debug, Args)]
pub struct DelegationArgs {
#[command(subcommand)]
pub command: DelegationCommands,
}
#[derive(Debug, Subcommand)]
pub enum DelegationCommands {
List {
#[arg(long)]
from_user: Option<Uuid>,
#[arg(long)]
to_user: Option<Uuid>,
#[arg(long)]
page: Option<u32>,
#[arg(long)]
per_page: Option<u32>,
},
Create {
to_user: Uuid,
#[arg(long)]
until: String,
#[arg(long)]
from: Option<String>,
#[arg(long)]
workflow: Option<String>,
},
Delete {
id: Uuid,
#[arg(long)]
yes: bool,
},
}
fn parse_timestamp(raw: &str, flag: &str) -> Result<DateTime<Utc>> {
DateTime::parse_from_rfc3339(raw)
.map(|d| d.with_timezone(&Utc))
.with_context(|| format!("--{flag} must be an RFC 3339 timestamp, got '{raw}'"))
}
fn delegations_table(items: &[ApprovalDelegationResponse]) -> Table {
let mut table = Table::new();
table.set_content_arrangement(ContentArrangement::Dynamic);
table.set_header(vec![
"ID",
"FROM",
"TO",
"FROM DATE",
"UNTIL",
"WORKFLOW FILTER",
]);
for d in items {
let filter = d.workflow_filter.as_deref().unwrap_or("-");
table.add_row(vec![
d.id.to_string(),
d.from_user_id.to_string(),
d.to_user_id.to_string(),
d.valid_from.to_string(),
d.valid_until.to_string(),
filter.to_string(),
]);
}
table
}
pub async fn execute(
client: &IronflowClient,
args: &DelegationArgs,
json_mode: bool,
) -> Result<()> {
match &args.command {
DelegationCommands::List {
from_user,
to_user,
page,
per_page,
} => {
let filter = ListApprovalDelegationsFilter {
from_user_id: *from_user,
to_user_id: *to_user,
page: *page,
per_page: *per_page,
};
let response = client.list_approval_delegations_filtered(&filter).await?;
output::print_output(json_mode, &response, || delegations_table(&response.data))
}
DelegationCommands::Create {
to_user,
until,
from,
workflow,
} => {
let valid_until = parse_timestamp(until, "until")?;
let valid_from = from
.as_deref()
.map(|raw| parse_timestamp(raw, "from"))
.transpose()?;
let response = client
.create_approval_delegation(&CreateApprovalDelegationRequest {
to_user_id: *to_user,
valid_from,
valid_until,
workflow_filter: workflow.clone(),
})
.await?;
if json_mode {
output::print_json(&response)?;
} else {
println!("Delegation {} created", response.data.id);
}
Ok(())
}
DelegationCommands::Delete { id, yes } => {
let prompt = format!("Revoke delegation {id}?");
confirm(&prompt, *yes)?;
client.delete_approval_delegation(*id).await?;
output::report_deletion(json_mode, "delegation", id.to_string())
}
}
}