use std::fmt;
use serde::{Deserialize, Deserializer, Serialize};
use super::Quota;
use crate::wire::lossy_bool;
const REDACTED: &str = "<redacted>";
#[derive(Clone, Default, PartialEq, Serialize)]
pub struct User {
pub id: String,
pub display_name: String,
pub email: Option<String>,
pub enabled: bool,
pub quota: Quota,
pub groups: Vec<String>,
pub subadmin: Vec<String>,
pub storage_location: Option<String>,
pub backend: Option<String>,
}
#[derive(Deserialize)]
struct UserWire {
#[serde(default)]
id: String,
#[serde(default)]
displayname: Option<String>,
#[serde(default, rename = "display-name")]
display_name_hyphen: Option<String>,
#[serde(default)]
display_name: Option<String>,
#[serde(default)]
email: Option<String>,
#[serde(default = "default_enabled", deserialize_with = "lossy_bool")]
enabled: bool,
#[serde(default)]
quota: Quota,
#[serde(default)]
groups: Vec<String>,
#[serde(default)]
subadmin: Vec<String>,
#[serde(default)]
storage_location: Option<String>,
#[serde(default, rename = "storageLocation")]
storage_location_camel: Option<String>,
#[serde(default, rename = "home")]
home: Option<String>,
#[serde(default)]
backend: Option<String>,
}
impl<'de> Deserialize<'de> for User {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let wire = UserWire::deserialize(deserializer)?;
let display_name = wire
.displayname
.or(wire.display_name_hyphen)
.or(wire.display_name)
.unwrap_or_default();
let storage_location = wire
.storage_location
.or(wire.storage_location_camel)
.or(wire.home);
Ok(Self {
id: wire.id,
display_name,
email: wire.email,
enabled: wire.enabled,
quota: wire.quota,
groups: wire.groups,
subadmin: wire.subadmin,
storage_location,
backend: wire.backend,
})
}
}
const fn default_enabled() -> bool {
true
}
impl User {
pub fn id(&self) -> &str {
&self.id
}
pub fn display_name(&self) -> &str {
&self.display_name
}
pub fn email(&self) -> Option<&str> {
self.email.as_deref()
}
pub const fn is_enabled(&self) -> bool {
self.enabled
}
pub const fn quota(&self) -> &Quota {
&self.quota
}
pub fn groups(&self) -> &[String] {
&self.groups
}
pub fn subadmin(&self) -> &[String] {
&self.subadmin
}
pub fn storage_location(&self) -> Option<&str> {
self.storage_location.as_deref()
}
pub fn backend(&self) -> Option<&str> {
self.backend.as_deref()
}
}
impl fmt::Debug for User {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("User")
.field("id", &self.id)
.field("display_name", &self.display_name)
.field("email", &self.email.as_ref().map(|_| REDACTED))
.field("enabled", &self.enabled)
.field("quota", &self.quota)
.field("groups", &self.groups)
.field("subadmin", &self.subadmin)
.field(
"storage_location",
&self.storage_location.as_ref().map(|_| REDACTED),
)
.field("backend", &self.backend)
.finish()
}
}