Skip to main content

linkrs_core/
permission.rs

1//! Permission Type Definition
2//!
3//! Provide core permission model and role type definitions
4
5/// Permission Type
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum Permission {
8    Read,
9    Write,
10    Delete,
11    Schema,
12    Admin,
13}
14
15/// 5-level permission model - reference nebula-graph implementation
16/// - God: global super administrator with all privileges (similar to Linux root)
17/// - Admin: Space administrator who can manage Schema and users in Space.
18/// - Dba: Database administrator who can modify the Schema.
19/// - User: Normal user, can read and write data
20/// - Guest: read-only user, can only read data
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
22pub enum RoleType {
23    God = 0x01,
24    Admin = 0x02,
25    Dba = 0x03,
26    User = 0x04,
27    Guest = 0x05,
28}
29
30impl RoleType {
31    /// Check that the role has the specified permissions
32    pub fn has_permission(&self, permission: Permission) -> bool {
33        match self {
34            RoleType::God => true,
35            RoleType::Admin => matches!(
36                permission,
37                Permission::Read
38                    | Permission::Write
39                    | Permission::Delete
40                    | Permission::Schema
41                    | Permission::Admin
42            ),
43            RoleType::Dba => matches!(
44                permission,
45                Permission::Read | Permission::Write | Permission::Delete | Permission::Schema
46            ),
47            RoleType::User => matches!(
48                permission,
49                Permission::Read | Permission::Write | Permission::Delete
50            ),
51            RoleType::Guest => matches!(permission, Permission::Read),
52        }
53    }
54
55    /// Checks if the specified role can be granted
56    pub fn can_grant(&self, target_role: RoleType) -> bool {
57        match self {
58            RoleType::God => target_role != RoleType::God,
59            RoleType::Admin => matches!(
60                target_role,
61                RoleType::Dba | RoleType::User | RoleType::Guest
62            ),
63            RoleType::Dba => matches!(target_role, RoleType::User | RoleType::Guest),
64            _ => false,
65        }
66    }
67
68    /// Check if the specified role can be revoked
69    pub fn can_revoke(&self, target_role: RoleType) -> bool {
70        self.can_grant(target_role)
71    }
72
73    /// Parsing role types from bytes
74    pub fn from_byte(byte: u8) -> Option<Self> {
75        match byte {
76            0x01 => Some(RoleType::God),
77            0x02 => Some(RoleType::Admin),
78            0x03 => Some(RoleType::Dba),
79            0x04 => Some(RoleType::User),
80            0x05 => Some(RoleType::Guest),
81            _ => None,
82        }
83    }
84
85    /// convert to bytes
86    pub fn to_byte(&self) -> u8 {
87        *self as u8
88    }
89}
90
91impl std::fmt::Display for RoleType {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        match self {
94            RoleType::God => write!(f, "GOD"),
95            RoleType::Admin => write!(f, "ADMIN"),
96            RoleType::Dba => write!(f, "DBA"),
97            RoleType::User => write!(f, "USER"),
98            RoleType::Guest => write!(f, "GUEST"),
99        }
100    }
101}
102
103impl std::str::FromStr for RoleType {
104    type Err = String;
105
106    fn from_str(s: &str) -> Result<Self, Self::Err> {
107        match s.to_uppercase().as_str() {
108            "GOD" => Ok(RoleType::God),
109            "ADMIN" => Ok(RoleType::Admin),
110            "DBA" => Ok(RoleType::Dba),
111            "USER" => Ok(RoleType::User),
112            "GUEST" => Ok(RoleType::Guest),
113            _ => Err(format!("Unknown role type: {}", s)),
114        }
115    }
116}