malwaredb_server/db/
admin.rs1use chrono::{DateTime, Utc};
4use std::fmt::{Display, Formatter};
5
6#[allow(clippy::struct_excessive_bools)]
8#[derive(Clone, Debug, PartialEq, Eq)]
9pub struct User {
10 pub id: u32,
12
13 pub email: String,
15
16 pub uname: String,
18
19 pub fname: String,
21
22 pub lname: String,
24
25 pub org: Option<String>,
27
28 pub phone: Option<String>,
30
31 pub has_password: bool,
33
34 pub has_api_key: bool,
36
37 pub created: DateTime<Utc>,
39
40 pub is_readonly: bool,
42
43 #[cfg(feature = "anonymous")]
45 pub is_anonymous_user: bool,
46}
47
48impl Display for User {
49 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
50 let has_password = {
51 if self.has_password {
52 "password set"
53 } else {
54 "no password"
55 }
56 };
57 let has_api_key = {
58 if self.has_api_key {
59 "API key set"
60 } else {
61 "no API key"
62 }
63 };
64 let org = {
65 if let Some(org) = &self.org {
66 format!(" ({org}) ")
67 } else {
68 String::new()
69 }
70 };
71 let phone = {
72 if let Some(ph) = &self.phone {
73 format!(" {ph} ")
74 } else {
75 String::new()
76 }
77 };
78
79 let readonly = if self.is_readonly { " read only" } else { "" };
80
81 let anon = {
82 #[cfg(feature = "anonymous")]
83 if self.is_anonymous_user {
84 " anonymous access account"
85 } else {
86 ""
87 }
88 #[cfg(not(feature = "anonymous"))]
89 ""
90 };
91
92 write!(
93 f,
94 "{}: {} {} {}<{}>,{phone}{org}{has_password}, {has_api_key} created {}{readonly}{anon}",
95 self.id, self.fname, self.lname, self.uname, self.email, self.created
96 )
97 }
98}
99
100#[derive(Clone, Debug)]
103pub struct Group {
104 pub id: u32,
106
107 pub name: String,
109
110 pub description: Option<String>,
112
113 pub parent: Option<String>,
115
116 pub members: Vec<User>,
118
119 pub sources: Vec<Source>,
121
122 pub files: u32,
124}
125
126impl Display for Group {
127 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
128 let parent = if let Some(p) = &self.parent {
129 format!("Parent: {p}")
130 } else {
131 String::new()
132 };
133
134 let sources_label = match self.sources.len() {
135 0 => "no sources".into(),
136 1 => "one source".into(),
137 x => format!("{x} sources:"),
138 };
139
140 let members_label = match self.members.len() {
141 0 => "no members".into(),
142 1 => "one member".into(),
143 x => format!("{x} members:"),
144 };
145
146 if let Some(desc) = &self.description {
147 writeln!(
148 f,
149 "{}: {} {parent} {} files -- {desc} {members_label} {sources_label}",
150 self.id, self.name, self.files
151 )?;
152 } else {
153 writeln!(
154 f,
155 "{}: {} {parent} {} files -- {members_label} {sources_label}",
156 self.id, self.name, self.files
157 )?;
158 }
159
160 writeln!(f, "Members:")?;
161 for user in &self.members {
162 writeln!(f, "\t{user}")?;
163 }
164
165 writeln!(f, "Sources:")?;
166 for source in &self.sources {
167 writeln!(f, "\t{source}")?;
168 }
169
170 Ok(())
171 }
172}
173
174#[derive(Clone, Debug, PartialEq, Eq)]
176pub struct Source {
177 pub id: u32,
179
180 pub name: String,
182
183 pub description: Option<String>,
185
186 pub url: Option<String>,
188
189 pub date: DateTime<chrono::Local>,
191
192 pub parent: Option<String>,
194
195 pub files: u64,
197
198 pub groups: u32,
200
201 pub malicious: Option<bool>,
203}
204
205impl Display for Source {
206 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
207 write!(f, "{}: {}", self.id, self.name)?;
208 if let Some(url) = &self.url {
209 write!(f, " {url}")?;
210 }
211 if let Some(desc) = &self.description {
212 write!(f, " {desc}")?;
213 }
214 if let Some(is_malicious) = &self.malicious {
215 write!(f, ", known malicious {is_malicious},")?;
216 }
217 if let Some(parent) = &self.parent {
218 write!(f, ", parent {parent},")?;
219 }
220 write!(f, " {} files and {} groups from {}", self.files, self.groups, self.date)?;
221 Ok(())
222 }
223}