client: print only json for show-db/show-user/show-privs --json
All checks were successful
All checks were successful
The earlier version would print out human readable errors before printing the json, which was not ideal. This version prints out the errors inside the json.
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -4,10 +4,16 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use itertools::Itertools;
|
||||
use prettytable::{Cell, Row, Table};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::core::{
|
||||
database_privileges::DatabasePrivilegeRow,
|
||||
common::yn,
|
||||
database_privileges::{
|
||||
DATABASE_PRIVILEGE_FIELDS, DatabasePrivilegeRow, db_priv_field_human_readable_name,
|
||||
},
|
||||
protocol::request_validation::{NameValidationError, OwnerValidationError},
|
||||
types::{DbOrUser, MySQLDatabase},
|
||||
};
|
||||
@@ -17,6 +23,84 @@ pub type ListPrivilegesRequest = Option<Vec<MySQLDatabase>>;
|
||||
pub type ListPrivilegesResponse =
|
||||
BTreeMap<MySQLDatabase, Result<Vec<DatabasePrivilegeRow>, GetDatabasesPrivilegeDataError>>;
|
||||
|
||||
pub fn print_list_privileges_output_status(output: &ListPrivilegesResponse) {
|
||||
let mut final_privs_map: BTreeMap<MySQLDatabase, Vec<DatabasePrivilegeRow>> = BTreeMap::new();
|
||||
for (db_name, db_result) in output {
|
||||
match db_result {
|
||||
Ok(db_rows) => {
|
||||
final_privs_map.insert(db_name.clone(), db_rows.clone());
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("{}", err.to_error_message(db_name));
|
||||
eprintln!("Skipping...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if final_privs_map.is_empty() {
|
||||
println!("No privileges to show.");
|
||||
} else {
|
||||
let mut table = Table::new();
|
||||
|
||||
table.add_row(Row::new(
|
||||
DATABASE_PRIVILEGE_FIELDS
|
||||
.into_iter()
|
||||
.map(db_priv_field_human_readable_name)
|
||||
.map(|name| Cell::new(&name))
|
||||
.collect(),
|
||||
));
|
||||
|
||||
for (_database, rows) in final_privs_map {
|
||||
for row in rows.iter() {
|
||||
table.add_row(row![
|
||||
row.db,
|
||||
row.user,
|
||||
c->yn(row.select_priv),
|
||||
c->yn(row.insert_priv),
|
||||
c->yn(row.update_priv),
|
||||
c->yn(row.delete_priv),
|
||||
c->yn(row.create_priv),
|
||||
c->yn(row.drop_priv),
|
||||
c->yn(row.alter_priv),
|
||||
c->yn(row.index_priv),
|
||||
c->yn(row.create_tmp_table_priv),
|
||||
c->yn(row.lock_tables_priv),
|
||||
c->yn(row.references_priv),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
table.printstd();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_list_privileges_output_status_json(output: &ListPrivilegesResponse) {
|
||||
let value = output
|
||||
.iter()
|
||||
.map(|(name, result)| match result {
|
||||
Ok(row) => (
|
||||
name.to_string(),
|
||||
json!({
|
||||
"status": "success",
|
||||
"value": row.iter().into_group_map_by(|priv_row| priv_row.user.clone()),
|
||||
}),
|
||||
),
|
||||
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())
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum GetDatabasesPrivilegeDataError {
|
||||
SanitizationError(NameValidationError),
|
||||
|
||||
@@ -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