1use crate::{CloudClient, Result};
44use serde::{Deserialize, Serialize};
45use serde_json::Value;
46use std::collections::HashMap;
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
54#[serde(rename_all = "camelCase")]
55pub struct AclRoleCreateRequest {
56 pub name: String,
58
59 pub redis_rules: Vec<AclRoleRedisRuleSpec>,
61
62 #[serde(skip_serializing_if = "Option::is_none")]
63 pub command_type: Option<String>,
64
65 #[serde(flatten)]
67 pub extra: Value,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
72#[serde(rename_all = "camelCase")]
73pub struct ProcessorResponse {
74 #[serde(skip_serializing_if = "Option::is_none")]
75 pub resource_id: Option<i32>,
76
77 #[serde(skip_serializing_if = "Option::is_none")]
78 pub additional_resource_id: Option<i32>,
79
80 #[serde(skip_serializing_if = "Option::is_none")]
81 pub resource: Option<HashMap<String, Value>>,
82
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub error: Option<String>,
85
86 #[serde(skip_serializing_if = "Option::is_none")]
87 pub additional_info: Option<String>,
88
89 #[serde(flatten)]
91 pub extra: Value,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
96#[serde(rename_all = "camelCase")]
97pub struct AclUserUpdateRequest {
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub user_id: Option<i32>,
100
101 #[serde(skip_serializing_if = "Option::is_none")]
103 pub role: Option<String>,
104
105 #[serde(skip_serializing_if = "Option::is_none")]
107 pub password: Option<String>,
108
109 #[serde(skip_serializing_if = "Option::is_none")]
110 pub command_type: Option<String>,
111
112 #[serde(flatten)]
114 pub extra: Value,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
121#[serde(rename_all = "camelCase")]
122pub struct AccountACLUsers {
123 #[serde(skip_serializing_if = "Option::is_none")]
125 pub account_id: Option<i32>,
126
127 #[serde(skip_serializing_if = "Option::is_none")]
129 pub users: Option<Vec<ACLUser>>,
130
131 #[serde(skip_serializing_if = "Option::is_none")]
133 pub links: Option<Vec<HashMap<String, Value>>>,
134
135 #[serde(flatten)]
137 pub extra: Value,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
144#[serde(rename_all = "camelCase")]
145pub struct AccountACLRedisRules {
146 #[serde(skip_serializing_if = "Option::is_none")]
148 pub account_id: Option<i32>,
149
150 #[serde(skip_serializing_if = "Option::is_none")]
152 pub redis_rules: Option<Vec<Value>>,
153
154 #[serde(skip_serializing_if = "Option::is_none")]
156 pub links: Option<Vec<HashMap<String, Value>>>,
157
158 #[serde(flatten)]
160 pub extra: Value,
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
165#[serde(rename_all = "camelCase")]
166pub struct AclRedisRuleCreateRequest {
167 pub name: String,
169
170 pub redis_rule: String,
172
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub command_type: Option<String>,
175
176 #[serde(flatten)]
178 pub extra: Value,
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
185#[serde(rename_all = "camelCase")]
186pub struct AccountACLRoles {
187 #[serde(skip_serializing_if = "Option::is_none")]
189 pub account_id: Option<i32>,
190
191 #[serde(skip_serializing_if = "Option::is_none")]
193 pub roles: Option<Vec<Value>>,
194
195 #[serde(skip_serializing_if = "Option::is_none")]
197 pub links: Option<Vec<HashMap<String, Value>>>,
198
199 #[serde(flatten)]
201 pub extra: Value,
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize)]
206#[serde(rename_all = "camelCase")]
207pub struct AclRedisRuleUpdateRequest {
208 #[serde(skip_serializing_if = "Option::is_none")]
209 pub redis_rule_id: Option<i32>,
210
211 pub name: String,
213
214 pub redis_rule: String,
216
217 #[serde(skip_serializing_if = "Option::is_none")]
218 pub command_type: Option<String>,
219
220 #[serde(flatten)]
222 pub extra: Value,
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
227#[serde(rename_all = "camelCase")]
228pub struct AclRoleDatabaseSpec {
229 pub subscription_id: i32,
231
232 pub database_id: i32,
234
235 #[serde(skip_serializing_if = "Option::is_none")]
237 pub regions: Option<Vec<String>>,
238
239 #[serde(flatten)]
241 pub extra: Value,
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
246#[serde(rename_all = "camelCase")]
247pub struct AclUserCreateRequest {
248 pub name: String,
250
251 pub role: String,
253
254 pub password: String,
256
257 #[serde(skip_serializing_if = "Option::is_none")]
258 pub command_type: Option<String>,
259
260 #[serde(flatten)]
262 pub extra: Value,
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
267pub struct ACLUser {
268 #[serde(skip_serializing_if = "Option::is_none")]
269 pub id: Option<i32>,
270
271 #[serde(skip_serializing_if = "Option::is_none")]
272 pub name: Option<String>,
273
274 #[serde(skip_serializing_if = "Option::is_none")]
275 pub role: Option<String>,
276
277 #[serde(skip_serializing_if = "Option::is_none")]
278 pub status: Option<String>,
279
280 #[serde(skip_serializing_if = "Option::is_none")]
282 pub links: Option<Vec<HashMap<String, Value>>>,
283
284 #[serde(flatten)]
286 pub extra: Value,
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize)]
291#[serde(rename_all = "camelCase")]
292pub struct AclRoleUpdateRequest {
293 #[serde(skip_serializing_if = "Option::is_none")]
295 pub name: Option<String>,
296
297 #[serde(skip_serializing_if = "Option::is_none")]
299 pub redis_rules: Option<Vec<AclRoleRedisRuleSpec>>,
300
301 #[serde(skip_serializing_if = "Option::is_none")]
302 pub role_id: Option<i32>,
303
304 #[serde(skip_serializing_if = "Option::is_none")]
305 pub command_type: Option<String>,
306
307 #[serde(flatten)]
309 pub extra: Value,
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize)]
314#[serde(rename_all = "camelCase")]
315pub struct AclRoleRedisRuleSpec {
316 pub rule_name: String,
318
319 pub databases: Vec<AclRoleDatabaseSpec>,
321
322 #[serde(flatten)]
324 pub extra: Value,
325}
326
327#[derive(Debug, Clone, Serialize, Deserialize)]
329#[serde(rename_all = "camelCase")]
330pub struct TaskStateUpdate {
331 #[serde(skip_serializing_if = "Option::is_none")]
332 pub task_id: Option<String>,
333
334 #[serde(skip_serializing_if = "Option::is_none")]
335 pub command_type: Option<String>,
336
337 #[serde(skip_serializing_if = "Option::is_none")]
338 pub status: Option<String>,
339
340 #[serde(skip_serializing_if = "Option::is_none")]
341 pub description: Option<String>,
342
343 #[serde(skip_serializing_if = "Option::is_none")]
344 pub timestamp: Option<String>,
345
346 #[serde(skip_serializing_if = "Option::is_none")]
347 pub response: Option<ProcessorResponse>,
348
349 #[serde(skip_serializing_if = "Option::is_none")]
351 pub links: Option<Vec<HashMap<String, Value>>>,
352
353 #[serde(flatten)]
355 pub extra: Value,
356}
357
358pub struct AclHandler {
367 client: CloudClient,
368}
369
370impl AclHandler {
371 pub fn new(client: CloudClient) -> Self {
373 Self { client }
374 }
375
376 pub async fn get_all_redis_rules(&self) -> Result<AccountACLRedisRules> {
381 self.client.get("/acl/redisRules").await
382 }
383
384 pub async fn create_redis_rule(
389 &self,
390 request: &AclRedisRuleCreateRequest,
391 ) -> Result<TaskStateUpdate> {
392 self.client.post("/acl/redisRules", request).await
393 }
394
395 pub async fn delete_redis_rule(&self, acl_redis_rule_id: i32) -> Result<TaskStateUpdate> {
400 let response = self
401 .client
402 .delete_raw(&format!("/acl/redisRules/{}", acl_redis_rule_id))
403 .await?;
404 serde_json::from_value(response).map_err(Into::into)
405 }
406
407 pub async fn update_redis_rule(
412 &self,
413 acl_redis_rule_id: i32,
414 request: &AclRedisRuleUpdateRequest,
415 ) -> Result<TaskStateUpdate> {
416 self.client
417 .put(&format!("/acl/redisRules/{}", acl_redis_rule_id), request)
418 .await
419 }
420
421 pub async fn get_roles(&self) -> Result<AccountACLRoles> {
426 self.client.get("/acl/roles").await
427 }
428
429 pub async fn create_role(&self, request: &AclRoleCreateRequest) -> Result<TaskStateUpdate> {
434 self.client.post("/acl/roles", request).await
435 }
436
437 pub async fn delete_acl_role(&self, acl_role_id: i32) -> Result<TaskStateUpdate> {
442 let response = self
443 .client
444 .delete_raw(&format!("/acl/roles/{}", acl_role_id))
445 .await?;
446 serde_json::from_value(response).map_err(Into::into)
447 }
448
449 pub async fn update_role(
454 &self,
455 acl_role_id: i32,
456 request: &AclRoleUpdateRequest,
457 ) -> Result<TaskStateUpdate> {
458 self.client
459 .put(&format!("/acl/roles/{}", acl_role_id), request)
460 .await
461 }
462
463 pub async fn get_all_acl_users(&self) -> Result<AccountACLUsers> {
468 self.client.get("/acl/users").await
469 }
470
471 pub async fn create_user(&self, request: &AclUserCreateRequest) -> Result<TaskStateUpdate> {
476 self.client.post("/acl/users", request).await
477 }
478
479 pub async fn delete_user(&self, acl_user_id: i32) -> Result<TaskStateUpdate> {
484 let response = self
485 .client
486 .delete_raw(&format!("/acl/users/{}", acl_user_id))
487 .await?;
488 serde_json::from_value(response).map_err(Into::into)
489 }
490
491 pub async fn get_user_by_id(&self, acl_user_id: i32) -> Result<ACLUser> {
496 self.client
497 .get(&format!("/acl/users/{}", acl_user_id))
498 .await
499 }
500
501 pub async fn update_acl_user(
506 &self,
507 acl_user_id: i32,
508 request: &AclUserUpdateRequest,
509 ) -> Result<TaskStateUpdate> {
510 self.client
511 .put(&format!("/acl/users/{}", acl_user_id), request)
512 .await
513 }
514}