1use std::collections::HashMap;
16
17use serde::{Deserialize, Serialize};
18
19use crate::client::{get_owner, Client, PostBody, Response};
20use crate::error::Result;
21use crate::serde_util::null_to_default;
22
23#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
26#[serde(rename_all = "camelCase", default)]
27pub struct Ldap {
28 pub id: String,
29 pub owner: String,
30 pub created_time: String,
31
32 pub server_name: String,
33 pub host: String,
34 pub port: i32,
35 pub enable_ssl: bool,
36 pub allow_self_signed_cert: bool,
37 pub username: String,
38 pub password: String,
39 pub base_dn: String,
40 pub filter: String,
41 #[serde(deserialize_with = "null_to_default")]
42 pub filter_fields: Vec<String>,
43 pub default_group: String,
44 #[serde(deserialize_with = "null_to_default")]
45 pub default_groups: Vec<String>,
46 pub password_type: String,
47 #[serde(deserialize_with = "null_to_default")]
48 pub custom_attributes: HashMap<String, String>,
49
50 pub auto_sync: i32,
51 pub last_sync: String,
52 pub enable_groups: bool,
53 pub enable_password_reset: bool,
54}
55
56#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
58#[serde(rename_all = "camelCase", default)]
59pub struct LdapUser {
60 pub uid_number: String,
61 pub uid: String,
62 pub cn: String,
63 pub gid_number: String,
64 pub uuid: String,
65 pub user_principal_name: String,
66 pub display_name: String,
67 #[serde(rename = "Mail")]
68 pub mail: String,
69 pub email: String,
70 #[serde(rename = "EmailAddress")]
71 pub email_address: String,
72 #[serde(rename = "TelephoneNumber")]
73 pub telephone_number: String,
74 pub mobile: String,
75 #[serde(rename = "MobileTelephoneNumber")]
76 pub mobile_telephone_number: String,
77 #[serde(rename = "RegisteredAddress")]
78 pub registered_address: String,
79 #[serde(rename = "PostalAddress")]
80 pub postal_address: String,
81 pub country: String,
82 pub country_name: String,
83
84 pub group_id: String,
85 pub address: String,
86 #[serde(deserialize_with = "null_to_default")]
87 pub member_of: Vec<String>,
88 #[serde(deserialize_with = "null_to_default")]
89 pub attributes: HashMap<String, String>,
90}
91
92#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
94#[serde(rename_all = "camelCase", default)]
95pub struct LdapUsersResponse {
96 #[serde(deserialize_with = "null_to_default")]
97 pub exist_uuids: Vec<String>,
98 #[serde(deserialize_with = "null_to_default")]
99 pub users: Vec<LdapUser>,
100}
101
102#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
104#[serde(rename_all = "camelCase", default)]
105pub struct SyncLdapUsersResponse {
106 #[serde(deserialize_with = "null_to_default")]
107 pub exist: Vec<LdapUser>,
108 #[serde(deserialize_with = "null_to_default")]
109 pub failed: Vec<LdapUser>,
110}
111
112impl Client {
113 pub async fn get_ldaps(&self) -> Result<Vec<Ldap>> {
115 self.get_list("get-ldaps", &[("owner", &self.config.organization_name)])
116 .await
117 }
118
119 pub async fn get_ldap(&self, id: &str) -> Result<Option<Ldap>> {
121 self.get_object("get-ldap", &[("id", &self.get_id(id))])
122 .await
123 }
124
125 pub async fn add_ldap(&self, ldap: &Ldap) -> Result<bool> {
127 Ok(self.modify_ldap("add-ldap", ldap, &[]).await?.1)
128 }
129
130 pub async fn update_ldap(&self, ldap: &Ldap) -> Result<bool> {
132 Ok(self.modify_ldap("update-ldap", ldap, &[]).await?.1)
133 }
134
135 pub async fn delete_ldap(&self, ldap: &Ldap) -> Result<bool> {
137 Ok(self.modify_ldap("delete-ldap", ldap, &[]).await?.1)
138 }
139
140 pub async fn get_ldap_users(&self, id: &str) -> Result<Option<LdapUsersResponse>> {
143 self.get_object("get-ldap-users", &[("id", &self.get_id(id))])
144 .await
145 }
146
147 pub async fn sync_ldap_users(
149 &self,
150 id: &str,
151 users: &[LdapUser],
152 ) -> Result<Option<SyncLdapUsersResponse>> {
153 let post_bytes = serde_json::to_vec(users)?;
154
155 let response = self
156 .do_post(
157 "sync-ldap-users",
158 &[("id", &self.get_id(id))],
159 PostBody::Raw(post_bytes),
160 )
161 .await?;
162
163 if response.data.is_null() {
164 return Ok(None);
165 }
166
167 Ok(Some(serde_json::from_value(response.data)?))
168 }
169
170 pub async fn sync_ldap_users_from_server(
172 &self,
173 id: &str,
174 ) -> Result<Option<SyncLdapUsersResponse>> {
175 let users = self
176 .get_ldap_users(id)
177 .await?
178 .map(|response| response.users)
179 .unwrap_or_default();
180
181 self.sync_ldap_users(id, &users).await
182 }
183
184 async fn modify_ldap(
185 &self,
186 action: &str,
187 ldap: &Ldap,
188 columns: &[&str],
189 ) -> Result<(Response, bool)> {
190 let mut ldap = ldap.clone();
191 ldap.owner = get_owner(&ldap.owner, &self.config.organization_name);
192
193 let id = format!("{}/{}", ldap.owner, ldap.id);
194 self.modify_object(action, &id, &ldap, columns).await
195 }
196}