Skip to main content

wekan_cli/commands/admin/
teams.rs

1use super::features::{FeatureChanges, UpdateAllArgs, confirm_bulk, identifier};
2use crate::{
3    client::WekanClientFactory,
4    command_result::*,
5    commands::{authenticated::AuthenticatedContext, client_error::map_client_error},
6    credentials::CredentialStore,
7    error::AppError,
8    input::ConfirmationProvider,
9    redaction::Redactor,
10};
11use clap::{Args, Subcommand};
12
13#[derive(Debug, Args)]
14pub struct TeamArgs {
15    #[command(subcommand)]
16    pub command: TeamCommand,
17}
18#[derive(Debug, Subcommand)]
19pub enum TeamCommand {
20    /// List identifying fields and the three feature flags (site admin).
21    List,
22    /// Update native feature flags on one or all teams.
23    Features(FeaturesArgs),
24}
25#[derive(Debug, Args)]
26pub struct FeaturesArgs {
27    #[command(subcommand)]
28    pub command: FeaturesCommand,
29}
30#[derive(Debug, Subcommand)]
31pub enum FeaturesCommand {
32    /// Update at least one feature on a single team; omitted flags are preserved.
33    Update(UpdateArgs),
34    /// Change one feature across every team, with confirmation or --yes.
35    UpdateAll(UpdateAllArgs),
36}
37#[derive(Debug, Args)]
38pub struct UpdateArgs {
39    /// Wekan team ID.
40    #[arg(long = "team", value_parser = identifier)]
41    id: String,
42    #[command(flatten)]
43    changes: FeatureChanges,
44}
45
46pub(super) async fn execute(
47    command: TeamCommand,
48    factory: &WekanClientFactory,
49    store: &dyn CredentialStore,
50    confirmation: &dyn ConfirmationProvider,
51) -> Result<CommandSuccess, AppError> {
52    let context = AuthenticatedContext::load(factory, store)?;
53    let redactor = Redactor::with_secret(context.record().token());
54    match command {
55        TeamCommand::List => {
56            let teams = context
57                .client()
58                .admin_teams(context.record().token())
59                .await
60                .map_err(|e| map_client_error(e, &redactor, "admin team list", false))?;
61            Ok(CommandSuccess::AdminTeams(AdminTeamCollectionSuccess {
62                teams,
63            }))
64        }
65        TeamCommand::Features(args) => match args.command {
66            FeaturesCommand::Update(args) => {
67                let team = context
68                    .client()
69                    .update_team_features(
70                        &args.id,
71                        &args.changes.team_request(),
72                        context.record().token(),
73                    )
74                    .await
75                    .map_err(|e| {
76                        map_client_error(e, &redactor, "admin team features update", true)
77                    })?;
78                Ok(CommandSuccess::AdminTeamUpdated(Box::new(
79                    AdminTeamUpdateSuccess {
80                        team,
81                        submitted_fields: args.changes.submitted_fields(),
82                    },
83                )))
84            }
85            FeaturesCommand::UpdateAll(args) => {
86                let operation = DestructiveOperation::AdminTeamFeaturesUpdateAll;
87                let Some(guard) = confirm_bulk(&args, confirmation, &context, store, operation)?
88                else {
89                    return Ok(CommandSuccess::Cancelled(CancellationSuccess::new(
90                        operation,
91                    )));
92                };
93                let field = args.field.into();
94                let result = context
95                    .client()
96                    .update_all_team_features(field, args.value, context.record().token())
97                    .await;
98                drop(guard);
99                let response = result.map_err(|e| {
100                    map_client_error(e, &redactor, "admin team features update-all", true)
101                })?;
102                Ok(CommandSuccess::AdminTeamFeaturesUpdatedAll(
103                    AdminFeaturesUpdateAllSuccess {
104                        field,
105                        value: args.value,
106                        updated: response.updated,
107                    },
108                ))
109            }
110        },
111    }
112}