Files
muscl/src/core/protocol/commands/modify_privileges.rs
h7x4 10ef171c91
All checks were successful
Build and test / check (push) Successful in 1m55s
Build and test / build (push) Successful in 2m37s
Build and test / check-license (push) Successful in 1m3s
Build and test / test (push) Successful in 3m6s
Build and test / docs (push) Successful in 5m56s
client: print errors and warnings to stderr
2025-12-16 17:21:58 +09:00

148 lines
5.4 KiB
Rust

use std::collections::{BTreeMap, BTreeSet};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::core::{
database_privileges::{DatabasePrivilegeRow, DatabasePrivilegeRowDiff, DatabasePrivilegesDiff},
protocol::request_validation::ValidationError,
types::{DbOrUser, MySQLDatabase, MySQLUser},
};
pub type ModifyPrivilegesRequest = BTreeSet<DatabasePrivilegesDiff>;
pub type ModifyPrivilegesResponse =
BTreeMap<(MySQLDatabase, MySQLUser), Result<(), ModifyDatabasePrivilegesError>>;
#[derive(Error, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ModifyDatabasePrivilegesError {
#[error("Database validation error: {0}")]
DatabaseValidationError(ValidationError),
#[error("User validation error: {0}")]
UserValidationError(ValidationError),
#[error("Database does not exist")]
DatabaseDoesNotExist,
#[error("User does not exist")]
UserDoesNotExist,
#[error("Diff does not apply: {0}")]
DiffDoesNotApply(DiffDoesNotApplyError),
#[error("MySQL error: {0}")]
MySqlError(String),
}
#[allow(clippy::enum_variant_names)]
#[derive(Error, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum DiffDoesNotApplyError {
#[error("Privileges row already exists for database '{0}' and user '{1}'")]
RowAlreadyExists(MySQLDatabase, MySQLUser),
#[error("Privileges row does not exist for database '{0}' and user '{1}'")]
RowDoesNotExist(MySQLDatabase, MySQLUser),
#[error("Privilege change '{0:?}' does not apply to row '{1:?}'")]
RowPrivilegeChangeDoesNotApply(DatabasePrivilegeRowDiff, DatabasePrivilegeRow),
}
pub fn print_modify_database_privileges_output_status(output: &ModifyPrivilegesResponse) {
for ((database_name, username), result) in output {
match result {
Ok(()) => {
println!(
"Privileges for user '{}' on database '{}' modified successfully.",
username, database_name
);
}
Err(err) => {
eprintln!("{}", err.to_error_message(database_name, username));
eprintln!("Skipping...");
}
}
println!();
}
}
impl ModifyDatabasePrivilegesError {
pub fn to_error_message(&self, database_name: &MySQLDatabase, username: &MySQLUser) -> String {
match self {
ModifyDatabasePrivilegesError::DatabaseValidationError(err) => {
err.to_error_message(DbOrUser::Database(database_name.clone()))
}
ModifyDatabasePrivilegesError::UserValidationError(err) => {
err.to_error_message(DbOrUser::User(username.clone()))
}
ModifyDatabasePrivilegesError::DatabaseDoesNotExist => {
format!("Database '{}' does not exist.", database_name)
}
ModifyDatabasePrivilegesError::UserDoesNotExist => {
format!("User '{}' does not exist.", username)
}
ModifyDatabasePrivilegesError::DiffDoesNotApply(diff) => {
format!(
"Could not apply privilege change:\n{}",
diff.to_error_message()
)
}
ModifyDatabasePrivilegesError::MySqlError(err) => {
format!("MySQL error: {}", err)
}
}
}
#[allow(dead_code)]
pub fn error_type(&self) -> String {
match self {
// TODO: should these be subtyped?
ModifyDatabasePrivilegesError::DatabaseValidationError(err) => err.error_type(),
ModifyDatabasePrivilegesError::UserValidationError(err) => err.error_type(),
ModifyDatabasePrivilegesError::DatabaseDoesNotExist => {
"database-does-not-exist".to_string()
}
ModifyDatabasePrivilegesError::UserDoesNotExist => "user-does-not-exist".to_string(),
ModifyDatabasePrivilegesError::DiffDoesNotApply(err) => {
format!("diff-does-not-apply/{}", err.error_type())
}
ModifyDatabasePrivilegesError::MySqlError(_) => "mysql-error".to_string(),
}
}
}
impl DiffDoesNotApplyError {
pub fn to_error_message(&self) -> String {
match self {
DiffDoesNotApplyError::RowAlreadyExists(database_name, username) => {
format!(
"Privileges for user '{}' on database '{}' already exist.",
username, database_name
)
}
DiffDoesNotApplyError::RowDoesNotExist(database_name, username) => {
format!(
"Privileges for user '{}' on database '{}' do not exist.",
username, database_name
)
}
DiffDoesNotApplyError::RowPrivilegeChangeDoesNotApply(diff, row) => {
format!(
"Could not apply privilege change {:?} to row {:?}",
diff, row
)
}
}
}
pub fn error_type(&self) -> String {
match self {
DiffDoesNotApplyError::RowAlreadyExists(_, _) => "row-already-exists".to_string(),
DiffDoesNotApplyError::RowDoesNotExist(_, _) => "row-does-not-exist".to_string(),
DiffDoesNotApplyError::RowPrivilegeChangeDoesNotApply(_, _) => {
"row-privilege-change-does-not-apply".to_string()
}
}
}
}