1
//! This module contains some base datastructures and functionality for dealing with
2
//! database privileges in `MySQL`.
3

            
4
use std::fmt;
5

            
6
use crate::core::types::{MySQLDatabase, MySQLUser};
7
use serde::{Deserialize, Serialize};
8

            
9
/// This is the list of fields that are used to fetch the db + user + privileges
10
/// from the `db` table in the database. If you need to add or remove privilege
11
/// fields, this is a good place to start.
12
pub const DATABASE_PRIVILEGE_FIELDS: [&str; 13] = [
13
    "Db",
14
    "User",
15
    "select_priv",
16
    "insert_priv",
17
    "update_priv",
18
    "delete_priv",
19
    "create_priv",
20
    "drop_priv",
21
    "alter_priv",
22
    "index_priv",
23
    "create_tmp_table_priv",
24
    "lock_tables_priv",
25
    "references_priv",
26
];
27

            
28
// NOTE: ord is needed for BTreeSet to accept the type, but it
29
//       doesn't have any natural implementation semantics.
30

            
31
/// Representation of the set of privileges for a single user on a single database.
32
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
33
pub struct DatabasePrivilegeRow {
34
    // TODO: don't store the db and user here, let the type be stored in a mapping
35
    pub db: MySQLDatabase,
36
    pub user: MySQLUser,
37
    pub select_priv: bool,
38
    pub insert_priv: bool,
39
    pub update_priv: bool,
40
    pub delete_priv: bool,
41
    pub create_priv: bool,
42
    pub drop_priv: bool,
43
    pub alter_priv: bool,
44
    pub index_priv: bool,
45
    pub create_tmp_table_priv: bool,
46
    pub lock_tables_priv: bool,
47
    pub references_priv: bool,
48
}
49

            
50
impl DatabasePrivilegeRow {
51
    /// Gets the value of a privilege by its name as a &str.
52
    #[must_use]
53
66
    pub fn get_privilege_by_name(&self, name: &str) -> Option<bool> {
54
66
        match name {
55
66
            "select_priv" => Some(self.select_priv),
56
60
            "insert_priv" => Some(self.insert_priv),
57
54
            "update_priv" => Some(self.update_priv),
58
48
            "delete_priv" => Some(self.delete_priv),
59
42
            "create_priv" => Some(self.create_priv),
60
36
            "drop_priv" => Some(self.drop_priv),
61
30
            "alter_priv" => Some(self.alter_priv),
62
24
            "index_priv" => Some(self.index_priv),
63
18
            "create_tmp_table_priv" => Some(self.create_tmp_table_priv),
64
12
            "lock_tables_priv" => Some(self.lock_tables_priv),
65
6
            "references_priv" => Some(self.references_priv),
66
            _ => None,
67
        }
68
66
    }
69
}
70

            
71
impl fmt::Display for DatabasePrivilegeRow {
72
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73
        for field in DATABASE_PRIVILEGE_FIELDS.into_iter().skip(2) {
74
            if self.get_privilege_by_name(field).unwrap() {
75
                f.write_str(db_priv_field_human_readable_name(field).as_str())?;
76
                f.write_str(": Y\n")?;
77
            } else {
78
                f.write_str(db_priv_field_human_readable_name(field).as_str())?;
79
                f.write_str(": N\n")?;
80
            }
81
        }
82
        Ok(())
83
    }
84
}
85

            
86
/// Converts a database privilege field name to a human-readable name.
87
#[must_use]
88
259
pub fn db_priv_field_human_readable_name(name: &str) -> String {
89
259
    match name {
90
259
        "Db" => "Database".to_owned(),
91
244
        "User" => "User".to_owned(),
92
231
        "select_priv" => "Select".to_owned(),
93
210
        "insert_priv" => "Insert".to_owned(),
94
189
        "update_priv" => "Update".to_owned(),
95
168
        "delete_priv" => "Delete".to_owned(),
96
147
        "create_priv" => "Create".to_owned(),
97
126
        "drop_priv" => "Drop".to_owned(),
98
105
        "alter_priv" => "Alter".to_owned(),
99
84
        "index_priv" => "Index".to_owned(),
100
63
        "create_tmp_table_priv" => "Temp".to_owned(),
101
42
        "lock_tables_priv" => "Lock".to_owned(),
102
21
        "references_priv" => "References".to_owned(),
103
        _ => format!("Unknown({name})"),
104
    }
105
259
}
106

            
107
/// Converts a database privilege field name to a single-character name.
108
/// (the characters from the cli privilege editor)
109
#[must_use]
110
pub fn db_priv_field_single_character_name(name: &str) -> &str {
111
    match name {
112
        "select_priv" => "s",
113
        "insert_priv" => "i",
114
        "update_priv" => "u",
115
        "delete_priv" => "d",
116
        "create_priv" => "c",
117
        "drop_priv" => "D",
118
        "alter_priv" => "a",
119
        "index_priv" => "I",
120
        "create_tmp_table_priv" => "t",
121
        "lock_tables_priv" => "l",
122
        "references_priv" => "r",
123
        _ => "?",
124
    }
125
}