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)]
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)]
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)]
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
265#[derive(Serialize, Deserialize, Described)]
296#[metadata_type(ElasticMeta)]
297#[metadata(index=false, store=false)]
298pub struct ApiKey {
299 pub acl: Vec<AclCatagory>,
301 pub password: String,
303 #[serde(default)]
305 pub roles: Vec<UserRole>,
306}
307
308#[derive(Serialize, Deserialize, Described)]
310#[metadata_type(ElasticMeta)]
311#[metadata(index=false, store=false)]
312pub struct Apps {
313 pub client_id: String,
315 pub netloc: String,
317 pub scope: Scope,
319 pub server: String,
321 #[serde(default)]
323 pub roles: Vec<UserRole>,
324}
325
326#[derive(Serialize, Deserialize, Described)]
328#[metadata_type(ElasticMeta)]
329#[metadata(index=true, store=true)]
330pub struct User {
331 #[metadata(index=false, store=false)]
333 #[serde(default)]
334 pub agrees_with_tos: Option<DateTime<Utc>>,
335 #[metadata(store=false, mapping="integer")]
337 #[serde(default)]
338 pub api_quota: Option<u64>,
339 #[metadata(store=false, mapping="integer")]
341 #[serde(default)]
342 pub api_daily_quota: Option<u64>,
343 #[metadata(index=false, store=false)]
345 #[serde(default)]
346 pub apikeys: HashMap<String, ApiKey>,
347 #[metadata(index=false, store=false)]
349 #[serde(default)]
350 pub apps: HashMap<String, Apps>,
351 #[metadata(index=false, store=false)]
353 #[serde(default)]
354 pub can_impersonate: bool,
355 #[metadata(copyto="__text__")]
357 #[serde(flatten, default="unrestricted_expanding_classification")]
358 pub classification: ExpandingClassification<true>,
359 #[metadata(store=false, copyto="__text__")]
361 #[serde(default)]
362 pub dn: Option<String>,
363 #[metadata(copyto="__text__")]
365 #[serde(default)]
366 pub email: Option<Email>,
367 #[metadata(copyto="__text__")]
369 #[serde(default)]
370 pub groups: Vec<UpperString>,
371 #[metadata(copyto="__text__", store=false)]
373 #[serde(default)]
374 identity_id: Option<String>,
375 #[serde(default="default_user_is_active")]
377 pub is_active: bool,
378 #[metadata(copyto="__text__")]
380 pub name: String,
381 #[metadata(index=false, store=false)]
383 #[serde(default)]
384 pub otp_sk: Option<String>,
385 #[metadata(index=false, store=false)]
387 pub password: String,
388 #[metadata(store=false, mapping="integer")]
390 #[serde(default)]
391 pub submission_quota: Option<u64>,
392 #[metadata(store=false, mapping="integer")]
394 #[serde(default)]
395 pub submission_async_quota: Option<u64>,
396 #[metadata(store=false, mapping="integer")]
398 #[serde(default)]
399 pub submission_daily_quota: Option<u64>,
400 #[serde(rename="type", default="default_user_types")]
402 pub user_types: Vec<UserType>,
403 #[serde(default)]
405 pub roles: Vec<UserRole>,
406 #[metadata(index=false, store=false)]
408 #[serde(default)]
409 pub security_tokens: HashMap<String, String>,
410 #[metadata(copyto="__text__")]
412 pub uname: String,
413}
414
415fn default_user_types() -> Vec<UserType> { vec![UserType::User] }
416fn default_user_is_active() -> bool { true }
417
418impl Readable for User {
419 fn set_from_archive(&mut self, _from_archive: bool) {}
420}
421
422impl User {
423 pub fn create_test_user() -> Self {
424 User {
425 agrees_with_tos: None,
426 api_quota: None,
427 api_daily_quota: None,
428 apikeys: Default::default(),
429 apps: Default::default(),
430 can_impersonate: false,
431 classification: ExpandingClassification::try_unrestricted().unwrap(),
432 dn: None,
433 email: None,
434 groups: Default::default(),
435 identity_id: None,
436 is_active: default_user_is_active(),
437 name: "User".to_owned(),
438 otp_sk: None,
439 password: Default::default(),
440 submission_quota: None,
441 submission_async_quota: None,
442 submission_daily_quota: None,
443 user_types: default_user_types(),
444 roles: Default::default(),
445 security_tokens: Default::default(),
446 uname: "user".to_owned(),
447 }
448 }
449}
450
451