1use crate::{FilesClient, PaginationInfo, Result};
11use serde::{Deserialize, Serialize};
12use serde_json::json;
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct UserEntity {
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub id: Option<i64>,
20
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub username: Option<String>,
24
25 #[serde(skip_serializing_if = "Option::is_none")]
27 pub email: Option<String>,
28
29 #[serde(skip_serializing_if = "Option::is_none")]
31 pub name: Option<String>,
32
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub company: Option<String>,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub notes: Option<String>,
40
41 #[serde(skip_serializing_if = "Option::is_none")]
43 pub user_home: Option<String>,
44
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub user_root: Option<String>,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
51 pub site_admin: Option<bool>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub readonly_site_admin: Option<bool>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub disabled: Option<bool>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub disabled_expired_or_inactive: Option<bool>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub ssl_required: Option<String>,
68
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub time_zone: Option<String>,
72
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub language: Option<String>,
76
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub allowed_ips: Option<String>,
80
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub bypass_site_allowed_ips: Option<bool>,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
87 pub group_ids: Option<String>,
88
89 #[serde(skip_serializing_if = "Option::is_none")]
91 pub admin_group_ids: Option<Vec<i64>>,
92
93 #[serde(skip_serializing_if = "Option::is_none")]
95 pub ftp_permission: Option<bool>,
96
97 #[serde(skip_serializing_if = "Option::is_none")]
99 pub sftp_permission: Option<bool>,
100
101 #[serde(skip_serializing_if = "Option::is_none")]
103 pub dav_permission: Option<bool>,
104
105 #[serde(skip_serializing_if = "Option::is_none")]
107 pub restapi_permission: Option<bool>,
108
109 #[serde(skip_serializing_if = "Option::is_none")]
111 pub require_2fa: Option<String>,
112
113 #[serde(skip_serializing_if = "Option::is_none")]
115 pub active_2fa: Option<bool>,
116
117 #[serde(skip_serializing_if = "Option::is_none")]
119 pub created_at: Option<String>,
120
121 #[serde(skip_serializing_if = "Option::is_none")]
123 pub last_login_at: Option<String>,
124
125 #[serde(skip_serializing_if = "Option::is_none")]
127 pub password_set_at: Option<String>,
128
129 #[serde(skip_serializing_if = "Option::is_none")]
131 pub password_validity_days: Option<i64>,
132
133 #[serde(skip_serializing_if = "Option::is_none")]
135 pub api_keys_count: Option<i64>,
136
137 #[serde(skip_serializing_if = "Option::is_none")]
139 pub public_keys_count: Option<i64>,
140}
141
142#[derive(Debug, Clone)]
144pub struct UserHandler {
145 client: FilesClient,
146}
147
148impl UserHandler {
149 pub fn new(client: FilesClient) -> Self {
151 Self { client }
152 }
153
154 pub async fn list(
178 &self,
179 cursor: Option<String>,
180 per_page: Option<i32>,
181 ) -> Result<(Vec<UserEntity>, PaginationInfo)> {
182 let mut path = "/users?".to_string();
183
184 if let Some(c) = cursor {
185 path.push_str(&format!("cursor={}&", c));
186 }
187 if let Some(pp) = per_page {
188 path.push_str(&format!("per_page={}&", pp));
189 }
190
191 let response = self.client.get_raw(&path).await?;
192 let users: Vec<UserEntity> = serde_json::from_value(response)?;
193
194 let pagination = PaginationInfo {
196 cursor_next: None,
197 cursor_prev: None,
198 };
199
200 Ok((users, pagination))
201 }
202
203 pub async fn get(&self, id: i64) -> Result<UserEntity> {
209 let path = format!("/users/{}", id);
210 let response = self.client.get_raw(&path).await?;
211 Ok(serde_json::from_value(response)?)
212 }
213
214 pub async fn create(
241 &self,
242 username: &str,
243 email: Option<&str>,
244 password: Option<&str>,
245 name: Option<&str>,
246 ) -> Result<UserEntity> {
247 let mut body = json!({
248 "username": username,
249 });
250
251 if let Some(e) = email {
252 body["email"] = json!(e);
253 }
254 if let Some(p) = password {
255 body["password"] = json!(p);
256 }
257 if let Some(n) = name {
258 body["name"] = json!(n);
259 }
260
261 let response = self.client.post_raw("/users", body).await?;
262 Ok(serde_json::from_value(response)?)
263 }
264
265 pub async fn update(
275 &self,
276 id: i64,
277 email: Option<&str>,
278 name: Option<&str>,
279 company: Option<&str>,
280 notes: Option<&str>,
281 ) -> Result<UserEntity> {
282 let mut body = json!({});
283
284 if let Some(e) = email {
285 body["email"] = json!(e);
286 }
287 if let Some(n) = name {
288 body["name"] = json!(n);
289 }
290 if let Some(c) = company {
291 body["company"] = json!(c);
292 }
293 if let Some(nt) = notes {
294 body["notes"] = json!(nt);
295 }
296
297 let path = format!("/users/{}", id);
298 let response = self.client.patch_raw(&path, body).await?;
299 Ok(serde_json::from_value(response)?)
300 }
301
302 pub async fn delete(&self, id: i64) -> Result<()> {
308 let path = format!("/users/{}", id);
309 self.client.delete_raw(&path).await?;
310 Ok(())
311 }
312
313 pub async fn unlock(&self, id: i64) -> Result<()> {
319 let path = format!("/users/{}/unlock", id);
320 self.client.post_raw(&path, json!({})).await?;
321 Ok(())
322 }
323
324 pub async fn reset_2fa(&self, id: i64) -> Result<()> {
330 let path = format!("/users/{}/2fa/reset", id);
331 self.client.post_raw(&path, json!({})).await?;
332 Ok(())
333 }
334
335 pub async fn resend_welcome_email(&self, id: i64) -> Result<()> {
341 let path = format!("/users/{}/resend_welcome_email", id);
342 self.client.post_raw(&path, json!({})).await?;
343 Ok(())
344 }
345}
346
347#[cfg(test)]
348mod tests {
349 use super::*;
350
351 #[test]
352 fn test_handler_creation() {
353 let client = FilesClient::builder().api_key("test-key").build().unwrap();
354 let _handler = UserHandler::new(client);
355 }
356}