1
use std::collections::BTreeMap;
2

            
3
use serde::{Deserialize, Serialize};
4
use serde_json::json;
5
use thiserror::Error;
6

            
7
use crate::core::{
8
    protocol::request_validation::ValidationError,
9
    types::{DbOrUser, MySQLUser},
10
};
11

            
12
pub type CreateUsersRequest = Vec<MySQLUser>;
13

            
14
pub type CreateUsersResponse = BTreeMap<MySQLUser, Result<(), CreateUserError>>;
15

            
16
#[derive(Error, Debug, Clone, PartialEq, Serialize, Deserialize)]
17
pub enum CreateUserError {
18
    #[error("Validation error: {0}")]
19
    ValidationError(#[from] ValidationError),
20

            
21
    #[error("User already exists")]
22
    UserAlreadyExists,
23

            
24
    #[error("MySQL error: {0}")]
25
    MySqlError(String),
26
}
27

            
28
pub fn print_create_users_output_status(output: &CreateUsersResponse) {
29
    for (username, result) in output {
30
        match result {
31
            Ok(()) => {
32
                println!("User '{username}' created successfully.");
33
            }
34
            Err(err) => {
35
                eprintln!("{}", err.to_error_message(username));
36
                eprintln!("Skipping...");
37
            }
38
        }
39
        println!();
40
    }
41
}
42

            
43
pub fn print_create_users_output_status_json(output: &CreateUsersResponse) {
44
    let value = output
45
        .iter()
46
        .map(|(name, result)| match result {
47
            Ok(()) => (name.to_string(), json!({ "status": "success" })),
48
            Err(err) => (
49
                name.to_string(),
50
                json!({
51
                  "status": "error",
52
                  "type": err.error_type(),
53
                  "error": err.to_error_message(name),
54
                }),
55
            ),
56
        })
57
        .collect::<serde_json::Map<_, _>>();
58
    println!(
59
        "{}",
60
        serde_json::to_string_pretty(&value)
61
            .unwrap_or("Failed to serialize result to JSON".to_string())
62
    );
63
}
64

            
65
impl CreateUserError {
66
    #[must_use]
67
    pub fn to_error_message(&self, username: &MySQLUser) -> String {
68
        match self {
69
            CreateUserError::ValidationError(err) => {
70
                err.to_error_message(&DbOrUser::User(username.clone()))
71
            }
72
            CreateUserError::UserAlreadyExists => {
73
                format!("User '{username}' already exists.")
74
            }
75
            CreateUserError::MySqlError(err) => {
76
                format!("MySQL error: {err}")
77
            }
78
        }
79
    }
80

            
81
    #[must_use]
82
    pub fn error_type(&self) -> String {
83
        match self {
84
            CreateUserError::ValidationError(err) => err.error_type(),
85
            CreateUserError::UserAlreadyExists => "user-already-exists".to_string(),
86
            CreateUserError::MySqlError(_) => "mysql-error".to_string(),
87
        }
88
    }
89
}