Skip to main content

malwaredb_server/db/
admin.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use chrono::{DateTime, Utc};
4use std::fmt::{Display, Formatter};
5
6/// User record
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct User {
9    /// User ID, for database relations
10    pub id: u32,
11
12    /// Email address
13    pub email: String,
14
15    /// Username, unique
16    pub uname: String,
17
18    /// First name
19    pub fname: String,
20
21    /// Last name
22    pub lname: String,
23
24    /// Organization, optional
25    pub org: Option<String>,
26
27    /// Phone number, optional
28    pub phone: Option<String>,
29
30    /// If a password is set
31    pub has_password: bool,
32
33    /// If the user has logged in and fetched an API key
34    pub has_api_key: bool,
35
36    /// Creation timestamp
37    pub created: DateTime<Utc>,
38
39    /// User is readonly
40    pub is_readonly: bool,
41}
42
43impl Display for User {
44    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
45        let has_password = {
46            if self.has_password {
47                "password set"
48            } else {
49                "no password"
50            }
51        };
52        let has_api_key = {
53            if self.has_api_key {
54                "API key set"
55            } else {
56                "no API key"
57            }
58        };
59        let org = {
60            if let Some(org) = &self.org {
61                format!(" ({org}) ")
62            } else {
63                String::new()
64            }
65        };
66        let phone = {
67            if let Some(ph) = &self.phone {
68                format!(" {ph} ")
69            } else {
70                String::new()
71            }
72        };
73
74        let readonly = if self.is_readonly { " read only" } else { "" };
75
76        write!(
77            f,
78            "{}: {} {} {}<{}>,{phone}{org}{has_password}, {has_api_key} created {}{readonly}",
79            self.id, self.fname, self.lname, self.uname, self.email, self.created
80        )
81    }
82}
83
84/// Group record
85
86#[derive(Clone, Debug)]
87pub struct Group {
88    /// Group ID, for database relations
89    pub id: u32,
90
91    /// Group name
92    pub name: String,
93
94    /// Optional description
95    pub description: Option<String>,
96
97    /// Parent group, if present
98    pub parent: Option<String>,
99
100    /// Members of the group
101    pub members: Vec<User>,
102
103    /// Sources available to the group
104    pub sources: Vec<Source>,
105
106    /// Number of files accessible by the group
107    pub files: u32,
108}
109
110impl Display for Group {
111    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
112        let parent = if let Some(p) = &self.parent {
113            format!("Parent: {p}")
114        } else {
115            String::new()
116        };
117
118        let sources_label = match self.sources.len() {
119            0 => "no sources".into(),
120            1 => "one source".into(),
121            x => format!("{x} sources:"),
122        };
123
124        let members_label = match self.members.len() {
125            0 => "no members".into(),
126            1 => "one member".into(),
127            x => format!("{x} members:"),
128        };
129
130        if let Some(desc) = &self.description {
131            writeln!(
132                f,
133                "{}: {} {parent} {} files -- {desc} {members_label} {sources_label}",
134                self.id, self.name, self.files
135            )?;
136        } else {
137            writeln!(
138                f,
139                "{}: {} {parent} {} files -- {members_label} {sources_label}",
140                self.id, self.name, self.files
141            )?;
142        }
143
144        writeln!(f, "Members:")?;
145        for user in &self.members {
146            writeln!(f, "\t{user}")?;
147        }
148
149        writeln!(f, "Sources:")?;
150        for source in &self.sources {
151            writeln!(f, "\t{source}")?;
152        }
153
154        Ok(())
155    }
156}
157
158/// Source of samples in Malware DB
159#[derive(Clone, Debug, PartialEq, Eq)]
160pub struct Source {
161    /// ID of the source
162    pub id: u32,
163
164    /// Name of the source
165    pub name: String,
166
167    /// Description of the source
168    pub description: Option<String>,
169
170    /// Website of the source, or where the source's data may be found
171    pub url: Option<String>,
172
173    /// Date of first acquisition from the source, or creation date of the source
174    pub date: DateTime<chrono::Local>,
175
176    /// Name of the parent source
177    pub parent: Option<String>,
178
179    /// Amount of files originating from this source
180    pub files: u64,
181
182    /// Number of groups which may access this source
183    pub groups: u32,
184
185    /// Whether this source is known to host malware
186    pub malicious: Option<bool>,
187}
188
189impl Display for Source {
190    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
191        write!(f, "{}: {}", self.id, self.name)?;
192        if let Some(url) = &self.url {
193            write!(f, " {url}")?;
194        }
195        if let Some(desc) = &self.description {
196            write!(f, " {desc}")?;
197        }
198        if let Some(is_malicious) = &self.malicious {
199            write!(f, ", known malicious {is_malicious},")?;
200        }
201        if let Some(parent) = &self.parent {
202            write!(f, ", parent {parent},")?;
203        }
204        write!(f, " {} files and {} groups from {}", self.files, self.groups, self.date)?;
205        Ok(())
206    }
207}