1
use anyhow::Context;
2
use clap::Parser;
3
use futures_util::SinkExt;
4
use tokio_stream::StreamExt;
5

            
6
use crate::{
7
    client::commands::erroneous_server_response,
8
    core::{
9
        protocol::{ClientToServerMessageStream, Request, Response},
10
        types::MySQLUser,
11
    },
12
};
13

            
14
#[derive(Parser, Debug, Clone)]
15
pub struct ShowUserArgs {
16
    #[arg(num_args = 0..)]
17
    username: Vec<MySQLUser>,
18

            
19
    /// Print the information as JSON
20
    #[arg(short, long)]
21
    json: bool,
22
}
23

            
24
pub async fn show_users(
25
    args: ShowUserArgs,
26
    mut server_connection: ClientToServerMessageStream,
27
) -> anyhow::Result<()> {
28
    let message = if args.username.is_empty() {
29
        Request::ListUsers(None)
30
    } else {
31
        Request::ListUsers(Some(args.username.to_owned()))
32
    };
33

            
34
    if let Err(err) = server_connection.send(message).await {
35
        server_connection.close().await.ok();
36
        anyhow::bail!(err);
37
    }
38

            
39
    let users = match server_connection.next().await {
40
        Some(Ok(Response::ListUsers(users))) => users
41
            .into_iter()
42
            .filter_map(|(username, result)| match result {
43
                Ok(user) => Some(user),
44
                Err(err) => {
45
                    eprintln!("{}", err.to_error_message(&username));
46
                    eprintln!("Skipping...");
47
                    None
48
                }
49
            })
50
            .collect::<Vec<_>>(),
51
        Some(Ok(Response::ListAllUsers(users))) => match users {
52
            Ok(users) => users,
53
            Err(err) => {
54
                server_connection.send(Request::Exit).await?;
55
                return Err(
56
                    anyhow::anyhow!(err.to_error_message()).context("Failed to list all users")
57
                );
58
            }
59
        },
60
        response => return erroneous_server_response(response),
61
    };
62

            
63
    server_connection.send(Request::Exit).await?;
64

            
65
    if args.json {
66
        println!(
67
            "{}",
68
            serde_json::to_string_pretty(&users).context("Failed to serialize users to JSON")?
69
        );
70
    } else if users.is_empty() {
71
        println!("No users to show.");
72
    } else {
73
        let mut table = prettytable::Table::new();
74
        table.add_row(row![
75
            "User",
76
            "Password is set",
77
            "Locked",
78
            "Databases where user has privileges"
79
        ]);
80
        for user in users {
81
            table.add_row(row![
82
                user.user,
83
                user.has_password,
84
                user.is_locked,
85
                user.databases.join("\n")
86
            ]);
87
        }
88
        table.printstd();
89
    }
90

            
91
    Ok(())
92
}