userlib/dto/
update_user_request.rs

1use 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    /* identical to check_above_2 body */
100}