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
33
    pub fn get_privilege_by_name(&self, name: &str) -> Option<bool> {
53
33
        match name {
54
33
            "select_priv" => Some(self.select_priv),
55
30
            "insert_priv" => Some(self.insert_priv),
56
27
            "update_priv" => Some(self.update_priv),
57
24
            "delete_priv" => Some(self.delete_priv),
58
21
            "create_priv" => Some(self.create_priv),
59
18
            "drop_priv" => Some(self.drop_priv),
60
15
            "alter_priv" => Some(self.alter_priv),
61
12
            "index_priv" => Some(self.index_priv),
62
9
            "create_tmp_table_priv" => Some(self.create_tmp_table_priv),
63
6
            "lock_tables_priv" => Some(self.lock_tables_priv),
64
3
            "references_priv" => Some(self.references_priv),
65
            _ => None,
66
        }
67
33
    }
68
}
69

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

            
85
/// Converts a database privilege field name to a human-readable name.
86
61
pub fn db_priv_field_human_readable_name(name: &str) -> String {
87
61
    match name {
88
61
        "Db" => "Database".to_owned(),
89
57
        "User" => "User".to_owned(),
90
55
        "select_priv" => "Select".to_owned(),
91
50
        "insert_priv" => "Insert".to_owned(),
92
45
        "update_priv" => "Update".to_owned(),
93
40
        "delete_priv" => "Delete".to_owned(),
94
35
        "create_priv" => "Create".to_owned(),
95
30
        "drop_priv" => "Drop".to_owned(),
96
25
        "alter_priv" => "Alter".to_owned(),
97
20
        "index_priv" => "Index".to_owned(),
98
15
        "create_tmp_table_priv" => "Temp".to_owned(),
99
10
        "lock_tables_priv" => "Lock".to_owned(),
100
5
        "references_priv" => "References".to_owned(),
101
        _ => format!("Unknown({})", name),
102
    }
103
61
}