1
use clap::Parser;
2
use futures_util::SinkExt;
3
use prettytable::{Cell, Row, Table};
4
use tokio_stream::StreamExt;
5

            
6
use crate::{
7
    client::commands::erroneous_server_response,
8
    core::{
9
        common::yn,
10
        database_privileges::{DATABASE_PRIVILEGE_FIELDS, db_priv_field_human_readable_name},
11
        protocol::{ClientToServerMessageStream, Request, Response},
12
        types::MySQLDatabase,
13
    },
14
};
15

            
16
#[derive(Parser, Debug, Clone)]
17
pub struct ShowPrivsArgs {
18
    /// The name of the database(s) to show
19
    #[arg(num_args = 0..)]
20
    name: Vec<MySQLDatabase>,
21

            
22
    /// Print the information as JSON
23
    #[arg(short, long)]
24
    json: bool,
25
}
26

            
27
pub async fn show_database_privileges(
28
    args: ShowPrivsArgs,
29
    mut server_connection: ClientToServerMessageStream,
30
) -> anyhow::Result<()> {
31
    let message = if args.name.is_empty() {
32
        Request::ListPrivileges(None)
33
    } else {
34
        Request::ListPrivileges(Some(args.name.to_owned()))
35
    };
36
    server_connection.send(message).await?;
37

            
38
    let privilege_data = match server_connection.next().await {
39
        Some(Ok(Response::ListPrivileges(databases))) => databases
40
            .into_iter()
41
            .filter_map(|(database_name, result)| match result {
42
                Ok(privileges) => Some(privileges),
43
                Err(err) => {
44
                    eprintln!("{}", err.to_error_message(&database_name));
45
                    eprintln!("Skipping...");
46
                    println!();
47
                    None
48
                }
49
            })
50
            .flatten()
51
            .collect::<Vec<_>>(),
52
        Some(Ok(Response::ListAllPrivileges(privilege_rows))) => match privilege_rows {
53
            Ok(list) => list,
54
            Err(err) => {
55
                server_connection.send(Request::Exit).await?;
56
                return Err(anyhow::anyhow!(err.to_error_message())
57
                    .context("Failed to list database privileges"));
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!("{}", serde_json::to_string_pretty(&privilege_data)?);
67
    } else if privilege_data.is_empty() {
68
        println!("No database privileges to show.");
69
    } else {
70
        let mut table = Table::new();
71
        table.add_row(Row::new(
72
            DATABASE_PRIVILEGE_FIELDS
73
                .into_iter()
74
                .map(db_priv_field_human_readable_name)
75
                .map(|name| Cell::new(&name))
76
                .collect(),
77
        ));
78

            
79
        for row in privilege_data {
80
            table.add_row(row![
81
                row.db,
82
                row.user,
83
                c->yn(row.select_priv),
84
                c->yn(row.insert_priv),
85
                c->yn(row.update_priv),
86
                c->yn(row.delete_priv),
87
                c->yn(row.create_priv),
88
                c->yn(row.drop_priv),
89
                c->yn(row.alter_priv),
90
                c->yn(row.index_priv),
91
                c->yn(row.create_tmp_table_priv),
92
                c->yn(row.lock_tables_priv),
93
                c->yn(row.references_priv),
94
            ]);
95
        }
96
        table.printstd();
97
    }
98

            
99
    Ok(())
100
}