ratchjob/common/model/
privilege.rs1use 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 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11 pub struct PrivilegeGroupFlags: u8 {
12 const ENABLE = 0b00000001;
14 const WHILE_LIST_IS_ALL = 0b00000010;
16 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#[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}