authbeam/
permissions.rs

1use serde::{
2    de::{Error as DeError, Visitor},
3    Deserialize, Deserializer, Serialize,
4};
5use bitflags::bitflags;
6
7bitflags! {
8    /// Fine-grained permissions built using bitwise operations.
9    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10    pub struct FinePermission: u32 {
11        const DEFAULT = 1 << 0;
12        const ADMINISTRATOR = 1 << 1;
13        const MANAGE_RESPONSES = 1 << 2;
14        const MANAGE_COMMENTS = 1 << 3;
15        const MANAGE_QUESTIONS = 1 << 4;
16        const MANAGE_CHATS = 1 << 5;
17        const MANAGE_MESSAGES = 1 << 6;
18        const UNUSED = 1 << 7;
19        const MANAGE_NOTIFICATIONS = 1 << 8;
20        const UNUSED_1 = 1 << 9;
21        const BAN_IP = 1 << 10;
22        const UNBAN_IP = 1 << 11;
23        const APPROVE_MARKETPLACE_ITEMS = 1 << 12;
24        const VIEW_PROFILE_MANAGE = 1 << 13;
25        const VIEW_AUDIT_LOG = 1 << 14;
26        const VIEW_REPORTS = 1 << 15;
27        const MANAGE_PROFILE_GROUP = 1 << 16;
28        const MANAGE_PROFILE_TIER = 1 << 17;
29        const MANAGE_PROFILE_SETTINGS = 1 << 18;
30        const MANAGE_GROUP_PERMISSIONS = 1 << 19;
31        const PROMOTE_USERS = 1 << 20;
32        const EDIT_USER = 1 << 21;
33        const ECON_MASTER = 1 << 22;
34        const DELETE_USER = 1 << 23;
35        const CREATE_LABEL = 1 << 24;
36        const MANAGE_WARNINGS = 1 << 25;
37        const MANAGE_REACTIONS = 1 << 26;
38        const EXPORT_DATA = 1 << 27;
39        const MANAGE_LABELS = 1 << 28;
40
41        const _ = !0;
42    }
43}
44
45impl Serialize for FinePermission {
46    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47    where
48        S: serde::Serializer,
49    {
50        serializer.serialize_u32(self.bits())
51    }
52}
53
54struct FinePermissionVisitor;
55impl<'de> Visitor<'de> for FinePermissionVisitor {
56    type Value = FinePermission;
57
58    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
59        formatter.write_str("u32")
60    }
61
62    fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
63    where
64        E: DeError,
65    {
66        if let Some(permission) = FinePermission::from_bits(value) {
67            Ok(permission)
68        } else {
69            Ok(FinePermission::from_bits_retain(value))
70        }
71    }
72
73    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
74    where
75        E: DeError,
76    {
77        if let Some(permission) = FinePermission::from_bits(value as u32) {
78            Ok(permission)
79        } else {
80            Ok(FinePermission::from_bits_retain(value as u32))
81        }
82    }
83
84    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
85    where
86        E: DeError,
87    {
88        if let Some(permission) = FinePermission::from_bits(value as u32) {
89            Ok(permission)
90        } else {
91            Ok(FinePermission::from_bits_retain(value as u32))
92        }
93    }
94}
95
96impl<'de> Deserialize<'de> for FinePermission {
97    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
98    where
99        D: Deserializer<'de>,
100    {
101        deserializer.deserialize_any(FinePermissionVisitor)
102    }
103}
104
105impl FinePermission {
106    /// Join two [`FinePermission`]s into a single `u32`.
107    pub fn join(lhs: FinePermission, rhs: FinePermission) -> FinePermission {
108        lhs | rhs
109    }
110
111    /// Check if the given `input` contains the given [`FinePermission`].
112    pub fn check(self, permission: FinePermission) -> bool {
113        if (self & FinePermission::ADMINISTRATOR) == FinePermission::ADMINISTRATOR {
114            // has administrator permission, meaning everything else is automatically true
115            return true;
116        }
117
118        (self & permission) == permission
119    }
120
121    /// Check if thhe given [`FinePermission`] is qualifies as "Helper" status.
122    pub fn check_helper(self) -> bool {
123        self.check(FinePermission::MANAGE_QUESTIONS)
124            && self.check(FinePermission::MANAGE_RESPONSES)
125            && self.check(FinePermission::MANAGE_COMMENTS)
126            && self.check(FinePermission::MANAGE_WARNINGS)
127            && self.check(FinePermission::VIEW_REPORTS)
128            && self.check(FinePermission::VIEW_AUDIT_LOG)
129    }
130
131    /// Check if thhe given [`FinePermission`] is qualifies as "Manager" status.
132    pub fn check_manager(self) -> bool {
133        self.check_helper()
134            && self.check(FinePermission::DELETE_USER)
135            && self.check(FinePermission::BAN_IP)
136            && self.check(FinePermission::UNBAN_IP)
137            && self.check(FinePermission::VIEW_PROFILE_MANAGE)
138    }
139}
140
141impl Default for FinePermission {
142    fn default() -> Self {
143        Self::DEFAULT
144    }
145}