Skip to main content

kalamdb_commons/models/
role.rs

1use std::{fmt, str::FromStr};
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6/// Enum representing user roles in KalamDB.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[cfg_attr(
9    feature = "serde",
10    derive(Serialize, Deserialize),
11    serde(rename_all = "lowercase")
12)]
13pub enum Role {
14    #[cfg_attr(feature = "serde", serde(alias = "Anonymous"))]
15    Anonymous,
16    #[cfg_attr(feature = "serde", serde(alias = "User"))]
17    User,
18    #[cfg_attr(feature = "serde", serde(alias = "Service"))]
19    Service,
20    #[cfg_attr(feature = "serde", serde(alias = "Dba"))]
21    Dba,
22    #[cfg_attr(feature = "serde", serde(alias = "System"))]
23    System,
24}
25
26impl Role {
27    pub fn as_str(&self) -> &'static str {
28        match self {
29            Role::Anonymous => "anonymous",
30            Role::User => "user",
31            Role::Service => "service",
32            Role::Dba => "dba",
33            Role::System => "system",
34        }
35    }
36
37    pub fn from_str_opt(s: &str) -> Option<Self> {
38        match s.to_lowercase().as_str() {
39            "anonymous" => Some(Role::Anonymous),
40            "user" => Some(Role::User),
41            "service" => Some(Role::Service),
42            "dba" => Some(Role::Dba),
43            "system" => Some(Role::System),
44            _ => None,
45        }
46    }
47}
48
49impl FromStr for Role {
50    type Err = String;
51    fn from_str(s: &str) -> Result<Self, Self::Err> {
52        Role::from_str_opt(s).ok_or_else(|| format!("Invalid Role: {}", s))
53    }
54}
55
56impl fmt::Display for Role {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        write!(f, "{}", self.as_str())
59    }
60}
61
62impl From<&str> for Role {
63    fn from(s: &str) -> Self {
64        match s.to_lowercase().as_str() {
65            "anonymous" => Role::Anonymous,
66            "user" => Role::User,
67            "service" => Role::Service,
68            "dba" => Role::Dba,
69            "system" => Role::System,
70            _ => Role::User,
71        }
72    }
73}
74
75impl From<String> for Role {
76    fn from(s: String) -> Self {
77        Role::from(s.as_str())
78    }
79}
80
81#[cfg(all(test, feature = "serde"))]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn serializes_to_lowercase_wire_values() {
87        assert_eq!(serde_json::to_string(&Role::Anonymous).unwrap(), "\"anonymous\"");
88        assert_eq!(serde_json::to_string(&Role::User).unwrap(), "\"user\"");
89        assert_eq!(serde_json::to_string(&Role::Service).unwrap(), "\"service\"");
90        assert_eq!(serde_json::to_string(&Role::Dba).unwrap(), "\"dba\"");
91        assert_eq!(serde_json::to_string(&Role::System).unwrap(), "\"system\"");
92    }
93
94    #[test]
95    fn deserializes_legacy_title_case_wire_values() {
96        let anonymous: Role = serde_json::from_str("\"Anonymous\"").unwrap();
97        let user: Role = serde_json::from_str("\"User\"").unwrap();
98        let service: Role = serde_json::from_str("\"Service\"").unwrap();
99        let dba: Role = serde_json::from_str("\"Dba\"").unwrap();
100        let system: Role = serde_json::from_str("\"System\"").unwrap();
101
102        assert_eq!(anonymous, Role::Anonymous);
103        assert_eq!(user, Role::User);
104        assert_eq!(service, Role::Service);
105        assert_eq!(dba, Role::Dba);
106        assert_eq!(system, Role::System);
107    }
108}