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; 16] = [
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
    "create_view_priv",
27
    "show_view_priv",
28
    "trigger_priv",
29
];
30

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

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

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

            
80
impl fmt::Display for DatabasePrivilegeRow {
81
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82
        for field in DATABASE_PRIVILEGE_FIELDS.into_iter().skip(2) {
83
            if self.get_privilege_by_name(field).unwrap() {
84
                f.write_str(db_priv_field_human_readable_name(field).as_str())?;
85
                f.write_str(": Y\n")?;
86
            } else {
87
                f.write_str(db_priv_field_human_readable_name(field).as_str())?;
88
                f.write_str(": N\n")?;
89
            }
90
        }
91
        Ok(())
92
    }
93
}
94

            
95
/// Converts a database privilege field name to a human-readable name.
96
#[must_use]
97
299
pub fn db_priv_field_human_readable_name(name: &str) -> String {
98
299
    match name {
99
299
        "Db" => "Database".to_owned(),
100
284
        "User" => "User".to_owned(),
101
281
        "select_priv" => "Select".to_owned(),
102
260
        "insert_priv" => "Insert".to_owned(),
103
240
        "update_priv" => "Update".to_owned(),
104
220
        "delete_priv" => "Delete".to_owned(),
105
200
        "create_priv" => "Create".to_owned(),
106
180
        "drop_priv" => "Drop".to_owned(),
107
160
        "alter_priv" => "Alter".to_owned(),
108
140
        "index_priv" => "Index".to_owned(),
109
120
        "create_tmp_table_priv" => "Temp".to_owned(),
110
100
        "lock_tables_priv" => "Lock".to_owned(),
111
80
        "references_priv" => "References".to_owned(),
112
60
        "create_view_priv" => "CreateView".to_owned(),
113
40
        "show_view_priv" => "ShowView".to_owned(),
114
20
        "trigger_priv" => "Trigger".to_owned(),
115
        _ => format!("Unknown({name})"),
116
    }
117
299
}
118

            
119
/// Converts a database privilege field name to a single-character name.
120
/// (the characters from the cli privilege editor)
121
#[must_use]
122
pub fn db_priv_field_single_character_name(name: &str) -> &str {
123
    match name {
124
        "select_priv" => "s",
125
        "insert_priv" => "i",
126
        "update_priv" => "u",
127
        "delete_priv" => "d",
128
        "create_priv" => "c",
129
        "drop_priv" => "D",
130
        "alter_priv" => "a",
131
        "index_priv" => "I",
132
        "create_tmp_table_priv" => "t",
133
        "lock_tables_priv" => "l",
134
        "references_priv" => "r",
135
        "create_view_priv" => "v",
136
        "show_view_priv" => "V",
137
        "trigger_priv" => "T",
138
        _ => "?",
139
    }
140
}