userlib/dto/
update_user_request.rs1use chrono::NaiveDateTime;
2use common::enums::gender::Gender;
3use common::enums::status::Status;
4use common::utils::serialize_option_naive_date;
5use regex::Regex;
6use serde::de::Error;
7use serde::{Deserialize, Deserializer, Serialize};
8use uuid::Uuid;
9
10use crate::jsonb::address::Address;
11use crate::enums::aboriginality_type::AboriginalityType;
12use crate::jsonb::court_order::CourtOrder;
13use crate::jsonb::emergency_contacts::EmergencyDetails;
14use crate::jsonb::mfa::Mfa;
15use crate::jsonb::visa_info::VisaInfo;
16
17#[derive(Serialize, Deserialize, Default, Clone)]
18#[serde(rename_all = "camelCase")]
19pub struct UpdateUserRequest {
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub addresses: Option<Vec<Address>>,
22 pub first_name: String,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub middle_name: Option<String>,
25 pub last_name: String,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub nickname: Option<String>,
28 #[serde(rename = "password")]
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub shapass: Option<String>,
31 #[serde(default)]
32 #[serde(with = "serialize_option_naive_date")]
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub birthday: Option<NaiveDateTime>,
35 pub email: String,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 #[serde(deserialize_with = "de_phone")]
38 #[serde(default)]
39 pub phone: Option<String>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub site: Option<String>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub last_online: Option<NaiveDateTime>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub last_offline: Option<NaiveDateTime>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub language: Option<String>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub terms_accepted: Option<i32>,
50 pub id: Uuid,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub avatar_path: Option<String>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub status: Option<Status>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub gender: Option<Gender>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub time_zone: Option<String>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub title: Option<String>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub online_status: Option<String>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub mfa: Option<Mfa>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub emergency_contacts: Option<Vec<EmergencyDetails>>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 pub preferred_name: Option<String>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 pub co_enrolment: Option<bool>,
71 #[serde(skip_serializing_if = "Option::is_none")]
72 pub visa_information: Option<VisaInfo>,
73 #[serde(skip_serializing_if = "Option::is_none")]
74 pub orders: Option<Vec<CourtOrder>>,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 pub aboriginality: Option<AboriginalityType>,
77 pub discoverable_external: Option<bool>,
78 pub discoverable_external_admins: Option<bool>,
79 pub discoverable_internal: Option<bool>,
80}
81
82fn de_phone<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
83where
84 D: Deserializer<'de>,
85{
86 let v: Option<String> = Option::deserialize(deserializer)?;
87 if v.is_none() {
88 return Ok(None);
89 }
90 let v = v.unwrap();
91 if v.len() > 20
92 || !Regex::new(r"^[0-9.\-\(\)\*\#\ ]*$")
93 .unwrap()
94 .is_match(v.as_str())
95 {
96 return Err(Error::custom("Invalid phone number"));
97 }
98 Ok(Some(v))
99 }