nextcloud_users/user/
profile.rs1use std::fmt;
2
3use serde::{Deserialize, Deserializer, Serialize};
4
5use super::Quota;
6use crate::wire::lossy_bool;
7
8const REDACTED: &str = "<redacted>";
10
11#[derive(Clone, Default, PartialEq, Serialize)]
21pub struct User {
22 pub id: String,
24 pub display_name: String,
26 pub email: Option<String>,
28 pub enabled: bool,
30 pub quota: Quota,
32 pub groups: Vec<String>,
34 pub subadmin: Vec<String>,
36 pub storage_location: Option<String>,
38 pub backend: Option<String>,
40}
41
42#[derive(Deserialize)]
43struct UserWire {
44 #[serde(default)]
45 id: String,
46 #[serde(default)]
47 displayname: Option<String>,
48 #[serde(default, rename = "display-name")]
49 display_name_hyphen: Option<String>,
50 #[serde(default)]
51 display_name: Option<String>,
52 #[serde(default)]
53 email: Option<String>,
54 #[serde(default = "default_enabled", deserialize_with = "lossy_bool")]
55 enabled: bool,
56 #[serde(default)]
57 quota: Quota,
58 #[serde(default)]
59 groups: Vec<String>,
60 #[serde(default)]
61 subadmin: Vec<String>,
62 #[serde(default)]
63 storage_location: Option<String>,
64 #[serde(default, rename = "storageLocation")]
65 storage_location_camel: Option<String>,
66 #[serde(default, rename = "home")]
67 home: Option<String>,
68 #[serde(default)]
69 backend: Option<String>,
70}
71
72impl<'de> Deserialize<'de> for User {
73 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
74 let wire = UserWire::deserialize(deserializer)?;
75 let display_name = wire
76 .displayname
77 .or(wire.display_name_hyphen)
78 .or(wire.display_name)
79 .unwrap_or_default();
80 let storage_location = wire
81 .storage_location
82 .or(wire.storage_location_camel)
83 .or(wire.home);
84 Ok(Self {
85 id: wire.id,
86 display_name,
87 email: wire.email,
88 enabled: wire.enabled,
89 quota: wire.quota,
90 groups: wire.groups,
91 subadmin: wire.subadmin,
92 storage_location,
93 backend: wire.backend,
94 })
95 }
96}
97
98const fn default_enabled() -> bool {
99 true
100}
101
102impl User {
103 pub fn id(&self) -> &str {
105 &self.id
106 }
107
108 pub fn display_name(&self) -> &str {
110 &self.display_name
111 }
112
113 pub fn email(&self) -> Option<&str> {
115 self.email.as_deref()
116 }
117
118 pub const fn is_enabled(&self) -> bool {
120 self.enabled
121 }
122
123 pub const fn quota(&self) -> &Quota {
125 &self.quota
126 }
127
128 pub fn groups(&self) -> &[String] {
130 &self.groups
131 }
132
133 pub fn subadmin(&self) -> &[String] {
135 &self.subadmin
136 }
137
138 pub fn storage_location(&self) -> Option<&str> {
140 self.storage_location.as_deref()
141 }
142
143 pub fn backend(&self) -> Option<&str> {
145 self.backend.as_deref()
146 }
147}
148
149impl fmt::Debug for User {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 f.debug_struct("User")
152 .field("id", &self.id)
153 .field("display_name", &self.display_name)
154 .field("email", &self.email.as_ref().map(|_| REDACTED))
155 .field("enabled", &self.enabled)
156 .field("quota", &self.quota)
157 .field("groups", &self.groups)
158 .field("subadmin", &self.subadmin)
159 .field(
160 "storage_location",
161 &self.storage_location.as_ref().map(|_| REDACTED),
162 )
163 .field("backend", &self.backend)
164 .finish()
165 }
166}