mysqladm/client/commands.rs
1mod create_db;
2mod create_user;
3mod drop_db;
4mod drop_user;
5mod edit_db_privs;
6mod lock_user;
7mod passwd_user;
8mod show_db;
9mod show_db_privs;
10mod show_user;
11mod unlock_user;
12
13pub use create_db::*;
14pub use create_user::*;
15pub use drop_db::*;
16pub use drop_user::*;
17pub use edit_db_privs::*;
18pub use lock_user::*;
19pub use passwd_user::*;
20pub use show_db::*;
21pub use show_db_privs::*;
22pub use show_user::*;
23pub use unlock_user::*;
24
25use clap::Parser;
26
27use crate::core::protocol::{ClientToServerMessageStream, Response};
28
29#[derive(Parser, Debug, Clone)]
30pub enum ClientCommand {
31 /// Create one or more databases
32 #[command()]
33 CreateDb(CreateDbArgs),
34
35 /// Delete one or more databases
36 #[command()]
37 DropDb(DropDbArgs),
38
39 /// Print information about one or more databases
40 ///
41 /// If no database name is provided, all databases you have access will be shown.
42 #[command()]
43 ShowDb(ShowDbArgs),
44
45 /// Print user privileges for one or more databases
46 ///
47 /// If no database names are provided, all databases you have access to will be shown.
48 #[command()]
49 ShowDbPrivs(ShowDbPrivsArgs),
50
51 /// Change user privileges for one or more databases. See `edit-db-privs --help` for details.
52 ///
53 /// This command has two modes of operation:
54 ///
55 /// 1. Interactive mode: If nothing else is specified, the user will be prompted to edit the privileges using a text editor.
56 ///
57 /// You can configure your preferred text editor by setting the `VISUAL` or `EDITOR` environment variables.
58 ///
59 /// Follow the instructions inside the editor for more information.
60 ///
61 /// 2. Non-interactive mode: If the `-p` flag is specified, the user can write privileges using arguments.
62 ///
63 /// The privilege arguments should be formatted as `<db>:<user>+<privileges>-<privileges>`
64 /// where the privileges are a string of characters, each representing a single privilege.
65 /// The character `A` is an exception - it represents all privileges.
66 ///
67 /// The character-to-privilege mapping is defined as follows:
68 ///
69 /// - `s` - SELECT
70 /// - `i` - INSERT
71 /// - `u` - UPDATE
72 /// - `d` - DELETE
73 /// - `c` - CREATE
74 /// - `D` - DROP
75 /// - `a` - ALTER
76 /// - `I` - INDEX
77 /// - `t` - CREATE TEMPORARY TABLES
78 /// - `l` - LOCK TABLES
79 /// - `r` - REFERENCES
80 /// - `A` - ALL PRIVILEGES
81 ///
82 /// If you provide a database name, you can omit it from the privilege string,
83 /// e.g. `edit-db-privs my_db -p my_user+siu` is equivalent to `edit-db-privs -p my_db:my_user:siu`.
84 /// While it doesn't make much of a difference for a single edit, it can be useful for editing multiple users
85 /// on the same database at once.
86 ///
87 /// Example usage of non-interactive mode:
88 ///
89 /// Enable privileges `SELECT`, `INSERT`, and `UPDATE` for user `my_user` on database `my_db`:
90 ///
91 /// `mysqladm edit-db-privs -p my_db:my_user:siu`
92 ///
93 /// Enable all privileges for user `my_other_user` on database `my_other_db`:
94 ///
95 /// `mysqladm edit-db-privs -p my_other_db:my_other_user:A`
96 ///
97 /// Set miscellaneous privileges for multiple users on database `my_db`:
98 ///
99 /// `mysqladm edit-db-privs my_db -p my_user:siu my_other_user:ct``
100 ///
101 #[command(verbatim_doc_comment)]
102 EditDbPrivs(EditDbPrivsArgs),
103
104 /// Create one or more users
105 #[command()]
106 CreateUser(CreateUserArgs),
107
108 /// Delete one or more users
109 #[command()]
110 DropUser(DropUserArgs),
111
112 /// Change the MySQL password for a user
113 #[command()]
114 PasswdUser(PasswdUserArgs),
115
116 /// Print information about one or more users
117 ///
118 /// If no username is provided, all users you have access will be shown.
119 #[command()]
120 ShowUser(ShowUserArgs),
121
122 /// Lock account for one or more users
123 #[command()]
124 LockUser(LockUserArgs),
125
126 /// Unlock account for one or more users
127 #[command()]
128 UnlockUser(UnlockUserArgs),
129}
130
131pub async fn handle_command(
132 command: ClientCommand,
133 server_connection: ClientToServerMessageStream,
134) -> anyhow::Result<()> {
135 match command {
136 ClientCommand::CreateDb(args) => create_databases(args, server_connection).await,
137 ClientCommand::DropDb(args) => drop_databases(args, server_connection).await,
138 ClientCommand::ShowDb(args) => show_databases(args, server_connection).await,
139 ClientCommand::ShowDbPrivs(args) => show_database_privileges(args, server_connection).await,
140 ClientCommand::EditDbPrivs(args) => edit_database_privileges(args, server_connection).await,
141 ClientCommand::CreateUser(args) => create_users(args, server_connection).await,
142 ClientCommand::DropUser(args) => drop_users(args, server_connection).await,
143 ClientCommand::PasswdUser(args) => passwd_user(args, server_connection).await,
144 ClientCommand::ShowUser(args) => show_users(args, server_connection).await,
145 ClientCommand::LockUser(args) => lock_users(args, server_connection).await,
146 ClientCommand::UnlockUser(args) => unlock_users(args, server_connection).await,
147 }
148}
149
150pub fn erroneous_server_response(
151 response: Option<Result<Response, std::io::Error>>,
152) -> anyhow::Result<()> {
153 match response {
154 Some(Ok(Response::Error(e))) => {
155 anyhow::bail!("Server returned error: {}", e);
156 }
157 Some(Err(e)) => {
158 anyhow::bail!(e);
159 }
160 Some(response) => {
161 anyhow::bail!("Unexpected response from server: {:?}", response);
162 }
163 None => {
164 anyhow::bail!("No response from server");
165 }
166 }
167}