use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default,
)]
#[serde(rename_all = "lowercase")]
pub enum Permission {
#[default]
Read,
Write,
Admin,
}
impl Permission {
pub fn has(&self, required: Permission) -> bool {
*self >= required
}
pub fn parse(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"read" => Some(Permission::Read),
"write" | "push" => Some(Permission::Write),
"admin" | "owner" => Some(Permission::Admin),
_ => None,
}
}
}
impl fmt::Display for Permission {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Permission::Read => write!(f, "read"),
Permission::Write => write!(f, "write"),
Permission::Admin => write!(f, "admin"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PermissionGrant {
pub resource: String,
pub permission: Permission,
pub source: String,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_permission_ordering() {
assert!(Permission::Read < Permission::Write);
assert!(Permission::Write < Permission::Admin);
assert!(Permission::Read < Permission::Admin);
}
#[test]
fn test_permission_has() {
assert!(Permission::Admin.has(Permission::Read));
assert!(Permission::Admin.has(Permission::Write));
assert!(Permission::Admin.has(Permission::Admin));
assert!(Permission::Write.has(Permission::Read));
assert!(Permission::Write.has(Permission::Write));
assert!(!Permission::Write.has(Permission::Admin));
assert!(Permission::Read.has(Permission::Read));
assert!(!Permission::Read.has(Permission::Write));
assert!(!Permission::Read.has(Permission::Admin));
}
#[test]
fn test_permission_parse() {
assert_eq!(Permission::parse("read"), Some(Permission::Read));
assert_eq!(Permission::parse("write"), Some(Permission::Write));
assert_eq!(Permission::parse("push"), Some(Permission::Write));
assert_eq!(Permission::parse("admin"), Some(Permission::Admin));
assert_eq!(Permission::parse("owner"), Some(Permission::Admin));
assert_eq!(Permission::parse("ADMIN"), Some(Permission::Admin));
assert_eq!(Permission::parse("invalid"), None);
}
#[test]
fn test_permission_display() {
assert_eq!(format!("{}", Permission::Read), "read");
assert_eq!(format!("{}", Permission::Write), "write");
assert_eq!(format!("{}", Permission::Admin), "admin");
}
}