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, Email, ExpandingClassification, Readable, types::UpperString};
10
11
12
13#[derive(SerializeDisplay, DeserializeFromStr, strum::Display, strum::EnumString, strum::FromRepr, Described, Clone, Copy)]
14#[metadata_type(ElasticMeta)]
15#[strum(serialize_all = "snake_case")]
16pub enum UserType {
17 Admin = 0,
19 User = 1,
21 SignatureManager = 2,
23 SignatureImporter = 3,
25 Viewer = 4,
27 Submitter = 5,
29 Custom = 6,
31}
32
33#[derive(SerializeDisplay, DeserializeFromStr, strum::Display, strum::EnumString, Described, Clone, Copy)]
34#[metadata_type(ElasticMeta)]
35#[strum(serialize_all = "lowercase")]
36pub enum Scope {R, W, RW, C}
37
38
39#[derive(SerializeDisplay, DeserializeFromStr, strum::Display, strum::EnumString, strum::FromRepr, strum::EnumIter, Described, Clone, Copy, PartialEq, Eq)]
40#[metadata_type(ElasticMeta)]
41#[strum(serialize_all = "snake_case")]
42pub enum UserRole {
43 AlertManage = 0,
45 AlertView = 1,
47 ApikeyAccess = 2,
49 BundleDownload = 3,
51 FileDetail = 4,
53 FileDownload = 5,
55 FilePurge = 33,
57 HeuristicView = 6,
59 OboAccess = 7,
61 ReplayTrigger = 8,
63 SafelistView = 9,
65 SafelistManage = 10,
67 SignatureDownload = 11,
69 SignatureView = 12,
71 SubmissionCreate = 13,
73 SubmissionDelete = 14,
75 SubmissionManage = 15,
77 SubmissionView = 16,
79 WorkflowManage = 17,
81 WorkflowView = 18,
83 Administration = 19,
85 ReplaySystem = 20,
87 SignatureImport = 21,
89 SignatureManage = 22,
91 ArchiveView = 23,
93 ArchiveManage = 24,
95 ArchiveTrigger = 25,
97 ArchiveDownload = 26,
99 SelfManage = 27,
101 RetrohuntView = 28,
103 RetrohuntRun = 29,
105 ExternalQuery = 30,
107 BadlistView = 31,
109 BadlistManage = 32,
111 ArchiveComment = 35, AssistantUse = 34,
115}
116
117const USER_ROLES_BASIC: [UserRole; 30] = [
118 UserRole::AlertManage,
119 UserRole::AlertView,
120 UserRole::ArchiveTrigger,
121 UserRole::ArchiveView,
122 UserRole::ArchiveManage,
123 UserRole::ArchiveDownload,
124 UserRole::ArchiveComment,
125 UserRole::ApikeyAccess,
126 UserRole::BundleDownload,
127 UserRole::ExternalQuery,
128 UserRole::FileDetail,
129 UserRole::FileDownload,
130 UserRole::HeuristicView,
131 UserRole::OboAccess,
132 UserRole::ReplayTrigger,
133 UserRole::SafelistView,
134 UserRole::SafelistManage,
135 UserRole::SelfManage,
136 UserRole::SignatureDownload,
137 UserRole::SignatureView,
138 UserRole::SubmissionCreate,
139 UserRole::SubmissionDelete,
140 UserRole::SubmissionManage,
141 UserRole::SubmissionView,
142 UserRole::WorkflowManage,
143 UserRole::WorkflowView,
144 UserRole::RetrohuntView,
145 UserRole::RetrohuntRun,
146 UserRole::BadlistView,
147 UserRole::BadlistManage,
148];
149
150impl UserType {
160 #[must_use]
161 pub fn roles(&self) -> Vec<UserRole> {
162 match self {
163 UserType::Admin => UserRole::iter().collect(),
164 UserType::SignatureImporter => vec![
165 UserRole::BadlistManage,
166 UserRole::SafelistManage,
167 UserRole::SelfManage,
168 UserRole::SignatureDownload,
169 UserRole::SignatureImport,
170 UserRole::SignatureView
171 ],
172 UserType::SignatureManager => {
173 let mut roles: Vec<_> = UserRole::iter().collect();
174 roles.push(UserRole::SignatureManage);
175 roles
176 },
177 UserType::User => USER_ROLES_BASIC.into_iter().collect(),
178 UserType::Viewer => vec![
179 UserRole::AlertView,
180 UserRole::ApikeyAccess,
181 UserRole::BadlistView,
182 UserRole::FileDetail,
183 UserRole::OboAccess,
184 UserRole::HeuristicView,
185 UserRole::SafelistView,
186 UserRole::SelfManage,
187 UserRole::SignatureView,
188 UserRole::SubmissionView,
189 UserRole::WorkflowView,
190 ],
191 UserType::Submitter => vec![
192 UserRole::ApikeyAccess,
193 UserRole::OboAccess,
194 UserRole::SelfManage,
195 UserRole::SubmissionCreate,
196 UserRole::ReplayTrigger,
197 UserRole::RetrohuntRun,
198 ],
199 UserType::Custom => vec![],
201 }
202 }
203}
204
205
206#[derive(SerializeDisplay, DeserializeFromStr, strum::Display, strum::EnumString, Described, Clone, Copy)]
207#[metadata_type(ElasticMeta)]
208pub enum AclCatagory {R, W, E, C}
209
210impl AclCatagory {
211 #[must_use]
212 pub fn roles(&self) -> &[UserRole] {
213 match self {
214 AclCatagory::R => &[
215 UserRole::AlertView,
216 UserRole::ArchiveView,
217 UserRole::ArchiveDownload,
218 UserRole::BadlistView,
219 UserRole::BundleDownload,
220 UserRole::ExternalQuery,
221 UserRole::FileDetail,
222 UserRole::FileDownload,
223 UserRole::HeuristicView,
224 UserRole::SafelistView,
225 UserRole::SignatureDownload,
226 UserRole::SignatureView,
227 UserRole::SubmissionView,
228 UserRole::WorkflowView,
229 UserRole::RetrohuntView,
230 ],
231 AclCatagory::W => &[
232 UserRole::AlertManage,
233 UserRole::ArchiveTrigger,
234 UserRole::ArchiveManage,
235 UserRole::BadlistManage,
236 UserRole::ReplayTrigger,
237 UserRole::SafelistManage,
238 UserRole::SubmissionCreate,
239 UserRole::SubmissionDelete,
240 UserRole::SubmissionManage,
241 UserRole::RetrohuntRun,
242 ],
243 AclCatagory::E => &[
244 UserRole::Administration,
245 UserRole::ApikeyAccess,
246 UserRole::FilePurge,
247 UserRole::OboAccess,
248 UserRole::ReplaySystem,
249 UserRole::SelfManage,
250 UserRole::SignatureImport,
251 UserRole::SignatureManage,
252 UserRole::WorkflowManage
253 ],
254 AclCatagory::C => &[],
255 }
256 }
257}
258
259
260#[derive(Serialize, Deserialize, Described)]
291#[metadata_type(ElasticMeta)]
292#[metadata(index=false, store=false)]
293pub struct ApiKey {
294 pub acl: Vec<AclCatagory>,
296 pub password: String,
298 #[serde(default)]
300 pub roles: Vec<UserRole>,
301}
302
303#[derive(Serialize, Deserialize, Described)]
305#[metadata_type(ElasticMeta)]
306#[metadata(index=false, store=false)]
307pub struct Apps {
308 pub client_id: String,
310 pub netloc: String,
312 pub scope: Scope,
314 pub server: String,
316 #[serde(default)]
318 pub roles: Vec<UserRole>,
319}
320
321#[derive(Serialize, Deserialize, Described)]
323#[metadata_type(ElasticMeta)]
324#[metadata(index=true, store=true)]
325pub struct User {
326 #[metadata(index=false, store=false)]
328 #[serde(default)]
329 pub agrees_with_tos: Option<DateTime<Utc>>,
330 #[metadata(store=false, mapping="integer")]
332 #[serde(default)]
333 pub api_quota: Option<u64>,
334 #[metadata(store=false, mapping="integer")]
336 #[serde(default)]
337 pub api_daily_quota: Option<u64>,
338 #[metadata(index=false, store=false)]
340 #[serde(default)]
341 pub apikeys: HashMap<String, ApiKey>,
342 #[metadata(index=false, store=false)]
344 #[serde(default)]
345 pub apps: HashMap<String, Apps>,
346 #[metadata(index=false, store=false)]
348 #[serde(default)]
349 pub can_impersonate: bool,
350 #[metadata(copyto="__text__")]
352 #[serde(flatten, default="unrestricted_expanding_classification")]
353 pub classification: ExpandingClassification<true>,
354 #[metadata(store=false, copyto="__text__")]
356 #[serde(default)]
357 pub dn: Option<String>,
358 #[metadata(copyto="__text__")]
360 #[serde(default)]
361 pub email: Option<Email>,
362 #[metadata(copyto="__text__")]
364 #[serde(default)]
365 pub groups: Vec<UpperString>,
366 #[metadata(copyto="__text__", store=false)]
368 #[serde(default)]
369 identity_id: Option<String>,
370 #[serde(default="default_user_is_active")]
372 pub is_active: bool,
373 #[metadata(copyto="__text__")]
375 pub name: String,
376 #[metadata(index=false, store=false)]
378 #[serde(default)]
379 pub otp_sk: Option<String>,
380 #[metadata(index=false, store=false)]
382 pub password: String,
383 #[metadata(store=false, mapping="integer")]
385 #[serde(default)]
386 pub submission_quota: Option<u64>,
387 #[metadata(store=false, mapping="integer")]
389 #[serde(default)]
390 pub submission_async_quota: Option<u64>,
391 #[metadata(store=false, mapping="integer")]
393 #[serde(default)]
394 pub submission_daily_quota: Option<u64>,
395 #[serde(rename="type", default="default_user_types")]
397 pub user_types: Vec<UserType>,
398 #[serde(default)]
400 pub roles: Vec<UserRole>,
401 #[metadata(index=false, store=false)]
403 #[serde(default)]
404 pub security_tokens: HashMap<String, String>,
405 #[metadata(copyto="__text__")]
407 pub uname: String,
408}
409
410fn default_user_types() -> Vec<UserType> { vec![UserType::User] }
411fn default_user_is_active() -> bool { true }
412
413impl Readable for User {
414 fn set_from_archive(&mut self, _from_archive: bool) {}
415}
416
417impl User {
418 pub fn create_test_user() -> Self {
419 User {
420 agrees_with_tos: None,
421 api_quota: None,
422 api_daily_quota: None,
423 apikeys: Default::default(),
424 apps: Default::default(),
425 can_impersonate: false,
426 classification: ExpandingClassification::try_unrestricted().unwrap(),
427 dn: None,
428 email: None,
429 groups: Default::default(),
430 identity_id: None,
431 is_active: default_user_is_active(),
432 name: "User".to_owned(),
433 otp_sk: None,
434 password: Default::default(),
435 submission_quota: None,
436 submission_async_quota: None,
437 submission_daily_quota: None,
438 user_types: default_user_types(),
439 roles: Default::default(),
440 security_tokens: Default::default(),
441 uname: "user".to_owned(),
442 }
443 }
444}
445
446