client: print only json for show-db/show-user --json
All checks were successful
All checks were successful
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
use clap::Parser;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use futures_util::SinkExt;
|
||||
use prettytable::{Cell, Row, Table};
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
use crate::{
|
||||
client::commands::erroneous_server_response,
|
||||
core::{
|
||||
completion::mysql_database_completer,
|
||||
protocol::{ClientToServerMessageStream, Request, Response},
|
||||
protocol::{
|
||||
ClientToServerMessageStream, Request, Response, print_list_databases_output_status,
|
||||
print_list_databases_output_status_json,
|
||||
},
|
||||
types::MySQLDatabase,
|
||||
},
|
||||
};
|
||||
@@ -40,25 +42,13 @@ pub async fn show_databases(
|
||||
|
||||
server_connection.send(message).await?;
|
||||
|
||||
// TODO: collect errors for json output.
|
||||
|
||||
let mut contained_errors = false;
|
||||
let database_list = match server_connection.next().await {
|
||||
Some(Ok(Response::ListDatabases(databases))) => databases
|
||||
.into_iter()
|
||||
.filter_map(|(database_name, result)| match result {
|
||||
Ok(database_row) => Some(database_row),
|
||||
Err(err) => {
|
||||
contained_errors = true;
|
||||
eprintln!("{}", err.to_error_message(&database_name));
|
||||
eprintln!("Skipping...");
|
||||
println!();
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
let databases = match server_connection.next().await {
|
||||
Some(Ok(Response::ListDatabases(databases))) => databases,
|
||||
Some(Ok(Response::ListAllDatabases(database_list))) => match database_list {
|
||||
Ok(list) => list,
|
||||
Ok(list) => list
|
||||
.into_iter()
|
||||
.map(|db| (db.database.clone(), Ok(db)))
|
||||
.collect(),
|
||||
Err(err) => {
|
||||
server_connection.send(Request::Exit).await?;
|
||||
return Err(
|
||||
@@ -72,19 +62,12 @@ pub async fn show_databases(
|
||||
server_connection.send(Request::Exit).await?;
|
||||
|
||||
if args.json {
|
||||
println!("{}", serde_json::to_string_pretty(&database_list)?);
|
||||
} else if database_list.is_empty() {
|
||||
println!("No databases to show.");
|
||||
print_list_databases_output_status_json(&databases);
|
||||
} else {
|
||||
let mut table = Table::new();
|
||||
table.add_row(Row::new(vec![Cell::new("Database")]));
|
||||
for db in database_list {
|
||||
table.add_row(row![db.database]);
|
||||
}
|
||||
table.printstd();
|
||||
print_list_databases_output_status(&databases);
|
||||
}
|
||||
|
||||
if args.fail && contained_errors {
|
||||
if args.fail && databases.values().any(|res| res.is_err()) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
use clap_complete::ArgValueCompleter;
|
||||
use futures_util::SinkExt;
|
||||
@@ -8,7 +7,10 @@ use crate::{
|
||||
client::commands::erroneous_server_response,
|
||||
core::{
|
||||
completion::mysql_user_completer,
|
||||
protocol::{ClientToServerMessageStream, Request, Response},
|
||||
protocol::{
|
||||
ClientToServerMessageStream, Request, Response, print_list_users_output_status,
|
||||
print_list_users_output_status_json,
|
||||
},
|
||||
types::MySQLUser,
|
||||
},
|
||||
};
|
||||
@@ -43,22 +45,13 @@ pub async fn show_users(
|
||||
anyhow::bail!(err);
|
||||
}
|
||||
|
||||
let mut contained_errors = false;
|
||||
let users = match server_connection.next().await {
|
||||
Some(Ok(Response::ListUsers(users))) => users
|
||||
.into_iter()
|
||||
.filter_map(|(username, result)| match result {
|
||||
Ok(user) => Some(user),
|
||||
Err(err) => {
|
||||
contained_errors = true;
|
||||
eprintln!("{}", err.to_error_message(&username));
|
||||
eprintln!("Skipping...");
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
Some(Ok(Response::ListUsers(users))) => users,
|
||||
Some(Ok(Response::ListAllUsers(users))) => match users {
|
||||
Ok(users) => users,
|
||||
Ok(users) => users
|
||||
.into_iter()
|
||||
.map(|user| (user.user.clone(), Ok(user)))
|
||||
.collect(),
|
||||
Err(err) => {
|
||||
server_connection.send(Request::Exit).await?;
|
||||
return Err(
|
||||
@@ -72,32 +65,12 @@ pub async fn show_users(
|
||||
server_connection.send(Request::Exit).await?;
|
||||
|
||||
if args.json {
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&users).context("Failed to serialize users to JSON")?
|
||||
);
|
||||
} else if users.is_empty() {
|
||||
println!("No users to show.");
|
||||
print_list_users_output_status_json(&users);
|
||||
} else {
|
||||
let mut table = prettytable::Table::new();
|
||||
table.add_row(row![
|
||||
"User",
|
||||
"Password is set",
|
||||
"Locked",
|
||||
"Databases where user has privileges"
|
||||
]);
|
||||
for user in users {
|
||||
table.add_row(row![
|
||||
user.user,
|
||||
user.has_password,
|
||||
user.is_locked,
|
||||
user.databases.join("\n")
|
||||
]);
|
||||
}
|
||||
table.printstd();
|
||||
print_list_users_output_status(&users);
|
||||
}
|
||||
|
||||
if args.fail && contained_errors {
|
||||
if args.fail && users.values().any(|result| result.is_err()) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use prettytable::{Cell, Row, Table};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{
|
||||
core::{
|
||||
@@ -22,6 +24,57 @@ pub enum ListDatabasesError {
|
||||
MySqlError(String),
|
||||
}
|
||||
|
||||
pub fn print_list_databases_output_status(output: &ListDatabasesResponse) {
|
||||
let mut final_database_list: Vec<&DatabaseRow> = Vec::new();
|
||||
for (db_name, db_result) in output {
|
||||
match db_result {
|
||||
Ok(db_row) => final_database_list.push(db_row),
|
||||
Err(err) => {
|
||||
eprintln!("{}", err.to_error_message(db_name));
|
||||
eprintln!("Skipping...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if final_database_list.is_empty() {
|
||||
println!("No databases to show.");
|
||||
} else {
|
||||
let mut table = Table::new();
|
||||
table.add_row(Row::new(vec![Cell::new("Database")]));
|
||||
for db in final_database_list {
|
||||
table.add_row(row![db.database]);
|
||||
}
|
||||
table.printstd();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_list_databases_output_status_json(output: &ListDatabasesResponse) {
|
||||
let value = output
|
||||
.iter()
|
||||
.map(|(name, result)| match result {
|
||||
Ok(_row) => (
|
||||
name.to_string(),
|
||||
json!({
|
||||
"status": "success",
|
||||
// NOTE: there will likely be more data to include here in the future
|
||||
}),
|
||||
),
|
||||
Err(err) => (
|
||||
name.to_string(),
|
||||
json!({
|
||||
"status": "error",
|
||||
"error": err.to_error_message(name),
|
||||
}),
|
||||
),
|
||||
})
|
||||
.collect::<serde_json::Map<_, _>>();
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&value)
|
||||
.unwrap_or("Failed to serialize result to JSON".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
impl ListDatabasesError {
|
||||
pub fn to_error_message(&self, database_name: &MySQLDatabase) -> String {
|
||||
match self {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use prettytable::Table;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{
|
||||
core::{
|
||||
@@ -22,6 +24,72 @@ pub enum ListUsersError {
|
||||
MySqlError(String),
|
||||
}
|
||||
|
||||
pub fn print_list_users_output_status(output: &ListUsersResponse) {
|
||||
let mut final_user_list: Vec<&DatabaseUser> = Vec::new();
|
||||
for (db_name, db_result) in output {
|
||||
match db_result {
|
||||
Ok(db_row) => final_user_list.push(db_row),
|
||||
Err(err) => {
|
||||
eprintln!("{}", err.to_error_message(db_name));
|
||||
eprintln!("Skipping...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if final_user_list.is_empty() {
|
||||
println!("No users to show.");
|
||||
} else {
|
||||
let mut table = Table::new();
|
||||
table.add_row(row![
|
||||
"User",
|
||||
"Password is set",
|
||||
"Locked",
|
||||
"Databases where user has privileges"
|
||||
]);
|
||||
for user in final_user_list {
|
||||
table.add_row(row![
|
||||
user.user,
|
||||
user.has_password,
|
||||
user.is_locked,
|
||||
user.databases.join("\n")
|
||||
]);
|
||||
}
|
||||
table.printstd();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_list_users_output_status_json(output: &ListUsersResponse) {
|
||||
let value = output
|
||||
.iter()
|
||||
.map(|(name, result)| match result {
|
||||
Ok(row) => (
|
||||
name.to_string(),
|
||||
json!({
|
||||
"status": "success",
|
||||
"value": {
|
||||
"user": row.user,
|
||||
"has_password": row.has_password,
|
||||
"is_locked": row.is_locked,
|
||||
"databases": row.databases,
|
||||
}
|
||||
}),
|
||||
),
|
||||
Err(err) => (
|
||||
name.to_string(),
|
||||
json!({
|
||||
"status": "error",
|
||||
"error": err.to_error_message(name),
|
||||
}),
|
||||
),
|
||||
})
|
||||
.collect::<serde_json::Map<_, _>>();
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&value)
|
||||
.unwrap_or("Failed to serialize result to JSON".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
impl ListUsersError {
|
||||
pub fn to_error_message(&self, username: &MySQLUser) -> String {
|
||||
match self {
|
||||
|
||||
Reference in New Issue
Block a user