1use std::collections::HashMap;
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use serde_with::{DeserializeFromStr, SerializeDisplay};
6use struct_metadata::Described;
7use strum::IntoEnumIterator;
8
9use crate::{ElasticMeta, Readable, };
10use crate::types::{Email, UpperString, ExpandingClassification};
11
12
13
14#[derive(SerializeDisplay, DeserializeFromStr, strum::Display, strum::EnumString, strum::FromRepr, Described, Clone, Copy, Debug)]
15#[metadata_type(ElasticMeta)]
16#[strum(serialize_all = "snake_case")]
17pub enum UserType {
18 Admin = 0,
20 User = 1,
22 SignatureManager = 2,
24 SignatureImporter = 3,
26 Viewer = 4,
28 Submitter = 5,
30 Custom = 6,
32}
33
34#[derive(SerializeDisplay, DeserializeFromStr, strum::Display, strum::EnumString, Described, Clone, Copy)]
35#[metadata_type(ElasticMeta)]
36#[strum(serialize_all = "lowercase")]
37pub enum Scope {R, W, RW, C}
38
39
40#[derive(SerializeDisplay, DeserializeFromStr, strum::Display, strum::EnumString, strum::FromRepr, strum::EnumIter, Described, Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)]
41#[metadata_type(ElasticMeta)]
42#[strum(serialize_all = "snake_case")]
43pub enum UserRole {
44 AlertManage = 0,
46 AlertView = 1,
48 ApikeyAccess = 2,
50 BundleDownload = 3,
52 FileDetail = 4,
54 FileDownload = 5,
56 FilePurge = 33,
58 HeuristicView = 6,
60 OboAccess = 7,
62 ReplayTrigger = 8,
64 SafelistView = 9,
66 SafelistManage = 10,
68 SignatureDownload = 11,
70 SignatureView = 12,
72 SubmissionCreate = 13,
74 SubmissionDelete = 14,
76 SubmissionManage = 15,
78 SubmissionView = 16,
80 WorkflowManage = 17,
82 WorkflowView = 18,
84 Administration = 19,
86 ReplaySystem = 20,
88 SignatureImport = 21,
90 SignatureManage = 22,
92 ArchiveView = 23,
94 ArchiveManage = 24,
96 ArchiveTrigger = 25,
98 ArchiveDownload = 26,
100 SelfManage = 27,
102 RetrohuntView = 28,
104 RetrohuntRun = 29,
106 ExternalQuery = 30,
108 BadlistView = 31,
110 BadlistManage = 32,
112 ArchiveComment = 35,
114 AssistantUse = 34,
116 SubmissionCustomize = 36,
118}
119
120const USER_ROLES_BASIC: [UserRole; 31] = [
121 UserRole::AlertManage,
122 UserRole::AlertView,
123 UserRole::ArchiveTrigger,
124 UserRole::ArchiveView,
125 UserRole::ArchiveManage,
126 UserRole::ArchiveDownload,
127 UserRole::ArchiveComment,
128 UserRole::ApikeyAccess,
129 UserRole::BundleDownload,
130 UserRole::ExternalQuery,
131 UserRole::FileDetail,
132 UserRole::FileDownload,
133 UserRole::HeuristicView,
134 UserRole::OboAccess,
135 UserRole::ReplayTrigger,
136 UserRole::SafelistView,
137 UserRole::SafelistManage,
138 UserRole::SelfManage,
139 UserRole::SignatureDownload,
140 UserRole::SignatureView,
141 UserRole::SubmissionCreate,
142 UserRole::SubmissionDelete,
143 UserRole::SubmissionManage,
144 UserRole::SubmissionView,
145 UserRole::WorkflowManage,
146 UserRole::WorkflowView,
147 UserRole::RetrohuntView,
148 UserRole::RetrohuntRun,
149 UserRole::BadlistView,
150 UserRole::BadlistManage,
151 UserRole::SubmissionCustomize,
152];
153
154impl UserType {
164 #[must_use]
165 pub fn roles(&self) -> Vec<UserRole> {
166 match self {
167 UserType::Admin => UserRole::iter().collect(),
168 UserType::SignatureImporter => vec![
169 UserRole::BadlistManage,
170 UserRole::SafelistManage,
171 UserRole::SelfManage,
172 UserRole::SignatureDownload,
173 UserRole::SignatureImport,
174 UserRole::SignatureView
175 ],
176 UserType::SignatureManager => {
177 let mut roles: Vec<_> = UserRole::iter().collect();
178 roles.push(UserRole::SignatureManage);
179 roles
180 },
181 UserType::User => USER_ROLES_BASIC.into_iter().collect(),
182 UserType::Viewer => vec![
183 UserRole::AlertView,
184 UserRole::ApikeyAccess,
185 UserRole::BadlistView,
186 UserRole::FileDetail,
187 UserRole::OboAccess,
188 UserRole::HeuristicView,
189 UserRole::SafelistView,
190 UserRole::SelfManage,
191 UserRole::SignatureView,
192 UserRole::SubmissionView,
193 UserRole::WorkflowView,
194 ],
195 UserType::Submitter => vec![
196 UserRole::ApikeyAccess,
197 UserRole::OboAccess,
198 UserRole::SelfManage,
199 UserRole::SubmissionCreate,
200 UserRole::ReplayTrigger,
201 UserRole::RetrohuntRun,
202 ],
203 UserType::Custom => vec![],
205 }
206 }
207}
208
209
210#[derive(SerializeDisplay, DeserializeFromStr, strum::Display, strum::EnumString, Described, Clone, Copy, Debug, PartialEq, Eq)]
211#[metadata_type(ElasticMeta)]
212pub enum AclCatagory {R, W, E, C}
213
214impl AclCatagory {
215 #[must_use]
216 pub fn roles(&self) -> &[UserRole] {
217 match self {
218 AclCatagory::R => &[
219 UserRole::AlertView,
220 UserRole::ArchiveView,
221 UserRole::ArchiveDownload,
222 UserRole::BadlistView,
223 UserRole::BundleDownload,
224 UserRole::ExternalQuery,
225 UserRole::FileDetail,
226 UserRole::FileDownload,
227 UserRole::HeuristicView,
228 UserRole::SafelistView,
229 UserRole::SignatureDownload,
230 UserRole::SignatureView,
231 UserRole::SubmissionView,
232 UserRole::WorkflowView,
233 UserRole::RetrohuntView,
234 ],
235 AclCatagory::W => &[
236 UserRole::AlertManage,
237 UserRole::ArchiveTrigger,
238 UserRole::ArchiveManage,
239 UserRole::BadlistManage,
240 UserRole::ReplayTrigger,
241 UserRole::SafelistManage,
242 UserRole::SubmissionCreate,
243 UserRole::SubmissionDelete,
244 UserRole::SubmissionManage,
245 UserRole::RetrohuntRun,
246 UserRole::SubmissionCustomize,
247 ],
248 AclCatagory::E => &[
249 UserRole::Administration,
250 UserRole::ApikeyAccess,
251 UserRole::FilePurge,
252 UserRole::OboAccess,
253 UserRole::ReplaySystem,
254 UserRole::SelfManage,
255 UserRole::SignatureImport,
256 UserRole::SignatureManage,
257 UserRole::WorkflowManage
258 ],
259 AclCatagory::C => &[],
260 }
261 }
262}
263
264
265pub fn load_roles_form_acls(acls: &[AclCatagory], current_roles: &[UserRole]) -> Vec<UserRole> {
266 if !current_roles.is_empty() {
268 return current_roles.to_vec()
269 }
270
271 let mut roles = vec![];
273 for acl in acls {
274 roles.extend_from_slice(acl.roles())
275 }
276
277 roles.sort_unstable();
279 roles.dedup();
280 return roles
281}
282
283
284pub fn load_roles(types: &[UserType], current_roles: &[UserRole]) -> Vec<UserRole> {
285 if !current_roles.is_empty() {
287 return current_roles.to_vec()
288 }
289
290 let mut roles = vec![];
292 for user_type in types {
293 roles.extend_from_slice(&user_type.roles());
294 }
295
296 roles.sort_unstable();
298 roles.dedup();
299 return roles
300}
301
302#[derive(Serialize, Deserialize, Described)]
304#[metadata_type(ElasticMeta)]
305#[metadata(index=false, store=false)]
306pub struct Apps {
307 pub client_id: String,
309 pub netloc: String,
311 pub scope: Scope,
313 pub server: String,
315 #[serde(default)]
317 pub roles: Vec<UserRole>,
318}
319
320#[derive(Serialize, Deserialize, Described)]
322#[metadata_type(ElasticMeta)]
323#[metadata(index=true, store=true)]
324pub struct User {
325 #[metadata(index=false, store=false)]
327 #[serde(default)]
328 pub agrees_with_tos: Option<DateTime<Utc>>,
329 #[metadata(store=false, mapping="integer")]
331 #[serde(default)]
332 pub api_quota: Option<u64>,
333 #[metadata(store=false, mapping="integer")]
335 #[serde(default)]
336 pub api_daily_quota: Option<u64>,
337 #[metadata(index=false, store=false)]
343 #[serde(default)]
344 pub apps: HashMap<String, Apps>,
345 #[metadata(index=false, store=false)]
347 #[serde(default)]
348 pub can_impersonate: bool,
349 #[metadata(copyto="__text__")]
351 #[serde(flatten, default="unrestricted_expanding_classification")]
352 pub classification: ExpandingClassification<true>,
353 #[metadata(store=false, copyto="__text__")]
355 #[serde(default)]
356 pub dn: Option<String>,
357 #[metadata(copyto="__text__")]
359 #[serde(default)]
360 pub email: Option<Email>,
361 #[metadata(copyto="__text__")]
363 #[serde(default)]
364 pub groups: Vec<UpperString>,
365 #[metadata(copyto="__text__", store=false)]
367 #[serde(default)]
368 identity_id: Option<String>,
369 #[serde(default="default_user_is_active")]
371 pub is_active: bool,
372 #[metadata(copyto="__text__")]
374 pub name: String,
375 #[metadata(index=false, store=false)]
377 #[serde(default)]
378 pub otp_sk: Option<String>,
379 #[metadata(index=false, store=false)]
381 pub password: String,
382 #[metadata(store=false, mapping="integer")]
384 #[serde(default)]
385 pub submission_quota: Option<u64>,
386 #[metadata(store=false, mapping="integer")]
388 #[serde(default)]
389 pub submission_async_quota: Option<u64>,
390 #[metadata(store=false, mapping="integer")]
392 #[serde(default)]
393 pub submission_daily_quota: Option<u64>,
394 #[serde(rename="type", default="default_user_types")]
396 pub user_types: Vec<UserType>,
397 #[serde(default)]
399 pub roles: Vec<UserRole>,
400 #[metadata(index=false, store=false)]
402 #[serde(default)]
403 pub security_tokens: HashMap<String, String>,
404 #[metadata(copyto="__text__")]
406 pub uname: String,
407}
408
409pub fn default_user_types() -> Vec<UserType> { vec![UserType::User] }
410fn default_user_is_active() -> bool { true }
411
412impl Readable for User {
413 fn set_from_archive(&mut self, _from_archive: bool) {}
414}
415
416impl User {
417 pub fn create_test_user() -> Self {
418 User {
419 agrees_with_tos: None,
420 api_quota: None,
421 api_daily_quota: None,
422 apps: Default::default(),
424 can_impersonate: false,
425 classification: ExpandingClassification::try_unrestricted().unwrap(),
426 dn: None,
427 email: None,
428 groups: Default::default(),
429 identity_id: None,
430 is_active: default_user_is_active(),
431 name: "User".to_owned(),
432 otp_sk: None,
433 password: Default::default(),
434 submission_quota: None,
435 submission_async_quota: None,
436 submission_daily_quota: None,
437 user_types: default_user_types(),
438 roles: Default::default(),
439 security_tokens: Default::default(),
440 uname: "user".to_owned(),
441 }
442 }
443}
444
445