1
mod check_auth;
2
mod create_db;
3
mod create_user;
4
mod drop_db;
5
mod drop_user;
6
mod edit_privs;
7
mod lock_user;
8
mod passwd_user;
9
mod show_db;
10
mod show_privs;
11
mod show_user;
12
mod unlock_user;
13

            
14
pub use check_auth::*;
15
pub use create_db::*;
16
pub use create_user::*;
17
pub use drop_db::*;
18
pub use drop_user::*;
19
pub use edit_privs::*;
20
pub use lock_user::*;
21
pub use passwd_user::*;
22
pub use show_db::*;
23
pub use show_privs::*;
24
pub use show_user::*;
25
pub use unlock_user::*;
26

            
27
use futures_util::SinkExt;
28
use itertools::Itertools;
29
use tokio_stream::StreamExt;
30

            
31
use crate::core::protocol::{ClientToServerMessageStream, Request, Response};
32

            
33
/// Handle an unexpected or erroneous response from the server.
34
///
35
/// This function checks the provided response and returns an appropriate error message.
36
/// It is typically used in `match` branches for expecting a specific response type from the server.
37
pub fn erroneous_server_response(
38
    response: Option<Result<Response, std::io::Error>>,
39
) -> anyhow::Result<()> {
40
    match response {
41
        Some(Ok(Response::Error(e))) => {
42
            anyhow::bail!("Server returned error: {e}");
43
        }
44
        Some(Err(e)) => {
45
            anyhow::bail!(e);
46
        }
47
        Some(response) => {
48
            anyhow::bail!("Unexpected response from server: {response:?}");
49
        }
50
        None => {
51
            anyhow::bail!("No response from server");
52
        }
53
    }
54
}
55

            
56
/// Print a hint about which name prefixes the user is authorized to manage
57
/// by querying the server for valid name prefixes.
58
///
59
/// This function should be used when an authorization error occurs,
60
/// to help the user understand which databases or users they are allowed to manage.
61
async fn print_authorization_owner_hint(
62
    server_connection: &mut ClientToServerMessageStream,
63
) -> anyhow::Result<()> {
64
    server_connection
65
        .send(Request::ListValidNamePrefixes)
66
        .await?;
67

            
68
    let response = match server_connection.next().await {
69
        Some(Ok(Response::ListValidNamePrefixes(prefixes))) => prefixes,
70
        response => return erroneous_server_response(response),
71
    };
72

            
73
    eprintln!(
74
        "Note: You are allowed to manage databases and users with the following prefixes:\n{}",
75
        response.into_iter().map(|p| format!(" - {p}")).join("\n")
76
    );
77

            
78
    Ok(())
79
}