ratchjob/common/model/
privilege.rs

1use crate::common::pb::data_object::PrivilegeGroupDo;
2use bitflags::bitflags;
3use serde::{Deserialize, Serialize};
4use std::borrow::Cow;
5use std::collections::HashSet;
6use std::sync::Arc;
7
8bitflags! {
9    /// Represents a set of flags.
10    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11    pub struct PrivilegeGroupFlags: u8 {
12        /// The value `ENABLE`, at bit position `0`.
13        const ENABLE = 0b00000001;
14        /// The value `WHILE_LIST_IS_ALL`, at bit position `1`.
15        const WHILE_LIST_IS_ALL = 0b00000010;
16        /// The value `BLACK_LIST_IS_ALL`, at bit position `2`.
17        const BLACK_LIST_IS_ALL= 0b00000100;
18    }
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, Default)]
22#[serde(rename_all = "camelCase")]
23pub struct PrivilegeGroupOptionParam<T>
24where
25    T: Sized + std::hash::Hash + std::cmp::Eq,
26{
27    pub whitelist_is_all: Option<bool>,
28    pub whitelist: Option<Arc<HashSet<T>>>,
29    pub blacklist_is_all: Option<bool>,
30    pub blacklist: Option<Arc<HashSet<T>>>,
31}
32
33impl<T> PrivilegeGroupOptionParam<T>
34where
35    T: Sized + std::hash::Hash + std::cmp::Eq,
36{
37    pub fn is_none(&self) -> bool {
38        self.whitelist_is_all.is_none()
39            && self.whitelist.is_none()
40            && self.blacklist_is_all.is_none()
41            && self.blacklist.is_none()
42    }
43}
44
45///
46/// 数据权限组
47/// 支持分别设置黑白名单
48#[derive(Debug, Clone, Serialize, Deserialize)]
49#[serde(rename_all = "camelCase")]
50pub struct PrivilegeGroup<T>
51where
52    T: Sized + std::hash::Hash + std::cmp::Eq,
53{
54    pub enabled: bool,
55    pub whitelist_is_all: bool,
56    pub whitelist: Option<Arc<HashSet<T>>>,
57    pub blacklist_is_all: bool,
58    pub blacklist: Option<Arc<HashSet<T>>>,
59}
60
61impl<T> Default for PrivilegeGroup<T>
62where
63    T: Sized + std::hash::Hash + std::cmp::Eq,
64{
65    fn default() -> Self {
66        Self::all()
67    }
68}
69
70impl<T> PrivilegeGroup<T>
71where
72    T: Sized + std::hash::Hash + std::cmp::Eq,
73{
74    pub fn new(
75        flags: u8,
76        whitelist: Option<Arc<HashSet<T>>>,
77        blacklist: Option<Arc<HashSet<T>>>,
78    ) -> PrivilegeGroup<T> {
79        let enabled = flags & PrivilegeGroupFlags::ENABLE.bits() > 0;
80        let white_list_is_all = flags & PrivilegeGroupFlags::WHILE_LIST_IS_ALL.bits() > 0;
81        let black_list_is_all = flags & PrivilegeGroupFlags::BLACK_LIST_IS_ALL.bits() > 0;
82        Self {
83            enabled,
84            whitelist_is_all: white_list_is_all,
85            blacklist_is_all: black_list_is_all,
86            whitelist,
87            blacklist,
88        }
89    }
90
91    pub fn empty() -> Self {
92        Self {
93            enabled: true,
94            whitelist_is_all: false,
95            whitelist: None,
96            blacklist_is_all: false,
97            blacklist: None,
98        }
99    }
100
101    pub fn all() -> Self {
102        Self {
103            enabled: true,
104            whitelist_is_all: true,
105            whitelist: None,
106            blacklist_is_all: false,
107            blacklist: None,
108        }
109    }
110
111    pub fn is_all(&self) -> bool {
112        self.enabled && self.whitelist_is_all && self.blacklist_is_empty()
113    }
114
115    fn blacklist_is_empty(&self) -> bool {
116        if self.blacklist_is_all {
117            return false;
118        }
119        if let Some(blacklist) = &self.blacklist {
120            blacklist.is_empty()
121        } else {
122            true
123        }
124    }
125
126    pub fn get_flags(&self) -> u8 {
127        let mut v = 0;
128        if self.enabled {
129            v |= PrivilegeGroupFlags::ENABLE.bits();
130        }
131        if self.whitelist_is_all {
132            v |= PrivilegeGroupFlags::WHILE_LIST_IS_ALL.bits();
133        }
134        if self.blacklist_is_all {
135            v |= PrivilegeGroupFlags::BLACK_LIST_IS_ALL.bits();
136        }
137        v
138    }
139
140    pub fn set_flags(&mut self, flags: u8) {
141        self.enabled = flags & PrivilegeGroupFlags::ENABLE.bits() > 0;
142        self.whitelist_is_all = flags & PrivilegeGroupFlags::WHILE_LIST_IS_ALL.bits() > 0;
143        self.blacklist_is_all = flags & PrivilegeGroupFlags::BLACK_LIST_IS_ALL.bits() > 0;
144    }
145
146    pub fn check_permission(&self, key: &T) -> bool {
147        self.at_whitelist(key) && !self.at_blacklist(key)
148    }
149
150    pub fn check_option_value_permission(&self, key: &Option<T>, empty_default: bool) -> bool {
151        if let Some(key) = key {
152            self.at_whitelist(key) && !self.at_blacklist(key)
153        } else {
154            empty_default
155        }
156    }
157
158    fn at_whitelist(&self, key: &T) -> bool {
159        if self.whitelist_is_all {
160            return true;
161        }
162        if let Some(list) = &self.whitelist {
163            list.contains(key)
164        } else {
165            false
166        }
167    }
168
169    fn at_blacklist(&self, key: &T) -> bool {
170        if self.blacklist_is_all {
171            return true;
172        }
173        if let Some(list) = &self.blacklist {
174            list.contains(key)
175        } else {
176            false
177        }
178    }
179
180    pub fn update(&mut self, options: PrivilegeGroupOptionParam<T>) {
181        if let Some(enabled) = options.whitelist_is_all {
182            self.whitelist_is_all = enabled;
183        }
184        if let Some(whitelist) = options.whitelist {
185            self.whitelist = Some(whitelist);
186        }
187        if let Some(blacklist_is_all) = options.blacklist_is_all {
188            self.blacklist_is_all = blacklist_is_all;
189        }
190        if let Some(blacklist) = options.blacklist {
191            self.blacklist = Some(blacklist);
192        }
193    }
194
195    pub fn update_option(&mut self, options: Option<PrivilegeGroupOptionParam<T>>) {
196        if let Some(param) = options {
197            self.update(param)
198        }
199    }
200}
201
202impl PrivilegeGroup<Arc<String>> {
203    pub fn to_do(&self) -> PrivilegeGroupDo<'_> {
204        let whitelist = if let Some(whitelist) = &self.whitelist {
205            whitelist
206                .iter()
207                .map(|w| Cow::Borrowed(w.as_str()))
208                .collect()
209        } else {
210            vec![]
211        };
212        let blacklist = if let Some(blacklist) = &self.blacklist {
213            blacklist
214                .iter()
215                .map(|b| Cow::Borrowed(b.as_str()))
216                .collect()
217        } else {
218            vec![]
219        };
220        PrivilegeGroupDo {
221            enabled: self.enabled,
222            whitelist_is_all: self.whitelist_is_all,
223            whitelist,
224            blacklist_is_all: self.blacklist_is_all,
225            blacklist,
226        }
227    }
228}
229
230impl<'a> From<PrivilegeGroupDo<'a>> for PrivilegeGroup<Arc<String>> {
231    fn from(value: PrivilegeGroupDo<'a>) -> Self {
232        PrivilegeGroup {
233            enabled: value.enabled,
234            whitelist_is_all: value.whitelist_is_all,
235            whitelist: Some(Arc::new(
236                value
237                    .whitelist
238                    .into_iter()
239                    .map(|s| Arc::new(s.to_string()))
240                    .collect(),
241            )),
242            blacklist_is_all: value.blacklist_is_all,
243            blacklist: Some(Arc::new(
244                value
245                    .blacklist
246                    .into_iter()
247                    .map(|s| Arc::new(s.to_string()))
248                    .collect(),
249            )),
250        }
251    }
252}