Skip to main content

wekan_cli/commands/
integrations.rs

1mod activities;
2mod create;
3mod delete;
4mod get;
5mod inbound_email;
6mod list;
7#[cfg(test)]
8mod tests;
9mod update;
10
11use crate::{
12    client::WekanClientFactory,
13    command_result::CommandSuccess,
14    credentials::{CredentialStore, SecretInputProvider},
15    error::{AppError, ErrorCode},
16    exit_code::StableExitCode,
17    input::ConfirmationProvider,
18};
19use clap::{Args, Subcommand};
20
21#[derive(Debug, Args)]
22pub struct IntegrationArgs {
23    #[command(subcommand)]
24    pub command: IntegrationCommand,
25}
26
27#[derive(Debug, Subcommand)]
28pub enum IntegrationCommand {
29    InboundEmail(inbound_email::InboundEmailArgs),
30    /// List a board's webhook integrations.
31    List(list::ListArgs),
32    /// Show an integration and its activity subscriptions; tokens are excluded.
33    Get(get::GetArgs),
34    /// Create an outgoing webhook using Wekan's defaults.
35    Create(create::CreateArgs),
36    /// Update integration fields; omitted fields stay unchanged.
37    Update(update::UpdateArgs),
38    /// Delete an integration, with confirmation or --yes.
39    Delete(delete::DeleteArgs),
40    /// Add or remove webhook activity subscriptions.
41    Activity(activities::ActivityArgs),
42}
43
44pub(crate) async fn dispatch(
45    command: IntegrationCommand,
46    factory: &WekanClientFactory,
47    store: &dyn CredentialStore,
48    secrets: &dyn SecretInputProvider,
49    confirmation: &dyn ConfirmationProvider,
50) -> Result<CommandSuccess, AppError> {
51    match command {
52        IntegrationCommand::InboundEmail(args) => {
53            inbound_email::dispatch(args.command, factory, secrets).await
54        }
55        IntegrationCommand::List(args) => list::execute(args, factory, store).await,
56        IntegrationCommand::Get(args) => get::execute(args, factory, store).await,
57        IntegrationCommand::Create(args) => create::execute(args, factory, store).await,
58        IntegrationCommand::Update(args) => update::execute(args, factory, store, secrets).await,
59        IntegrationCommand::Delete(args) => {
60            delete::execute(args, factory, store, confirmation).await
61        }
62        IntegrationCommand::Activity(args) => {
63            activities::dispatch(args.command, factory, store).await
64        }
65    }
66}
67
68#[derive(Debug, Args)]
69struct Target {
70    /// Wekan integration ID.
71    #[arg(value_parser = identifier, help_heading = "Target")]
72    integration_id: String,
73    /// Wekan board ID.
74    #[arg(long = "board", value_parser = identifier, help_heading = "Target")]
75    board_id: String,
76}
77
78fn identifier(value: &str) -> Result<String, String> {
79    let value = value.trim();
80    if value.is_empty() || matches!(value, "." | "..") {
81        Err("ID must not be empty, whitespace, or dot-only".to_owned())
82    } else {
83        Ok(value.to_owned())
84    }
85}
86
87fn missing_integration() -> AppError {
88    AppError::new(
89        ErrorCode::NotFound,
90        "the integration was not found on that Wekan board",
91        StableExitCode::Server,
92    )
93    .with_details(crate::commands::client_error::response_error_details(
94        reqwest::StatusCode::OK,
95        None,
96    ))
97}