1use crate::client::RestClient;
12use crate::error::Result;
13use serde::{Deserialize, Serialize};
14use serde_json::Value;
15use typed_builder::TypedBuilder;
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct User {
20 pub uid: u32,
22 pub email: String,
24 pub name: Option<String>,
26 pub role: String,
28 pub status: Option<String>,
30 pub auth_method: Option<String>,
32 pub certificate_subject_line: Option<String>,
34 pub password_issue_date: Option<String>,
36 pub email_alerts: Option<bool>,
38 pub role_uids: Option<Vec<u32>>,
40 pub bdbs: Option<Vec<u32>>,
42 pub alert_audit_db_conns: Option<bool>,
44 pub alert_bdb_backup: Option<bool>,
46 pub alert_bdb_crdt_src_syncer: Option<bool>,
48 pub password_expiration_duration: Option<u32>,
50}
51
52#[derive(Debug, Serialize, TypedBuilder)]
68pub struct CreateUserRequest {
69 #[builder(setter(into))]
71 pub email: String,
72 #[builder(setter(into))]
74 pub password: String,
75 #[serde(skip_serializing_if = "Option::is_none")]
78 #[builder(default, setter(into, strip_option))]
79 pub role: Option<String>,
80 #[serde(skip_serializing_if = "Option::is_none")]
82 #[builder(default, setter(into, strip_option))]
83 pub name: Option<String>,
84 #[serde(skip_serializing_if = "Option::is_none")]
86 #[builder(default, setter(strip_option))]
87 pub email_alerts: Option<bool>,
88 #[serde(skip_serializing_if = "Option::is_none")]
90 #[builder(default, setter(strip_option))]
91 pub bdbs_email_alerts: Option<Vec<String>>,
92 #[serde(skip_serializing_if = "Option::is_none")]
95 #[builder(default, setter(strip_option))]
96 pub role_uids: Option<Vec<u32>>,
97 #[serde(skip_serializing_if = "Option::is_none")]
99 #[builder(default, setter(into, strip_option))]
100 pub auth_method: Option<String>,
101}
102
103#[derive(Debug, Serialize, TypedBuilder)]
116pub struct UpdateUserRequest {
117 #[serde(skip_serializing_if = "Option::is_none")]
119 #[builder(default, setter(into, strip_option))]
120 pub password: Option<String>,
121 #[serde(skip_serializing_if = "Option::is_none")]
123 #[builder(default, setter(into, strip_option))]
124 pub role: Option<String>,
125 #[serde(skip_serializing_if = "Option::is_none")]
127 #[builder(default, setter(into, strip_option))]
128 pub email: Option<String>,
129 #[serde(skip_serializing_if = "Option::is_none")]
131 #[builder(default, setter(into, strip_option))]
132 pub name: Option<String>,
133 #[serde(skip_serializing_if = "Option::is_none")]
135 #[builder(default, setter(strip_option))]
136 pub email_alerts: Option<bool>,
137 #[serde(skip_serializing_if = "Option::is_none")]
139 #[builder(default, setter(strip_option))]
140 pub bdbs_email_alerts: Option<Vec<String>>,
141 #[serde(skip_serializing_if = "Option::is_none")]
143 #[builder(default, setter(strip_option))]
144 pub role_uids: Option<Vec<u32>>,
145 #[serde(skip_serializing_if = "Option::is_none")]
147 #[builder(default, setter(into, strip_option))]
148 pub auth_method: Option<String>,
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct Role {
154 pub uid: u32,
156 pub name: String,
158 pub management: Option<String>,
160 pub data_access: Option<String>,
162}
163
164pub struct UserHandler {
166 client: RestClient,
167}
168
169pub type UsersHandler = UserHandler;
171
172impl UserHandler {
173 pub fn new(client: RestClient) -> Self {
175 UserHandler { client }
176 }
177
178 pub async fn list(&self) -> Result<Vec<User>> {
180 self.client.get("/v1/users").await
181 }
182
183 pub async fn get(&self, uid: u32) -> Result<User> {
185 self.client.get(&format!("/v1/users/{}", uid)).await
186 }
187
188 pub async fn create(&self, request: CreateUserRequest) -> Result<User> {
190 let has_role = request
191 .role
192 .as_deref()
193 .map(|role| !role.trim().is_empty())
194 .unwrap_or(false);
195 let has_role_uids = request
196 .role_uids
197 .as_ref()
198 .map(|role_uids| !role_uids.is_empty())
199 .unwrap_or(false);
200
201 if has_role == has_role_uids {
202 return Err(crate::error::RestError::ValidationError(
203 "CreateUserRequest must include exactly one of role or role_uids".to_string(),
204 ));
205 }
206
207 self.client.post("/v1/users", &request).await
208 }
209
210 pub async fn update(&self, uid: u32, request: UpdateUserRequest) -> Result<User> {
212 self.client
213 .put(&format!("/v1/users/{}", uid), &request)
214 .await
215 }
216
217 pub async fn delete(&self, uid: u32) -> Result<()> {
219 self.client.delete(&format!("/v1/users/{}", uid)).await
220 }
221
222 pub async fn permissions(&self) -> Result<Value> {
224 self.client.get("/v1/users/permissions").await
225 }
226
227 pub async fn permission_detail(&self, perm: &str) -> Result<Value> {
229 self.client
230 .get(&format!("/v1/users/permissions/{}", perm))
231 .await
232 }
233
234 pub async fn authorize(&self, body: AuthRequest) -> Result<AuthResponse> {
236 self.client.post("/v1/users/authorize", &body).await
237 }
238
239 pub async fn password_set(&self, body: PasswordSet) -> Result<()> {
241 self.client.post_action("/v1/users/password", &body).await
242 }
243
244 pub async fn password_update(&self, body: PasswordUpdate) -> Result<()> {
246 self.client.put("/v1/users/password", &body).await
247 }
248
249 pub async fn password_delete(&self) -> Result<()> {
251 self.client.delete("/v1/users/password").await
252 }
253
254 pub async fn refresh_jwt(&self, body: JwtRefreshRequest) -> Result<JwtRefreshResponse> {
256 self.client.post("/v1/users/refresh_jwt", &body).await
257 }
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
262pub struct AuthRequest {
263 pub email: String,
265 pub password: String,
267}
268
269#[derive(Debug, Clone, Serialize, Deserialize)]
271pub struct AuthResponse {
272 pub jwt: String,
274 #[serde(skip_serializing_if = "Option::is_none")]
276 pub expires_at: Option<String>,
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct PasswordSet {
282 pub email: String,
284 pub password: String,
286}
287
288#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct PasswordUpdate {
291 #[serde(skip_serializing_if = "Option::is_none")]
293 pub current_password: Option<String>,
294 pub new_password: String,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct JwtRefreshRequest {
301 pub jwt: String,
303}
304
305#[derive(Debug, Clone, Serialize, Deserialize)]
307pub struct JwtRefreshResponse {
308 pub jwt: String,
310 #[serde(skip_serializing_if = "Option::is_none")]
312 pub expires_at: Option<String>,
313}
314
315pub struct RoleHandler {
317 client: RestClient,
318}
319
320impl RoleHandler {
321 pub fn new(client: RestClient) -> Self {
323 RoleHandler { client }
324 }
325
326 pub async fn list(&self) -> Result<Vec<Role>> {
328 self.client.get("/v1/roles").await
329 }
330
331 pub async fn get(&self, uid: u32) -> Result<Role> {
333 self.client.get(&format!("/v1/roles/{}", uid)).await
334 }
335}