Lines
60.87 %
Functions
57.14 %
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::core::{
protocol::request_validation::ValidationError,
types::{DbOrUser, MySQLUser},
};
/// The desired new password for a user, either provided explicitly,
/// generated by the server, or cleared.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PasswordSource {
Explicit(String),
Generate,
Clear,
}
pub type SetUserPasswordRequest = (MySQLUser, PasswordSource);
/// The generated password is returned when the request used
/// [`PasswordSource::Generate`], and is `None` otherwise.
pub type SetUserPasswordResponse = Result<Option<String>, SetPasswordError>;
#[derive(Error, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum SetPasswordError {
#[error("Validation error: {0}")]
ValidationError(#[from] ValidationError),
#[error("User does not exist")]
UserDoesNotExist,
#[error("MySQL error: {0}")]
MySqlError(String),
pub fn print_set_password_output_status(output: &SetUserPasswordResponse, username: &MySQLUser) {
match output {
Ok(None) => {
println!("Password for user '{username}' set successfully.");
Ok(Some(generated_password)) => {
println!("Password for user '{username}' generated successfully: {generated_password}");
Err(err) => {
eprintln!("{}", err.to_error_message(username));
eprintln!("Skipping...");
impl SetPasswordError {
#[must_use]
pub fn to_error_message(&self, username: &MySQLUser) -> String {
match self {
SetPasswordError::ValidationError(err) => {
err.to_error_message(&DbOrUser::User(username.clone()))
SetPasswordError::UserDoesNotExist => {
format!("User '{username}' does not exist.")
SetPasswordError::MySqlError(err) => {
format!("MySQL error: {err}")
#[allow(dead_code)]
pub fn error_type(&self) -> String {
SetPasswordError::ValidationError(err) => err.error_type(),
SetPasswordError::UserDoesNotExist => "user-does-not-exist".to_string(),
SetPasswordError::MySqlError(_) => "mysql-error".to_string(),
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_serialize_deserialize_explicit_request() {
let request: SetUserPasswordRequest = (
"test_user".into(),
PasswordSource::Explicit("new_password".into()),
);
let json = serde_json::to_string_pretty(&request).unwrap();
println!("Serialized request:\n{}", json);
let deserialized: SetUserPasswordRequest = serde_json::from_str(&json).unwrap();
assert_eq!(request, deserialized);
fn test_serialize_deserialize_generate_request() {
let request: SetUserPasswordRequest = ("test_user".into(), PasswordSource::Generate);
fn test_serialize_deserialize_clear_request() {
let request: SetUserPasswordRequest = ("test_user".into(), PasswordSource::Clear);
fn test_serialize_deserialize_response() {
let response_ok: SetUserPasswordResponse = Ok(None);
let response_generated: SetUserPasswordResponse = Ok(Some("generated_password".into()));
let response_err: SetUserPasswordResponse = Err(SetPasswordError::UserDoesNotExist);
let json_ok = serde_json::to_string_pretty(&response_ok).unwrap();
let json_generated = serde_json::to_string_pretty(&response_generated).unwrap();
let json_err = serde_json::to_string_pretty(&response_err).unwrap();
println!("Serialized OK response:\n{}", json_ok);
println!("Serialized generated response:\n{}", json_generated);
println!("Serialized Error response:\n{}", json_err);
let deserialized_ok: SetUserPasswordResponse = serde_json::from_str(&json_ok).unwrap();
let deserialized_generated: SetUserPasswordResponse =
serde_json::from_str(&json_generated).unwrap();
let deserialized_err: SetUserPasswordResponse = serde_json::from_str(&json_err).unwrap();
assert_eq!(response_ok, deserialized_ok);
assert_eq!(response_generated, deserialized_generated);
assert_eq!(response_err, deserialized_err);