use chrono::{DateTime, Utc};
use std::fmt::{Display, Formatter};
#[derive(Clone, Debug)]
pub struct User {
pub id: u32,
pub email: String,
pub uname: String,
pub fname: String,
pub lname: String,
pub org: Option<String>,
pub phone: Option<String>,
pub has_password: bool,
pub has_api_key: bool,
pub created: DateTime<Utc>,
pub is_readonly: bool,
}
impl Display for User {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let has_password = {
if self.has_password {
"password set"
} else {
"no password"
}
};
let has_api_key = {
if self.has_api_key {
"API key set"
} else {
"no API key"
}
};
let org = {
if let Some(org) = &self.org {
format!(" ({org}) ")
} else {
String::new()
}
};
let phone = {
if let Some(ph) = &self.phone {
format!(" {ph} ")
} else {
String::new()
}
};
let readonly = if self.is_readonly { " read only" } else { "" };
write!(
f,
"{}: {} {} {}<{}>,{phone}{org}{has_password}, {has_api_key} created {}{readonly}",
self.id, self.fname, self.lname, self.uname, self.email, self.created
)
}
}
#[derive(Clone, Debug)]
pub struct Group {
pub id: u32,
pub name: String,
pub description: Option<String>,
pub parent: Option<String>,
pub members: Vec<User>,
pub sources: Vec<Source>,
pub files: u32,
}
impl Display for Group {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let parent = if let Some(p) = &self.parent {
format!("Parent: {p}")
} else {
String::new()
};
let sources_label = match self.sources.len() {
0 => "no sources".into(),
1 => "one source".into(),
x => format!("{x} sources:"),
};
let members_label = match self.members.len() {
0 => "no members".into(),
1 => "one member".into(),
x => format!("{x} members:"),
};
if let Some(desc) = &self.description {
writeln!(
f,
"{}: {} {parent} {} files -- {desc} {members_label} {sources_label}",
self.id, self.name, self.files
)?;
} else {
writeln!(
f,
"{}: {} {parent} {} files -- {members_label} {sources_label}",
self.id, self.name, self.files
)?;
}
writeln!(f, "Members:")?;
for user in &self.members {
writeln!(f, "\t{user}")?;
}
writeln!(f, "Sources:")?;
for source in &self.sources {
writeln!(f, "\t{source}")?;
}
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct Source {
pub id: u32,
pub name: String,
pub description: Option<String>,
pub url: Option<String>,
pub date: chrono::DateTime<chrono::Local>,
pub parent: Option<String>,
pub files: u64,
pub groups: u32,
pub malicious: Option<bool>,
}
impl Display for Source {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.id, self.name)?;
if let Some(url) = &self.url {
write!(f, " {url}")?;
}
if let Some(desc) = &self.description {
write!(f, " {desc}")?;
}
if let Some(is_malicious) = &self.malicious {
write!(f, ", known malicious {is_malicious},")?;
}
if let Some(parent) = &self.parent {
write!(f, ", parent {parent},")?;
}
write!(
f,
" {} files and {} groups from {}",
self.files, self.groups, self.date
)?;
Ok(())
}
}