1use crate::errors::{AuthError, Result};
4use crate::storage::AuthStorage;
5use std::collections::HashMap;
6use std::sync::Arc;
7use tracing::{debug, info, warn};
8
9pub type UserInfo = crate::auth::UserInfo;
11
12pub struct CredentialCheckResult {
21 pub user_id: String,
23 pub mfa_enabled: bool,
25}
26
27pub struct UserManager {
36 storage: Arc<dyn AuthStorage>,
37}
38
39impl UserManager {
40 pub fn new(storage: Arc<dyn AuthStorage>) -> Self {
47 Self { storage }
48 }
49
50 pub async fn create_api_key(
57 &self,
58 user_id: &str,
59 expires_in: Option<std::time::Duration>,
60 ) -> Result<String> {
61 debug!("Creating API key for user '{}'", user_id);
62
63 let api_key = format!("ak_{}", crate::utils::crypto::generate_token(32));
65
66 let key_data = serde_json::json!({
68 "user_id": user_id,
69 "created_at": chrono::Utc::now(),
70 "expires_at": expires_in.map(|d| chrono::Utc::now() + chrono::Duration::from_std(d).unwrap_or(chrono::Duration::days(365 * 10)))
71 });
72
73 let storage_key = format!("api_key:{}", api_key);
74 self.storage
75 .store_kv(&storage_key, key_data.to_string().as_bytes(), expires_in)
76 .await?;
77
78 info!("API key created for user '{}'", user_id);
79 Ok(api_key)
80 }
81
82 pub async fn validate_api_key(&self, api_key: &str) -> Result<UserInfo> {
90 debug!("Validating API key");
91
92 let storage_key = format!("api_key:{}", api_key);
93 if let Some(key_data) = self.storage.get_kv(&storage_key).await? {
94 let key_info: serde_json::Value = serde_json::from_slice(&key_data)?;
95
96 if let Some(user_id) = key_info["user_id"].as_str() {
97 if let Some(expires_at_str) = key_info["expires_at"].as_str() {
99 let expires_at: chrono::DateTime<chrono::Utc> = expires_at_str
100 .parse()
101 .map_err(|_| AuthError::token("Invalid API key expiration"))?;
102
103 if chrono::Utc::now() > expires_at {
104 return Err(AuthError::token("API key expired"));
105 }
106 }
107
108 Ok(UserInfo {
110 id: user_id.to_string(),
111 username: format!("api_user_{}", user_id),
112 email: None,
113 name: None,
114 roles: vec!["api_user".to_string()].into(),
115 active: true,
116 email_verified: false,
117 attributes: crate::types::UserAttributes::empty(),
118 })
119 } else {
120 Err(AuthError::token("Invalid API key format"))
121 }
122 } else {
123 Err(AuthError::token("Invalid API key"))
124 }
125 }
126
127 pub async fn revoke_api_key(&self, api_key: &str) -> Result<()> {
134 debug!("Revoking API key");
135
136 let storage_key = format!("api_key:{}", api_key);
137 if self.storage.get_kv(&storage_key).await?.is_some() {
138 self.storage.delete_kv(&storage_key).await?;
139 info!("API key revoked");
140 Ok(())
141 } else {
142 Err(AuthError::token("API key not found"))
143 }
144 }
145
146 pub async fn validate_username(&self, username: &str) -> Result<bool> {
154 debug!("Validating username format: '{}'", username);
155
156 let is_valid = username.len() >= 3
157 && username.len() <= 32
158 && username
159 .chars()
160 .all(|c| c.is_alphanumeric() || c == '_' || c == '-');
161
162 Ok(is_valid)
163 }
164
165 pub async fn validate_display_name(&self, display_name: &str) -> Result<bool> {
172 debug!("Validating display name format");
173
174 let is_valid = !display_name.is_empty()
175 && display_name.len() <= 100
176 && !display_name.trim().is_empty();
177
178 Ok(is_valid)
179 }
180
181 pub async fn validate_password_strength(&self, password: &str) -> Result<bool> {
191 debug!("Validating password strength");
192 let strength = crate::utils::password::check_password_strength(password);
193 let is_valid = crate::utils::password::meets_production_strength(strength.level);
194 if !is_valid {
195 warn!(
196 "Password validation failed - Actual: {:?}, Feedback: {}",
197 strength.level,
198 strength.feedback.join(", ")
199 );
200 }
201 Ok(is_valid)
202 }
203
204 pub async fn validate_user_input(&self, input: &str) -> Result<bool> {
216 debug!("Validating user input");
217
218 if input.is_empty() || input.len() > 1000 {
219 return Ok(false);
220 }
221
222 if !input.chars().all(|c| {
224 if c.is_control() {
225 matches!(c, ' ' | '\t' | '\n' | '\r')
226 } else {
227 !matches!(c, '<' | '>')
228 }
229 }) {
230 return Ok(false);
231 }
232
233 let lower = input.to_ascii_lowercase();
234 if lower.contains("%3c") || lower.contains("%3e") || lower.contains("%00") {
235 return Ok(false);
236 }
237 if lower.contains("javascript:")
238 || lower.contains("data:")
239 || lower.contains("file:")
240 || lower.contains("jndi:")
241 {
242 return Ok(false);
243 }
244 if input.contains("${") || input.contains("{{") {
245 return Ok(false);
246 }
247 if input.contains("../") || input.contains("..\\") {
248 return Ok(false);
249 }
250 if input.contains('\0') {
251 return Ok(false);
252 }
253 if lower.contains("; drop")
254 || lower.contains(";drop")
255 || lower.contains("' drop")
256 || lower.contains("'; drop")
257 || lower.contains("--")
258 {
259 return Ok(false);
260 }
261
262 Ok(true)
263 }
264
265 pub async fn get_user_info(&self, user_id: &str) -> Result<UserInfo> {
273 debug!("Getting user info for '{}'", user_id);
274
275 let key = format!("user:{}", user_id);
276 if let Some(data) = self.storage.get_kv(&key).await? {
277 let user_data: serde_json::Value = serde_json::from_slice(&data)
278 .map_err(|e| AuthError::internal(format!("Failed to parse user data: {e}")))?;
279
280 Ok(UserInfo {
281 id: user_data["user_id"].as_str().unwrap_or(user_id).to_string(),
282 username: user_data["username"].as_str().unwrap_or("").to_string(),
283 email: user_data["email"].as_str().map(String::from),
284 name: user_data["name"].as_str().map(String::from),
285 roles: user_data["roles"]
286 .as_array()
287 .map(|arr| {
288 arr.iter()
289 .filter_map(|v| v.as_str().map(String::from))
290 .collect::<Vec<_>>()
291 })
292 .unwrap_or_else(|| vec!["user".to_string()])
293 .into(),
294 active: user_data["active"].as_bool().unwrap_or(true),
295 email_verified: user_data["email_verified"].as_bool().unwrap_or(false),
296 attributes: crate::types::UserAttributes::empty(),
297 })
298 } else {
299 Err(AuthError::validation(format!("User '{user_id}' not found")))
300 }
301 }
302
303 pub async fn list_users(
311 &self,
312 limit: Option<usize>,
313 offset: Option<usize>,
314 active_only: bool,
315 ) -> Result<Vec<UserInfo>> {
316 let bytes = self.storage.get_kv("users:index").await?;
317 let user_ids: Vec<String> = match bytes {
318 Some(bytes) => serde_json::from_slice(&bytes)
319 .map_err(|e| AuthError::internal(format!("Failed to parse user index: {e}")))?,
320 None => return Ok(Vec::new()),
321 };
322
323 let skip = offset.unwrap_or(0);
324 let take = limit.unwrap_or(usize::MAX);
325 let mut users = Vec::new();
326
327 for user_id in user_ids.into_iter().skip(skip) {
328 let user = self.get_user_info(&user_id).await?;
329 if active_only && !user.active {
330 continue;
331 }
332 users.push(user);
333 if users.len() >= take {
334 break;
335 }
336 }
337
338 Ok(users)
339 }
340
341 pub async fn user_exists(&self, user_id: &str) -> Result<bool> {
350 debug!("Checking if user '{}' exists", user_id);
351
352 if user_id.is_empty() {
353 return Ok(false);
354 }
355
356 let key = format!("user:{}", user_id);
357 Ok(self.storage.get_kv(&key).await?.is_some())
358 }
359
360 pub async fn register_user(
372 &self,
373 username: &str,
374 email: &str,
375 password: &str,
376 ) -> Result<String> {
377 debug!("Registering new user: {}", username);
378
379 let username_key = format!("user:username:{}", username);
380 if self.storage.get_kv(&username_key).await?.is_some() {
381 return Err(AuthError::validation("Username already exists".to_string()));
382 }
383
384 let email_key = format!("user:email:{}", email);
385 if self.storage.get_kv(&email_key).await?.is_some() {
386 return Err(AuthError::validation("Email already exists".to_string()));
387 }
388
389 let user_id = crate::utils::string::generate_id(Some("user"));
390
391 let password_hash = bcrypt::hash(password, bcrypt::DEFAULT_COST)
392 .map_err(|e| AuthError::crypto(format!("Failed to hash password: {}", e)))?;
393
394 let user_data = serde_json::json!({
395 "user_id": user_id,
396 "username": username,
397 "email": email,
398 "password_hash": password_hash,
399 "roles": ["user"],
400 "active": true,
401 "email_verified": false,
402 "created_at": chrono::Utc::now().to_rfc3339(),
403 });
404
405 let user_key = format!("user:{}", user_id);
406 self.storage
407 .store_kv(&user_key, user_data.to_string().as_bytes(), None)
408 .await?;
409
410 self.storage
411 .store_kv(&username_key, user_id.as_bytes(), None)
412 .await?;
413 self.storage
414 .store_kv(&email_key, user_id.as_bytes(), None)
415 .await?;
416
417 let index_key = "users:index";
419 let mut ids: Vec<String> = match self.storage.get_kv(index_key).await? {
420 Some(bytes) => serde_json::from_slice(&bytes).unwrap_or_default(),
421 None => vec![],
422 };
423 ids.push(user_id.clone());
424 if let Ok(idx_json) = serde_json::to_vec(&ids) {
425 if let Err(e) = self.storage.store_kv(index_key, &idx_json, None).await {
426 warn!("Failed to update user index during registration: {}", e);
427 }
428 }
429
430 let creds_key = format!("user:credentials:{}", username);
432 let creds_hash = match crate::utils::password::hash_password(password) {
433 Ok(h) => h,
434 Err(e) => {
435 warn!("Failed to hash credentials for user '{}': {}", username, e);
436 return Ok(user_id);
437 }
438 };
439 let creds_data = serde_json::json!({
440 "user_id": user_id,
441 "username": username,
442 "email": email,
443 "password_hash": creds_hash,
444 "created_at": chrono::Utc::now().to_rfc3339(),
445 });
446 if let Err(e) = self
447 .storage
448 .store_kv(&creds_key, creds_data.to_string().as_bytes(), None)
449 .await
450 {
451 warn!("Failed to store credentials for user '{}': {}", username, e);
452 }
453
454 info!("User '{}' registered successfully", username);
455 Ok(user_id)
456 }
457
458 pub async fn delete_user(&self, username: &str) -> Result<()> {
465 debug!("Deleting user: {}", username);
466
467 let username_key = format!("user:username:{}", username);
468 let user_id_data = self
469 .storage
470 .get_kv(&username_key)
471 .await?
472 .ok_or_else(|| AuthError::validation("User not found".to_string()))?;
473
474 let user_id = String::from_utf8(user_id_data)
475 .map_err(|e| AuthError::crypto(format!("Invalid user ID format: {}", e)))?;
476
477 let user_key = format!("user:{}", user_id);
479 if let Some(user_data_bytes) = self.storage.get_kv(&user_key).await?
480 && let Ok(user_json_str) = String::from_utf8(user_data_bytes)
481 && let Ok(user_data) = serde_json::from_str::<serde_json::Value>(&user_json_str)
482 && let Some(email) = user_data.get("email").and_then(|v| v.as_str())
483 {
484 if let Err(e) = self
485 .storage
486 .delete_kv(&format!("user:email:{}", email))
487 .await
488 {
489 warn!("Failed to delete email index for user '{}': {}", username, e);
490 }
491 }
492
493 let index_key = "users:index";
495 if let Ok(Some(bytes)) = self.storage.get_kv(index_key).await {
496 let mut ids: Vec<String> = serde_json::from_slice(&bytes).unwrap_or_default();
497 ids.retain(|id| id != &user_id);
498 if let Ok(idx_json) = serde_json::to_vec(&ids) {
499 if let Err(e) = self.storage.store_kv(index_key, &idx_json, None).await {
500 warn!("Failed to update user index during deletion of '{}': {}", username, e);
501 }
502 }
503 }
504
505 if let Err(e) = self.storage.delete_kv(&user_key).await {
506 warn!("Failed to delete user record for '{}': {}", username, e);
507 }
508 if let Err(e) = self.storage.delete_kv(&username_key).await {
509 warn!("Failed to delete username index for '{}': {}", username, e);
510 }
511 if let Err(e) = self
512 .storage
513 .delete_kv(&format!("user:credentials:{}", username))
514 .await
515 {
516 warn!("Failed to delete credentials for '{}': {}", username, e);
517 }
518 if let Err(e) = self
519 .storage
520 .delete_kv(&format!("user:{}:totp_secret", user_id))
521 .await
522 {
523 warn!("Failed to delete TOTP secret for '{}': {}", username, e);
524 }
525 if let Err(e) = self
526 .storage
527 .delete_kv(&format!("user:{}:backup_codes", user_id))
528 .await
529 {
530 warn!("Failed to delete backup codes for '{}': {}", username, e);
531 }
532
533 info!("User '{}' deleted successfully", username);
534 Ok(())
535 }
536
537 pub async fn delete_user_by_id(&self, user_id: &str) -> Result<()> {
544 let username = self.get_username_by_id(user_id).await?;
545 self.delete_user(&username).await
546 }
547
548 pub async fn update_user_roles(&self, user_id: &str, roles: &[String]) -> Result<()> {
555 let user_key = format!("user:{}", user_id);
556 let bytes = self
557 .storage
558 .get_kv(&user_key)
559 .await?
560 .ok_or(AuthError::UserNotFound)?;
561 let mut user_data: serde_json::Value =
562 serde_json::from_slice(&bytes).map_err(|e| AuthError::crypto(format!("{e}")))?;
563 user_data["roles"] = serde_json::json!(roles);
564 user_data["updated_at"] = serde_json::json!(chrono::Utc::now().to_rfc3339());
565 self.storage
566 .store_kv(&user_key, user_data.to_string().as_bytes(), None)
567 .await?;
568 info!("Roles updated for user '{}'", user_id);
569 Ok(())
570 }
571
572 pub async fn set_user_active(&self, user_id: &str, active: bool) -> Result<()> {
579 let user_key = format!("user:{}", user_id);
580 let bytes = self
581 .storage
582 .get_kv(&user_key)
583 .await?
584 .ok_or(AuthError::UserNotFound)?;
585 let mut user_data: serde_json::Value =
586 serde_json::from_slice(&bytes).map_err(|e| AuthError::crypto(format!("{e}")))?;
587 user_data["active"] = serde_json::json!(active);
588 user_data["updated_at"] = serde_json::json!(chrono::Utc::now().to_rfc3339());
589 self.storage
590 .store_kv(&user_key, user_data.to_string().as_bytes(), None)
591 .await?;
592 info!("User '{}' active status set to {}", user_id, active);
593 Ok(())
594 }
595
596 pub async fn update_user_email(&self, user_id: &str, email: &str) -> Result<()> {
603 let user_key = format!("user:{}", user_id);
604 let bytes = self
605 .storage
606 .get_kv(&user_key)
607 .await?
608 .ok_or(AuthError::UserNotFound)?;
609 let mut user_data: serde_json::Value =
610 serde_json::from_slice(&bytes).map_err(|e| AuthError::crypto(format!("{e}")))?;
611
612 let new_email_key = format!("user:email:{}", email);
613 if let Some(existing_user_id) = self.storage.get_kv(&new_email_key).await? {
614 let existing_user_id = String::from_utf8(existing_user_id)
615 .map_err(|e| AuthError::crypto(format!("Invalid user ID format: {e}")))?;
616 if existing_user_id != user_id {
617 return Err(AuthError::validation("Email already exists".to_string()));
618 }
619 }
620
621 if let Some(old_email) = user_data.get("email").and_then(|value| value.as_str())
622 && old_email != email
623 {
624 self.storage
625 .delete_kv(&format!("user:email:{}", old_email))
626 .await?;
627 }
628
629 user_data["email"] = serde_json::json!(email);
630 user_data["updated_at"] = serde_json::json!(chrono::Utc::now().to_rfc3339());
631
632 self.storage
633 .store_kv(&user_key, user_data.to_string().as_bytes(), None)
634 .await?;
635 self.storage
636 .store_kv(&new_email_key, user_id.as_bytes(), None)
637 .await?;
638
639 Ok(())
640 }
641
642 pub async fn verify_user_password(&self, user_id: &str, password: &str) -> Result<bool> {
650 let user_key = format!("user:{}", user_id);
651 let bytes = self
652 .storage
653 .get_kv(&user_key)
654 .await?
655 .ok_or(AuthError::UserNotFound)?;
656 let user_data: serde_json::Value =
657 serde_json::from_slice(&bytes).map_err(|e| AuthError::crypto(format!("{e}")))?;
658 let hash = user_data["password_hash"]
659 .as_str()
660 .ok_or_else(|| AuthError::internal("User has no password hash".to_string()))?;
661 bcrypt::verify(password, hash)
662 .map_err(|e| AuthError::crypto(format!("Password verification failed: {}", e)))
663 }
664
665 pub async fn get_username_by_id(&self, user_id: &str) -> Result<String> {
672 let user_key = format!("user:{}", user_id);
673 let bytes = self
674 .storage
675 .get_kv(&user_key)
676 .await?
677 .ok_or(AuthError::UserNotFound)?;
678 let user_data: serde_json::Value =
679 serde_json::from_slice(&bytes).map_err(|e| AuthError::crypto(format!("{e}")))?;
680 user_data["username"]
681 .as_str()
682 .map(|s| s.to_string())
683 .ok_or_else(|| AuthError::internal("User has no username field".to_string()))
684 }
685
686 pub async fn username_exists(&self, username: &str) -> Result<bool> {
695 Ok(self
696 .storage
697 .get_kv(&format!("user:username:{}", username))
698 .await?
699 .is_some())
700 }
701
702 pub async fn email_exists(&self, email: &str) -> Result<bool> {
711 Ok(self
712 .storage
713 .get_kv(&format!("user:email:{}", email))
714 .await?
715 .is_some())
716 }
717
718 pub async fn get_user_by_username(
726 &self,
727 username: &str,
728 ) -> Result<HashMap<String, serde_json::Value>> {
729 let username_key = format!("user:username:{}", username);
730 let user_id_data = self
731 .storage
732 .get_kv(&username_key)
733 .await?
734 .ok_or_else(|| AuthError::validation("User not found".to_string()))?;
735 let user_id = String::from_utf8(user_id_data)
736 .map_err(|e| AuthError::crypto(format!("Invalid user ID format: {}", e)))?;
737 let user_key = format!("user:{}", user_id);
738 let user_data = self
739 .storage
740 .get_kv(&user_key)
741 .await?
742 .ok_or_else(|| AuthError::validation("User not found".to_string()))?;
743 let user_obj: serde_json::Value = serde_json::from_slice(&user_data)
744 .map_err(|e| AuthError::crypto(format!("Failed to parse user data: {}", e)))?;
745 if let Some(obj) = user_obj.as_object() {
746 Ok(obj
747 .into_iter()
748 .map(|(k, v)| (k.clone(), v.clone()))
749 .collect())
750 } else {
751 Err(AuthError::validation(
752 "Invalid user data structure".to_string(),
753 ))
754 }
755 }
756
757 pub async fn get_user_profile(
765 &self,
766 user_id: &str,
767 ) -> Result<crate::providers::ProviderProfile> {
768 let user_key = format!("user:{}", user_id);
769 if let Ok(Some(bytes)) = self.storage.get_kv(&user_key).await
770 && let Ok(user_data) = serde_json::from_slice::<serde_json::Value>(&bytes)
771 {
772 let username = user_data["username"].as_str().map(|s| s.to_string());
773 let email = user_data["email"].as_str().map(|s| s.to_string());
774 let name = user_data["name"].as_str().map(|s| s.to_string());
775 let email_verified = user_data["email_verified"].as_bool();
776
777 let mut additional_data = std::collections::HashMap::new();
778 if let Some(obj) = user_data.as_object() {
779 for (k, v) in obj {
780 match k.as_str() {
781 "user_id" | "username" | "email" | "name" | "email_verified"
782 | "password_hash" | "created_at" | "updated_at" => {}
783 _ => {
784 additional_data.insert(k.clone(), v.clone());
785 }
786 }
787 }
788 }
789
790 return Ok(crate::providers::ProviderProfile {
791 id: Some(user_id.to_string()),
792 provider: Some("local".to_string()),
793 username,
794 name,
795 email,
796 email_verified,
797 picture: None,
798 locale: None,
799 additional_data,
800 });
801 }
802 Err(AuthError::UserNotFound)
803 }
804
805 pub async fn get_user_roles(&self, user_id: &str) -> Result<Vec<String>> {
813 let user_key = format!("user:{}", user_id);
814 if let Ok(Some(data)) = self.storage.get_kv(&user_key).await
815 && let Ok(v) = serde_json::from_slice::<serde_json::Value>(&data)
816 && let Some(arr) = v.get("roles").and_then(|r| r.as_array())
817 {
818 let roles: Vec<String> = arr
819 .iter()
820 .filter_map(|v| v.as_str().map(String::from))
821 .collect();
822 if !roles.is_empty() {
823 return Ok(roles);
824 }
825 }
826 Ok(vec!["user".to_string()])
827 }
828
829 pub async fn verify_login_credentials(
844 &self,
845 username: &str,
846 password: &str,
847 ) -> Result<Option<CredentialCheckResult>> {
848 use crate::utils::password::verify_password;
849
850 if username.is_empty() || password.is_empty() {
851 return Ok(None);
852 }
853
854 let user_key = format!("user:credentials:{username}");
855 let stored_bytes = match self.storage.get_kv(&user_key).await? {
856 Some(bytes) => bytes,
857 None => {
858 let _ = verify_password(
860 password,
861 "$argon2id$v=19$m=19456,t=2,p=1$dGVzdHNhbHRmb3J0aW1pbmc$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
862 );
863 return Ok(None);
864 }
865 };
866
867 let user_data_str = String::from_utf8(stored_bytes)
868 .map_err(|e| AuthError::internal(format!("Failed to parse user data: {e}")))?;
869 let user_data: serde_json::Value = serde_json::from_str(&user_data_str)
870 .map_err(|e| AuthError::internal(format!("Failed to parse user JSON: {e}")))?;
871
872 let password_hash = user_data["password_hash"].as_str().ok_or_else(|| {
873 AuthError::internal("Missing password hash in user record".to_string())
874 })?;
875
876 if !verify_password(password, password_hash).unwrap_or(false) {
877 return Ok(None);
878 }
879
880 let user_id = user_data["user_id"]
881 .as_str()
882 .ok_or_else(|| AuthError::internal("Missing user_id in user record".to_string()))?
883 .to_string();
884
885 let canonical_key = format!("user:{}", user_id);
887 if let Ok(Some(canonical_bytes)) = self.storage.get_kv(&canonical_key).await
888 && let Ok(canonical_str) = String::from_utf8(canonical_bytes)
889 && let Ok(canonical_data) = serde_json::from_str::<serde_json::Value>(&canonical_str)
890 && !canonical_data["active"].as_bool().unwrap_or(true)
891 {
892 return Ok(None);
893 }
894
895 let mfa_enabled = matches!(
896 self.storage
897 .get_kv(&format!("mfa_enabled:{}", user_id))
898 .await,
899 Ok(Some(_))
900 );
901
902 Ok(Some(CredentialCheckResult {
903 user_id,
904 mfa_enabled,
905 }))
906 }
907
908 pub async fn update_user_password(&self, username: &str, new_password: &str) -> Result<()> {
915 debug!("Updating password for user: {}", username);
916
917 crate::utils::validation::validate_password(new_password)
918 .map_err(|e| AuthError::validation(format!("Password validation failed: {e}")))?;
919
920 let username_key = format!("user:username:{}", username);
921 let user_id_data = self
922 .storage
923 .get_kv(&username_key)
924 .await?
925 .ok_or_else(|| AuthError::validation("User not found".to_string()))?;
926 let user_id = String::from_utf8(user_id_data)
927 .map_err(|e| AuthError::crypto(format!("Invalid user ID format: {}", e)))?;
928
929 let user_key = format!("user:{}", user_id);
930 let user_bytes = self
931 .storage
932 .get_kv(&user_key)
933 .await?
934 .ok_or_else(|| AuthError::validation("User not found".to_string()))?;
935 let mut user_data: serde_json::Value = serde_json::from_slice(&user_bytes)
936 .map_err(|e| AuthError::crypto(format!("Failed to parse user data: {}", e)))?;
937
938 let password_hash = bcrypt::hash(new_password, bcrypt::DEFAULT_COST)
939 .map_err(|e| AuthError::crypto(format!("Failed to hash password: {}", e)))?;
940 user_data["password_hash"] = serde_json::json!(password_hash);
941 user_data["updated_at"] = serde_json::json!(chrono::Utc::now().to_rfc3339());
942 self.storage
943 .store_kv(&user_key, user_data.to_string().as_bytes(), None)
944 .await?;
945
946 let creds_key = format!("user:credentials:{}", username);
948 let creds_hash = crate::utils::password::hash_password(new_password)
949 .map_err(|e| AuthError::crypto(format!("Failed to hash login credentials: {e}")))?;
950 let creds_bytes =
951 self.storage.get_kv(&creds_key).await?.ok_or_else(|| {
952 AuthError::internal("Login credentials record not found".to_string())
953 })?;
954 let mut creds: serde_json::Value = serde_json::from_slice(&creds_bytes)
955 .map_err(|e| AuthError::internal(format!("Failed to parse credentials record: {e}")))?;
956 creds["password_hash"] = serde_json::json!(creds_hash);
957 creds["updated_at"] = serde_json::json!(chrono::Utc::now().to_rfc3339());
958 self.storage
959 .store_kv(&creds_key, creds.to_string().as_bytes(), None)
960 .await?;
961
962 info!("Password updated for user: {}", username);
963 Ok(())
964 }
965
966 pub async fn update_user_password_by_id(
973 &self,
974 user_id: &str,
975 new_password: &str,
976 ) -> Result<()> {
977 let username = self.get_username_by_id(user_id).await?;
978 self.update_user_password(&username, new_password).await
979 }
980}
981
982#[cfg(test)]
983mod tests {
984 use super::*;
985 use crate::storage::MemoryStorage;
986
987 fn make_manager() -> UserManager {
988 UserManager::new(Arc::new(MemoryStorage::new()))
989 }
990
991 #[tokio::test]
994 async fn test_register_user_success() {
995 let mgr = make_manager();
996 let id = mgr
997 .register_user("alice", "alice@example.com", "StrongP@ss1!")
998 .await
999 .unwrap();
1000 assert!(id.starts_with("user"));
1001 }
1002
1003 #[tokio::test]
1004 async fn test_register_user_duplicate_username() {
1005 let mgr = make_manager();
1006 mgr.register_user("bob", "bob@example.com", "StrongP@ss1!")
1007 .await
1008 .unwrap();
1009 let err = mgr
1010 .register_user("bob", "bob2@example.com", "StrongP@ss1!")
1011 .await;
1012 assert!(err.is_err());
1013 }
1014
1015 #[tokio::test]
1016 async fn test_register_user_duplicate_email() {
1017 let mgr = make_manager();
1018 mgr.register_user("carol", "dup@example.com", "StrongP@ss1!")
1019 .await
1020 .unwrap();
1021 let err = mgr
1022 .register_user("carol2", "dup@example.com", "StrongP@ss1!")
1023 .await;
1024 assert!(err.is_err());
1025 }
1026
1027 #[tokio::test]
1030 async fn test_get_user_info_success() {
1031 let mgr = make_manager();
1032 let id = mgr
1033 .register_user("dave", "dave@example.com", "StrongP@ss1!")
1034 .await
1035 .unwrap();
1036 let info = mgr.get_user_info(&id).await.unwrap();
1037 assert_eq!(info.username, "dave");
1038 assert!(info.active);
1039 }
1040
1041 #[tokio::test]
1042 async fn test_get_user_info_not_found() {
1043 let mgr = make_manager();
1044 assert!(mgr.get_user_info("nonexistent").await.is_err());
1045 }
1046
1047 #[tokio::test]
1050 async fn test_user_exists_true() {
1051 let mgr = make_manager();
1052 let id = mgr
1053 .register_user("eve", "eve@example.com", "StrongP@ss1!")
1054 .await
1055 .unwrap();
1056 assert!(mgr.user_exists(&id).await.unwrap());
1057 }
1058
1059 #[tokio::test]
1060 async fn test_user_exists_false() {
1061 let mgr = make_manager();
1062 assert!(!mgr.user_exists("nobody").await.unwrap());
1063 }
1064
1065 #[tokio::test]
1066 async fn test_user_exists_empty_id() {
1067 let mgr = make_manager();
1068 assert!(!mgr.user_exists("").await.unwrap());
1069 }
1070
1071 #[tokio::test]
1074 async fn test_delete_user_success() {
1075 let mgr = make_manager();
1076 let id = mgr
1077 .register_user("frank", "frank@example.com", "StrongP@ss1!")
1078 .await
1079 .unwrap();
1080 mgr.delete_user("frank").await.unwrap();
1081 assert!(!mgr.user_exists(&id).await.unwrap());
1082 }
1083
1084 #[tokio::test]
1085 async fn test_delete_user_not_found() {
1086 let mgr = make_manager();
1087 assert!(mgr.delete_user("ghost").await.is_err());
1088 }
1089
1090 #[tokio::test]
1091 async fn test_delete_user_by_id() {
1092 let mgr = make_manager();
1093 let id = mgr
1094 .register_user("gina", "gina@example.com", "StrongP@ss1!")
1095 .await
1096 .unwrap();
1097 mgr.delete_user_by_id(&id).await.unwrap();
1098 assert!(!mgr.user_exists(&id).await.unwrap());
1099 }
1100
1101 #[tokio::test]
1104 async fn test_list_users_empty() {
1105 let mgr = make_manager();
1106 let users = mgr.list_users(None, None, false).await.unwrap();
1107 assert!(users.is_empty());
1108 }
1109
1110 #[tokio::test]
1111 async fn test_list_users_with_limit_and_offset() {
1112 let mgr = make_manager();
1113 mgr.register_user("u1", "u1@example.com", "StrongP@ss1!")
1114 .await
1115 .unwrap();
1116 mgr.register_user("u2", "u2@example.com", "StrongP@ss1!")
1117 .await
1118 .unwrap();
1119 mgr.register_user("u3", "u3@example.com", "StrongP@ss1!")
1120 .await
1121 .unwrap();
1122 let page = mgr.list_users(Some(1), Some(1), false).await.unwrap();
1123 assert_eq!(page.len(), 1);
1124 }
1125
1126 #[tokio::test]
1129 async fn test_verify_password_correct() {
1130 let mgr = make_manager();
1131 let id = mgr
1132 .register_user("hank", "hank@example.com", "StrongP@ss1!")
1133 .await
1134 .unwrap();
1135 assert!(mgr.verify_user_password(&id, "StrongP@ss1!").await.unwrap());
1136 }
1137
1138 #[tokio::test]
1139 async fn test_verify_password_incorrect() {
1140 let mgr = make_manager();
1141 let id = mgr
1142 .register_user("ivan", "ivan@example.com", "StrongP@ss1!")
1143 .await
1144 .unwrap();
1145 assert!(!mgr.verify_user_password(&id, "wrong").await.unwrap());
1146 }
1147
1148 #[tokio::test]
1149 async fn test_verify_password_user_not_found() {
1150 let mgr = make_manager();
1151 assert!(mgr.verify_user_password("ghost", "x").await.is_err());
1152 }
1153
1154 #[tokio::test]
1157 async fn test_update_password() {
1158 let mgr = make_manager();
1159 let id = mgr
1160 .register_user("jack", "jack@example.com", "StrongP@ss1!")
1161 .await
1162 .unwrap();
1163 mgr.update_user_password("jack", "NewStr0ng!Pass")
1164 .await
1165 .unwrap();
1166 assert!(
1167 mgr.verify_user_password(&id, "NewStr0ng!Pass")
1168 .await
1169 .unwrap()
1170 );
1171 assert!(!mgr.verify_user_password(&id, "StrongP@ss1!").await.unwrap());
1172 }
1173
1174 #[tokio::test]
1175 async fn test_update_password_user_not_found() {
1176 let mgr = make_manager();
1177 assert!(
1178 mgr.update_user_password("ghost", "NewStr0ng!Pass")
1179 .await
1180 .is_err()
1181 );
1182 }
1183
1184 #[tokio::test]
1187 async fn test_update_user_roles() {
1188 let mgr = make_manager();
1189 let id = mgr
1190 .register_user("kate", "kate@example.com", "StrongP@ss1!")
1191 .await
1192 .unwrap();
1193 mgr.update_user_roles(&id, &["admin".into(), "user".into()])
1194 .await
1195 .unwrap();
1196 let info = mgr.get_user_info(&id).await.unwrap();
1197 assert!(info.roles.contains(&"admin".to_string()));
1198 }
1199
1200 #[tokio::test]
1201 async fn test_update_user_roles_not_found() {
1202 let mgr = make_manager();
1203 assert!(
1204 mgr.update_user_roles("ghost", &["admin".into()])
1205 .await
1206 .is_err()
1207 );
1208 }
1209
1210 #[tokio::test]
1213 async fn test_set_user_active_disable() {
1214 let mgr = make_manager();
1215 let id = mgr
1216 .register_user("leon", "leon@example.com", "StrongP@ss1!")
1217 .await
1218 .unwrap();
1219 mgr.set_user_active(&id, false).await.unwrap();
1220 let info = mgr.get_user_info(&id).await.unwrap();
1221 assert!(!info.active);
1222 }
1223
1224 #[tokio::test]
1225 async fn test_set_user_active_not_found() {
1226 let mgr = make_manager();
1227 assert!(mgr.set_user_active("ghost", false).await.is_err());
1228 }
1229
1230 #[tokio::test]
1233 async fn test_update_user_email() {
1234 let mgr = make_manager();
1235 let id = mgr
1236 .register_user("mary", "mary@example.com", "StrongP@ss1!")
1237 .await
1238 .unwrap();
1239 mgr.update_user_email(&id, "mary_new@example.com")
1240 .await
1241 .unwrap();
1242 let info = mgr.get_user_info(&id).await.unwrap();
1243 assert_eq!(info.email.as_deref(), Some("mary_new@example.com"));
1244 }
1245
1246 #[tokio::test]
1247 async fn test_update_user_email_already_taken() {
1248 let mgr = make_manager();
1249 mgr.register_user("n1", "taken@example.com", "StrongP@ss1!")
1250 .await
1251 .unwrap();
1252 let id2 = mgr
1253 .register_user("n2", "n2@example.com", "StrongP@ss1!")
1254 .await
1255 .unwrap();
1256 assert!(
1257 mgr.update_user_email(&id2, "taken@example.com")
1258 .await
1259 .is_err()
1260 );
1261 }
1262
1263 #[tokio::test]
1266 async fn test_create_and_validate_api_key() {
1267 let mgr = make_manager();
1268 let id = mgr
1269 .register_user("oscar", "oscar@example.com", "StrongP@ss1!")
1270 .await
1271 .unwrap();
1272 let key = mgr.create_api_key(&id, None).await.unwrap();
1273 assert!(key.starts_with("ak_"));
1274 let info = mgr.validate_api_key(&key).await.unwrap();
1275 assert_eq!(info.id, id);
1276 }
1277
1278 #[tokio::test]
1279 async fn test_validate_api_key_invalid() {
1280 let mgr = make_manager();
1281 assert!(mgr.validate_api_key("bad_key").await.is_err());
1282 }
1283
1284 #[tokio::test]
1285 async fn test_revoke_api_key() {
1286 let mgr = make_manager();
1287 let id = mgr
1288 .register_user("pat", "pat@example.com", "StrongP@ss1!")
1289 .await
1290 .unwrap();
1291 let key = mgr.create_api_key(&id, None).await.unwrap();
1292 mgr.revoke_api_key(&key).await.unwrap();
1293 assert!(mgr.validate_api_key(&key).await.is_err());
1294 }
1295
1296 #[tokio::test]
1297 async fn test_revoke_api_key_not_found() {
1298 let mgr = make_manager();
1299 assert!(mgr.revoke_api_key("nonexistent").await.is_err());
1300 }
1301
1302 #[tokio::test]
1305 async fn test_validate_username_valid() {
1306 let mgr = make_manager();
1307 assert!(mgr.validate_username("good_user-1").await.unwrap());
1308 }
1309
1310 #[tokio::test]
1311 async fn test_validate_username_too_short() {
1312 let mgr = make_manager();
1313 assert!(!mgr.validate_username("ab").await.unwrap());
1314 }
1315
1316 #[tokio::test]
1317 async fn test_validate_username_special_chars() {
1318 let mgr = make_manager();
1319 assert!(!mgr.validate_username("user@name").await.unwrap());
1320 }
1321
1322 #[tokio::test]
1325 async fn test_validate_display_name_valid() {
1326 let mgr = make_manager();
1327 assert!(mgr.validate_display_name("Alice Bob").await.unwrap());
1328 }
1329
1330 #[tokio::test]
1331 async fn test_validate_display_name_empty() {
1332 let mgr = make_manager();
1333 assert!(!mgr.validate_display_name("").await.unwrap());
1334 }
1335
1336 #[tokio::test]
1337 async fn test_validate_display_name_only_whitespace() {
1338 let mgr = make_manager();
1339 assert!(!mgr.validate_display_name(" ").await.unwrap());
1340 }
1341
1342 #[tokio::test]
1345 async fn test_validate_password_strong() {
1346 let mgr = make_manager();
1347 assert!(
1348 mgr.validate_password_strength("C0mpl3x!P@ssw0rd")
1349 .await
1350 .unwrap()
1351 );
1352 }
1353
1354 #[tokio::test]
1355 async fn test_validate_password_weak() {
1356 let mgr = make_manager();
1357 assert!(!mgr.validate_password_strength("123").await.unwrap());
1358 }
1359
1360 #[tokio::test]
1363 async fn test_validate_user_input_clean() {
1364 let mgr = make_manager();
1365 assert!(mgr.validate_user_input("Hello World 123").await.unwrap());
1366 }
1367
1368 #[tokio::test]
1369 async fn test_validate_user_input_html_tags() {
1370 let mgr = make_manager();
1371 assert!(
1372 !mgr.validate_user_input("<script>alert(1)</script>")
1373 .await
1374 .unwrap()
1375 );
1376 }
1377
1378 #[tokio::test]
1379 async fn test_validate_user_input_sql_injection() {
1380 let mgr = make_manager();
1381 assert!(
1382 !mgr.validate_user_input("'; drop table users--")
1383 .await
1384 .unwrap()
1385 );
1386 }
1387
1388 #[tokio::test]
1389 async fn test_validate_user_input_template_injection() {
1390 let mgr = make_manager();
1391 assert!(!mgr.validate_user_input("${evil}").await.unwrap());
1392 }
1393
1394 #[tokio::test]
1395 async fn test_validate_user_input_path_traversal() {
1396 let mgr = make_manager();
1397 assert!(!mgr.validate_user_input("../../etc/passwd").await.unwrap());
1398 }
1399
1400 #[tokio::test]
1401 async fn test_validate_user_input_javascript_uri() {
1402 let mgr = make_manager();
1403 assert!(
1404 !mgr.validate_user_input("javascript:alert(1)")
1405 .await
1406 .unwrap()
1407 );
1408 }
1409
1410 #[tokio::test]
1411 async fn test_validate_user_input_empty() {
1412 let mgr = make_manager();
1413 assert!(!mgr.validate_user_input("").await.unwrap());
1414 }
1415
1416 #[tokio::test]
1417 async fn test_validate_user_input_encoded_tags() {
1418 let mgr = make_manager();
1419 assert!(!mgr.validate_user_input("%3cscript%3e").await.unwrap());
1420 }
1421
1422 #[tokio::test]
1425 async fn test_username_exists() {
1426 let mgr = make_manager();
1427 mgr.register_user("quinn", "quinn@example.com", "StrongP@ss1!")
1428 .await
1429 .unwrap();
1430 assert!(mgr.username_exists("quinn").await.unwrap());
1431 assert!(!mgr.username_exists("noone").await.unwrap());
1432 }
1433
1434 #[tokio::test]
1435 async fn test_email_exists() {
1436 let mgr = make_manager();
1437 mgr.register_user("ross", "ross@example.com", "StrongP@ss1!")
1438 .await
1439 .unwrap();
1440 assert!(mgr.email_exists("ross@example.com").await.unwrap());
1441 assert!(!mgr.email_exists("nobody@example.com").await.unwrap());
1442 }
1443
1444 #[tokio::test]
1447 async fn test_get_user_by_username() {
1448 let mgr = make_manager();
1449 mgr.register_user("sam", "sam@example.com", "StrongP@ss1!")
1450 .await
1451 .unwrap();
1452 let data = mgr.get_user_by_username("sam").await.unwrap();
1453 assert_eq!(data["username"].as_str(), Some("sam"));
1454 }
1455
1456 #[tokio::test]
1457 async fn test_get_user_by_username_not_found() {
1458 let mgr = make_manager();
1459 assert!(mgr.get_user_by_username("ghost").await.is_err());
1460 }
1461
1462 #[tokio::test]
1465 async fn test_get_user_profile() {
1466 let mgr = make_manager();
1467 let id = mgr
1468 .register_user("tina", "tina@example.com", "StrongP@ss1!")
1469 .await
1470 .unwrap();
1471 let profile = mgr.get_user_profile(&id).await.unwrap();
1472 assert_eq!(profile.username.as_deref(), Some("tina"));
1473 assert_eq!(profile.email.as_deref(), Some("tina@example.com"));
1474 assert!(!profile.additional_data.contains_key("password_hash"));
1476 }
1477
1478 #[tokio::test]
1479 async fn test_get_user_profile_not_found() {
1480 let mgr = make_manager();
1481 assert!(mgr.get_user_profile("ghost").await.is_err());
1482 }
1483
1484 #[tokio::test]
1487 async fn test_get_user_roles_default() {
1488 let mgr = make_manager();
1489 let id = mgr
1490 .register_user("uma", "uma@example.com", "StrongP@ss1!")
1491 .await
1492 .unwrap();
1493 let roles = mgr.get_user_roles(&id).await.unwrap();
1494 assert!(roles.contains(&"user".to_string()));
1495 }
1496
1497 #[tokio::test]
1498 async fn test_get_user_roles_not_found_returns_default() {
1499 let mgr = make_manager();
1500 let roles = mgr.get_user_roles("ghost").await.unwrap();
1501 assert_eq!(roles, vec!["user".to_string()]);
1502 }
1503
1504 #[tokio::test]
1507 async fn test_verify_login_credentials_success() {
1508 let mgr = make_manager();
1509 mgr.register_user("vera", "vera@example.com", "StrongP@ss1!")
1510 .await
1511 .unwrap();
1512 let result = mgr
1513 .verify_login_credentials("vera", "StrongP@ss1!")
1514 .await
1515 .unwrap();
1516 assert!(result.is_some());
1517 assert!(!result.unwrap().mfa_enabled);
1518 }
1519
1520 #[tokio::test]
1521 async fn test_verify_login_credentials_wrong_password() {
1522 let mgr = make_manager();
1523 mgr.register_user("wanda", "wanda@example.com", "StrongP@ss1!")
1524 .await
1525 .unwrap();
1526 let result = mgr
1527 .verify_login_credentials("wanda", "wrong")
1528 .await
1529 .unwrap();
1530 assert!(result.is_none());
1531 }
1532
1533 #[tokio::test]
1534 async fn test_verify_login_credentials_unknown_user() {
1535 let mgr = make_manager();
1536 let result = mgr
1537 .verify_login_credentials("ghost", "StrongP@ss1!")
1538 .await
1539 .unwrap();
1540 assert!(result.is_none());
1541 }
1542
1543 #[tokio::test]
1544 async fn test_verify_login_credentials_empty_inputs() {
1545 let mgr = make_manager();
1546 assert!(
1547 mgr.verify_login_credentials("", "pass")
1548 .await
1549 .unwrap()
1550 .is_none()
1551 );
1552 assert!(
1553 mgr.verify_login_credentials("user", "")
1554 .await
1555 .unwrap()
1556 .is_none()
1557 );
1558 }
1559
1560 #[tokio::test]
1561 async fn test_verify_login_credentials_deactivated() {
1562 let mgr = make_manager();
1563 let id = mgr
1564 .register_user("xena", "xena@example.com", "StrongP@ss1!")
1565 .await
1566 .unwrap();
1567 mgr.set_user_active(&id, false).await.unwrap();
1568 let result = mgr
1569 .verify_login_credentials("xena", "StrongP@ss1!")
1570 .await
1571 .unwrap();
1572 assert!(result.is_none());
1573 }
1574
1575 #[tokio::test]
1578 async fn test_get_username_by_id() {
1579 let mgr = make_manager();
1580 let id = mgr
1581 .register_user("yara", "yara@example.com", "StrongP@ss1!")
1582 .await
1583 .unwrap();
1584 let username = mgr.get_username_by_id(&id).await.unwrap();
1585 assert_eq!(username, "yara");
1586 }
1587
1588 #[tokio::test]
1589 async fn test_get_username_by_id_not_found() {
1590 let mgr = make_manager();
1591 assert!(mgr.get_username_by_id("ghost").await.is_err());
1592 }
1593
1594 #[tokio::test]
1597 async fn test_list_users_active_only() {
1598 let mgr = make_manager();
1599 let id1 = mgr
1600 .register_user("active1", "active1@example.com", "StrongP@ss1!")
1601 .await
1602 .unwrap();
1603 let id2 = mgr
1604 .register_user("inactive1", "inactive1@example.com", "StrongP@ss1!")
1605 .await
1606 .unwrap();
1607 mgr.set_user_active(&id2, false).await.unwrap();
1608
1609 let all = mgr.list_users(None, None, false).await.unwrap();
1610 let active = mgr.list_users(None, None, true).await.unwrap();
1611 assert!(all.len() > active.len());
1612 assert!(active.iter().all(|u| u.active));
1613 assert!(all.iter().any(|u| u.id == id1));
1615 assert!(all.iter().any(|u| u.id == id2));
1616 }
1617}