Skip to main content

wekan_cli/commands/
users.rs

1mod boards;
2mod cards;
3mod create;
4mod current;
5mod delete;
6mod disable_login;
7mod enable_login;
8mod get;
9mod list;
10mod take_ownership;
11
12#[cfg(test)]
13mod tests;
14
15use clap::{Args, Subcommand};
16
17use crate::{
18    client::{UserRecord, WekanClientFactory},
19    command_result::{
20        CommandSuccess, UserBoardMembership, UserDetail, UserEmail, UserOrganization, UserTeam,
21    },
22    credentials::{CredentialStore, SecretInputProvider},
23    error::AppError,
24    input::ConfirmationProvider,
25};
26
27use super::client_error::map_client_error;
28
29#[derive(Debug, Args)]
30pub struct UserArgs {
31    #[command(subcommand)]
32    pub command: UserCommand,
33}
34
35#[derive(Debug, Subcommand)]
36pub enum UserCommand {
37    /// Show the currently authenticated Wekan user.
38    Current(current::CurrentArgs),
39
40    /// List cards related to the currently authenticated user.
41    Cards(cards::CardsArgs),
42
43    /// List Wekan users (site admin only).
44    List(list::ListArgs),
45
46    /// Show a Wekan user by ID or username (site admin only).
47    Get(get::GetArgs),
48
49    /// Create a Wekan user (site admin only).
50    Create(create::CreateArgs),
51
52    /// List active boards visible for a user ID.
53    Boards(boards::BoardsArgs),
54
55    /// Transfer boards administered by a user to the current user.
56    TakeOwnership(take_ownership::TakeOwnershipArgs),
57
58    /// Disable a user's login and clear their sessions.
59    DisableLogin(disable_login::DisableLoginArgs),
60
61    /// Re-enable a user's login.
62    EnableLogin(enable_login::EnableLoginArgs),
63
64    /// Delete a Wekan user.
65    Delete(delete::DeleteArgs),
66}
67
68impl UserCommand {
69    pub(crate) fn validate(&self) -> Result<(), AppError> {
70        if let Self::Cards(args) = self {
71            cards::validate_range(args.from.as_deref(), args.to.as_deref())?;
72        }
73        Ok(())
74    }
75}
76
77pub(crate) async fn dispatch(
78    command: UserCommand,
79    client_factory: &WekanClientFactory,
80    credential_store: &dyn CredentialStore,
81    secret_input: &dyn SecretInputProvider,
82    confirmation: &dyn ConfirmationProvider,
83) -> Result<CommandSuccess, AppError> {
84    match command {
85        UserCommand::Current(args) => {
86            current::execute(args, client_factory, credential_store).await
87        }
88        UserCommand::Cards(args) => cards::execute(args, client_factory, credential_store).await,
89        UserCommand::List(args) => list::execute(args, client_factory, credential_store).await,
90        UserCommand::Get(args) => get::execute(args, client_factory, credential_store).await,
91        UserCommand::Create(args) => {
92            create::execute(args, client_factory, credential_store, secret_input).await
93        }
94        UserCommand::Boards(args) => boards::execute(args, client_factory, credential_store).await,
95        UserCommand::TakeOwnership(args) => {
96            take_ownership::execute(args, client_factory, credential_store, confirmation).await
97        }
98        UserCommand::DisableLogin(args) => {
99            disable_login::execute(args, client_factory, credential_store, confirmation).await
100        }
101        UserCommand::EnableLogin(args) => {
102            enable_login::execute(args, client_factory, credential_store).await
103        }
104        UserCommand::Delete(args) => {
105            delete::execute(args, client_factory, credential_store, confirmation).await
106        }
107    }
108}
109
110fn user_detail(user: UserRecord) -> UserDetail {
111    UserDetail {
112        user_id: user.user_id,
113        username: user.username,
114        full_name: user.profile.fullname,
115        emails: user
116            .emails
117            .into_iter()
118            .map(|email| UserEmail {
119                address: email.address,
120                verified: email.verified,
121            })
122            .collect(),
123        is_admin: user.is_admin,
124        login_disabled: user.login_disabled,
125        authentication_method: user.authentication_method,
126        created_at: user.created_at,
127        modified_at: user.modified_at,
128        last_connection_date: user.last_connection_date,
129        organizations: user
130            .orgs
131            .into_iter()
132            .map(|organization| UserOrganization {
133                organization_id: organization.org_id,
134                display_name: organization.org_display_name,
135                is_admin: organization.is_admin,
136            })
137            .collect(),
138        teams: user
139            .teams
140            .into_iter()
141            .map(|team| UserTeam {
142                team_id: team.team_id,
143                display_name: team.team_display_name,
144            })
145            .collect(),
146        boards: user
147            .boards
148            .into_iter()
149            .map(|board| UserBoardMembership {
150                board_id: board.board_id,
151                is_active: board.is_active,
152                is_admin: board.is_admin,
153                is_no_comments: board.is_no_comments,
154                is_comment_only: board.is_comment_only,
155                is_worker: board.is_worker,
156                is_normal_assigned_only: board.is_normal_assigned_only,
157                is_comment_assigned_only: board.is_comment_assigned_only,
158                is_read_only: board.is_read_only,
159                is_read_assigned_only: board.is_read_assigned_only,
160            })
161            .collect(),
162    }
163}
164
165fn non_empty(value: &str) -> Result<String, String> {
166    if value.is_empty() {
167        Err("value must not be empty".to_owned())
168    } else {
169        Ok(value.to_owned())
170    }
171}