1use std::sync::Arc;
2
3use async_trait::async_trait;
4use chrono::{DateTime, Utc};
5use dco3_derive::FromResponse;
6use reqwest::Response;
7use serde::{Deserialize, Serialize};
8
9use crate::{
10 client::{DracoonClient, DracoonErrorResponse},
11 user::UserAuthData,
12 utils::{parse_body, FromResponse},
13 DracoonClientError, KeyValueEntry, RangedItems,
14};
15
16#[derive(Clone)]
17pub struct ProvisioningEndpoint<S> {
18 client: Arc<DracoonClient<S>>,
19 state: std::marker::PhantomData<S>,
20}
21
22impl<S> ProvisioningEndpoint<S> {
23 pub fn new(client: Arc<DracoonClient<S>>) -> Self {
24 Self {
25 client,
26 state: std::marker::PhantomData,
27 }
28 }
29
30 pub fn client(&self) -> &Arc<DracoonClient<S>> {
31 &self.client
32 }
33}
34
35#[derive(Debug, Serialize, Deserialize, Default, Clone)]
36pub struct CustomerAttributes {
37 pub items: Vec<KeyValueEntry>,
38}
39
40impl CustomerAttributes {
41 pub fn new() -> CustomerAttributes {
42 CustomerAttributes::default()
43 }
44
45 pub fn add_attribute(&mut self, key: impl Into<String>, value: impl Into<String>) {
46 let attrib = KeyValueEntry {
47 key: key.into(),
48 value: value.into(),
49 };
50 self.items.push(attrib);
51 }
52}
53
54pub type AttributesResponse = RangedItems<KeyValueEntry>;
55
56#[derive(Debug, Deserialize, FromResponse, Clone)]
57#[serde(rename_all = "camelCase")]
58pub struct Customer {
59 pub id: u64,
60 pub company_name: String,
61 pub customer_contract_type: String,
62 pub quota_max: u64,
63 pub quota_used: u64,
64 pub user_max: u64,
65 pub user_used: u64,
66 pub created_at: DateTime<Utc>,
67 pub customer_attributes: Option<CustomerAttributes>,
68 pub updated_at: Option<DateTime<Utc>>,
69 pub last_login_at: Option<DateTime<Utc>>,
70 pub trial_days_left: Option<i32>,
71 pub is_locked: Option<bool>,
72 pub customer_uuid: Option<String>,
73 pub cnt_internal_user: Option<u64>,
74 pub cnt_guest_user: Option<u64>,
75}
76
77pub type CustomerList = RangedItems<Customer>;
78
79#[async_trait]
80impl FromResponse for CustomerList {
81 async fn from_response(response: Response) -> Result<Self, DracoonClientError> {
82 parse_body::<Self, DracoonErrorResponse>(response).await
83 }
84}
85
86#[async_trait]
87impl FromResponse for AttributesResponse {
88 async fn from_response(response: Response) -> Result<Self, DracoonClientError> {
89 parse_body::<Self, DracoonErrorResponse>(response).await
90 }
91}
92
93#[derive(Debug, Serialize, Deserialize, Clone)]
94#[serde(rename_all = "camelCase")]
95pub struct FirstAdminUser {
96 pub first_name: String,
97 pub last_name: String,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub user_name: Option<String>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub auth_data: Option<UserAuthData>,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub receiver_language: Option<String>,
104 pub notify_user: Option<bool>,
105 #[serde(skip_serializing_if = "Option::is_none")]
106 pub email: Option<String>,
107 #[serde(skip_serializing_if = "Option::is_none")]
108 pub phone: Option<String>,
109}
110
111impl FirstAdminUser {
112 pub fn new_local(
113 first_name: impl Into<String>,
114 last_name: impl Into<String>,
115 user_name: Option<String>,
116 email: impl Into<String>,
117 receiver_language: Option<String>,
118 ) -> FirstAdminUser {
119 let auth_data = UserAuthData::new_basic(None, None);
120
121 FirstAdminUser {
122 first_name: first_name.into(),
123 last_name: last_name.into(),
124 user_name,
125 auth_data: Some(auth_data),
126 receiver_language,
127 notify_user: None,
128 email: Some(email.into()),
129 phone: None,
130 }
131 }
132}
133
134#[derive(Debug, Serialize, Clone)]
135#[serde(rename_all = "camelCase")]
136pub struct NewCustomerRequest {
137 pub customer_contract_type: String,
138 pub quota_max: u64,
139 pub user_max: u64,
140 pub first_admin_user: FirstAdminUser,
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub company_name: Option<String>,
143 #[serde(skip_serializing_if = "Option::is_none")]
144 pub trial_days: Option<u64>,
145 #[serde(skip_serializing_if = "Option::is_none")]
146 pub is_locked: Option<bool>,
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub customer_attributes: Option<CustomerAttributes>,
149 #[serde(skip_serializing_if = "Option::is_none")]
150 pub provider_customer_id: Option<String>,
151 #[serde(skip_serializing_if = "Option::is_none")]
152 pub webhooks_max: Option<u64>,
153}
154
155impl NewCustomerRequest {
156 pub fn builder(
157 customer_contract_type: impl Into<String>,
158 quota_max: u64,
159 user_max: u64,
160 first_admin_user: FirstAdminUser,
161 ) -> NewCustomerRequestBuilder {
162 NewCustomerRequestBuilder::new(
163 customer_contract_type.into(),
164 quota_max,
165 user_max,
166 first_admin_user,
167 )
168 }
169}
170
171pub struct NewCustomerRequestBuilder {
172 customer_contract_type: String,
173 quota_max: u64,
174 user_max: u64,
175 first_admin_user: FirstAdminUser,
176 company_name: Option<String>,
177 trial_days: Option<u64>,
178 is_locked: Option<bool>,
179 customer_attributes: Option<CustomerAttributes>,
180 provider_customer_id: Option<String>,
181 webhooks_max: Option<u64>,
182}
183
184impl NewCustomerRequestBuilder {
185 pub fn new(
186 customer_contract_type: String,
187 quota_max: u64,
188 user_max: u64,
189 first_admin_user: FirstAdminUser,
190 ) -> NewCustomerRequestBuilder {
191 NewCustomerRequestBuilder {
192 customer_contract_type,
193 quota_max,
194 user_max,
195 first_admin_user,
196 company_name: None,
197 trial_days: None,
198 is_locked: None,
199 customer_attributes: None,
200 provider_customer_id: None,
201 webhooks_max: None,
202 }
203 }
204
205 pub fn with_company_name(
206 mut self,
207 company_name: impl Into<String>,
208 ) -> NewCustomerRequestBuilder {
209 self.company_name = Some(company_name.into());
210 self
211 }
212
213 pub fn with_trial_days(mut self, trial_days: u64) -> NewCustomerRequestBuilder {
214 self.trial_days = Some(trial_days);
215 self
216 }
217
218 pub fn with_is_locked(mut self, is_locked: bool) -> NewCustomerRequestBuilder {
219 self.is_locked = Some(is_locked);
220 self
221 }
222
223 pub fn with_customer_attributes(
224 mut self,
225 customer_attributes: CustomerAttributes,
226 ) -> NewCustomerRequestBuilder {
227 self.customer_attributes = Some(customer_attributes);
228 self
229 }
230
231 pub fn with_provider_customer_id(
232 mut self,
233 provider_customer_id: String,
234 ) -> NewCustomerRequestBuilder {
235 self.provider_customer_id = Some(provider_customer_id);
236 self
237 }
238
239 pub fn with_webhooks_max(mut self, webhooks_max: u64) -> NewCustomerRequestBuilder {
240 self.webhooks_max = Some(webhooks_max);
241 self
242 }
243
244 pub fn build(self) -> NewCustomerRequest {
245 NewCustomerRequest {
246 customer_contract_type: self.customer_contract_type,
247 quota_max: self.quota_max,
248 user_max: self.user_max,
249 first_admin_user: self.first_admin_user,
250 company_name: self.company_name,
251 trial_days: self.trial_days,
252 is_locked: self.is_locked,
253 customer_attributes: self.customer_attributes,
254 provider_customer_id: self.provider_customer_id,
255 webhooks_max: self.webhooks_max,
256 }
257 }
258}
259
260#[derive(Debug, Deserialize, FromResponse, Clone)]
261#[serde(rename_all = "camelCase")]
262pub struct NewCustomerResponse {
263 pub id: u64,
264 pub company_name: String,
265 pub customer_contract_type: String,
266 pub quota_max: u64,
267 pub user_max: u64,
268 pub is_locked: Option<bool>,
269 pub trial_days: Option<u64>,
270 pub created_at: Option<DateTime<Utc>>,
271 pub first_admin_user: FirstAdminUser,
272 pub customer_attributes: Option<CustomerAttributes>,
273 pub provider_customer_id: Option<String>,
274 pub webhooks_max: Option<u64>,
275}
276
277#[derive(Debug, Deserialize, FromResponse, Clone)]
278#[serde(rename_all = "camelCase")]
279pub struct UpdateCustomerResponse {
280 pub id: u64,
281 pub company_name: String,
282 pub customer_contract_type: String,
283 pub quota_max: u64,
284 pub user_max: u64,
285 pub customer_uuid: String,
286 pub is_locked: Option<bool>,
287 pub trial_days: Option<u64>,
288 pub created_at: Option<DateTime<Utc>>,
289 pub updated_at: Option<DateTime<Utc>>,
290 pub customer_attributes: Option<CustomerAttributes>,
291 pub provider_customer_id: Option<String>,
292 pub webhooks_max: Option<u64>,
293}
294
295#[derive(Debug, Serialize, Clone)]
296#[serde(rename_all = "camelCase")]
297pub struct UpdateCustomerRequest {
298 #[serde(skip_serializing_if = "Option::is_none")]
299 company_name: Option<String>,
300 #[serde(skip_serializing_if = "Option::is_none")]
301 customer_contract_type: Option<String>,
302 #[serde(skip_serializing_if = "Option::is_none")]
303 quota_max: Option<u64>,
304 #[serde(skip_serializing_if = "Option::is_none")]
305 user_max: Option<u64>,
306 #[serde(skip_serializing_if = "Option::is_none")]
307 is_locked: Option<bool>,
308 #[serde(skip_serializing_if = "Option::is_none")]
309 provider_customer_id: Option<u64>,
310 #[serde(skip_serializing_if = "Option::is_none")]
311 webhooks_max: Option<u64>,
312}
313
314impl UpdateCustomerRequest {
315 pub fn builder() -> UpdateCustomerRequestBuilder {
316 UpdateCustomerRequestBuilder::new()
317 }
318}
319
320#[derive(Debug, Default)]
321pub struct UpdateCustomerRequestBuilder {
322 company_name: Option<String>,
323 customer_contract_type: Option<String>,
324 quota_max: Option<u64>,
325 user_max: Option<u64>,
326 is_locked: Option<bool>,
327 provider_customer_id: Option<u64>,
328 webhooks_max: Option<u64>,
329}
330
331impl UpdateCustomerRequestBuilder {
332 pub fn new() -> Self {
333 UpdateCustomerRequestBuilder::default()
334 }
335
336 pub fn with_company_name(mut self, company_name: impl Into<String>) -> Self {
337 self.company_name = Some(company_name.into());
338 self
339 }
340
341 pub fn with_customer_contract_type(
342 mut self,
343 customer_contract_type: impl Into<String>,
344 ) -> Self {
345 self.customer_contract_type = Some(customer_contract_type.into());
346 self
347 }
348
349 pub fn with_quota_max(mut self, quota_max: u64) -> Self {
350 self.quota_max = Some(quota_max);
351 self
352 }
353
354 pub fn with_user_max(mut self, user_max: u64) -> Self {
355 self.user_max = Some(user_max);
356 self
357 }
358
359 pub fn with_is_locked(mut self, is_locked: bool) -> Self {
360 self.is_locked = Some(is_locked);
361 self
362 }
363
364 pub fn with_provider_customer_id(mut self, provider_customer_id: u64) -> Self {
365 self.provider_customer_id = Some(provider_customer_id);
366 self
367 }
368
369 pub fn with_webhooks_max(mut self, webhooks_max: u64) -> Self {
370 self.webhooks_max = Some(webhooks_max);
371 self
372 }
373
374 pub fn build(self) -> UpdateCustomerRequest {
375 UpdateCustomerRequest {
376 company_name: self.company_name,
377 customer_contract_type: self.customer_contract_type,
378 quota_max: self.quota_max,
379 user_max: self.user_max,
380 is_locked: self.is_locked,
381 provider_customer_id: self.provider_customer_id,
382 webhooks_max: self.webhooks_max,
383 }
384 }
385}