1
use indoc::indoc;
2
use itertools::Itertools;
3
use serde::{Deserialize, Serialize};
4

            
5
use crate::core::common::UnixUser;
6

            
7
/// This enum is used to differentiate between database and user operations.
8
/// Their output are very similar, but there are slight differences in the words used.
9
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
10
pub enum DbOrUser {
11
    Database,
12
    User,
13
}
14

            
15
impl DbOrUser {
16
    pub fn lowercased(&self) -> &'static str {
17
        match self {
18
            DbOrUser::Database => "database",
19
            DbOrUser::User => "user",
20
        }
21
    }
22

            
23
    pub fn capitalized(&self) -> &'static str {
24
        match self {
25
            DbOrUser::Database => "Database",
26
            DbOrUser::User => "User",
27
        }
28
    }
29
}
30

            
31
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
32
pub enum NameValidationError {
33
    EmptyString,
34
    InvalidCharacters,
35
    TooLong,
36
}
37

            
38
impl NameValidationError {
39
    pub fn to_error_message(self, name: &str, db_or_user: DbOrUser) -> String {
40
        match self {
41
            NameValidationError::EmptyString => {
42
                format!("{} name cannot be empty.", db_or_user.capitalized()).to_owned()
43
            }
44
            NameValidationError::TooLong => format!(
45
                "{} is too long. Maximum length is 64 characters.",
46
                db_or_user.capitalized()
47
            )
48
            .to_owned(),
49
            NameValidationError::InvalidCharacters => format!(
50
                indoc! {r#"
51
                  Invalid characters in {} name: '{}'
52

            
53
                  Only A-Z, a-z, 0-9, _ (underscore) and - (dash) are permitted.
54
                "#},
55
                db_or_user.lowercased(),
56
                name
57
            )
58
            .to_owned(),
59
        }
60
    }
61
}
62

            
63
impl OwnerValidationError {
64
    pub fn to_error_message(self, name: &str, db_or_user: DbOrUser) -> String {
65
        let user = UnixUser::from_enviroment();
66

            
67
        let UnixUser {
68
            username,
69
            mut groups,
70
        } = user.unwrap_or(UnixUser {
71
            username: "???".to_string(),
72
            groups: vec![],
73
        });
74

            
75
        groups.sort();
76

            
77
        match self {
78
            OwnerValidationError::NoMatch => format!(
79
                indoc! {r#"
80
                  Invalid {} name prefix: '{}' does not match your username or any of your groups.
81
                  Are you sure you are allowed to create {} names with this prefix?
82
                  The format should be: <prefix>_<{} name>
83

            
84
                  Allowed prefixes:
85
                    - {}
86
                  {}
87
                "#},
88
                db_or_user.lowercased(),
89
                name,
90
                db_or_user.lowercased(),
91
                db_or_user.lowercased(),
92
                username,
93
                groups
94
                    .into_iter()
95
                    .filter(|g| g != &username)
96
                    .map(|g| format!("  - {}", g))
97
                    .join("\n"),
98
            )
99
            .to_owned(),
100
            OwnerValidationError::StringEmpty => format!(
101
                "'{}' is not a valid {} name.",
102
                name,
103
                db_or_user.lowercased()
104
            )
105
            .to_string(),
106
        }
107
    }
108
}
109

            
110
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
111
pub enum OwnerValidationError {
112
    // The name is valid, but none of the given prefixes matched the name
113
    NoMatch,
114

            
115
    // The name is empty, which is invalid
116
    StringEmpty,
117
}