Skip to main content

wekan_cli/commands/
integrations.rs

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