1use std::collections::HashMap;
4use std::sync::Arc;
5
6use crate::utils::Time;
7use async_trait::async_trait;
8use chrono::{DateTime, Utc};
9use serde::{Deserialize, Serialize};
10use tokio::sync::RwLock;
11use uuid::Uuid;
12
13use crate::error::{Error, Result};
14use crate::manager::{ManagedState, Manager, ManagerStatus, PlatformRequirements};
15
16pub type UserId = Uuid;
17
18#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
19pub struct User {
20 pub id: UserId,
21 pub username: String,
22 pub email: String,
23 pub roles: Vec<Role>,
24 pub permissions: Vec<Permission>,
25 pub preferences: UserPreferences,
26 pub profile: UserProfile,
27 pub created_at: DateTime<Utc>,
28 pub last_login: Option<DateTime<Utc>>,
29 pub is_active: bool,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
33pub struct Role {
34 pub id: String,
35 pub name: String,
36 pub description: String,
37 pub permissions: Vec<Permission>,
38 pub ui_layout: Option<String>,
39 pub is_system_role: bool,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
43pub struct Permission {
44 pub resource: String, pub action: String, pub scope: PermissionScope,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
50pub enum PermissionScope {
51 Own, Department(String), Global, }
55
56#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
57pub struct UserPreferences {
58 pub theme: String,
59 pub language: String,
60 pub timezone: String,
61 pub notifications_enabled: bool,
62 pub custom_settings: HashMap<String, serde_json::Value>,
63}
64
65impl Default for UserPreferences {
66 fn default() -> Self {
67 Self {
68 theme: "default".to_string(),
69 language: "en".to_string(),
70 timezone: "UTC".to_string(),
71 notifications_enabled: true,
72 custom_settings: HashMap::new(),
73 }
74 }
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
78pub struct UserProfile {
79 pub display_name: String,
80 pub avatar_url: Option<String>,
81 pub bio: Option<String>,
82 pub department: Option<String>,
83 pub title: Option<String>,
84 pub contact_info: ContactInfo,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
88pub struct ContactInfo {
89 pub phone: Option<String>,
90 pub address: Option<String>,
91 pub emergency_contact: Option<String>,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct UserSession {
96 pub id: Uuid,
97 pub user_id: UserId,
98 pub created_at: DateTime<Utc>,
99 pub expires_at: DateTime<Utc>,
100 pub last_activity: DateTime<Utc>,
101 pub ip_address: Option<String>,
102 pub user_agent: Option<String>,
103 pub is_active: bool,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub enum Credentials {
108 Password {
109 username: String,
110 password: String,
111 },
112 Token {
113 token: String,
114 },
115 OAuth2 {
116 provider: String,
117 code: String,
118 state: Option<String>,
119 },
120 Biometric {
121 user_id: UserId,
122 biometric_data: Vec<u8>,
123 },
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct AuthResult {
128 pub user: User,
129 pub session: UserSession,
130 pub tokens: TokenPair,
131 pub requires_mfa: bool,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
135pub struct TokenPair {
136 pub access_token: String,
137 pub refresh_token: String,
138 pub token_type: String,
139 pub expires_in: u64,
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize)]
143pub struct Claims {
144 pub sub: String, pub iat: i64, pub exp: i64, pub aud: String, pub iss: String, pub roles: Vec<String>,
150 pub permissions: Vec<String>,
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub enum AuthProviderType {
155 Local,
156 OAuth2 { provider: String },
157 SAML { provider: String },
158 LDAP { server: String },
159}
160
161#[cfg(not(target_arch = "wasm32"))]
162#[async_trait]
163pub trait AuthProvider: Send + Sync {
164 async fn authenticate(&self, credentials: &Credentials) -> Result<AuthResult>;
165 async fn refresh_token(&self, refresh_token: &str) -> Result<TokenPair>;
166 async fn validate_token(&self, token: &str) -> Result<Claims>;
167 fn provider_type(&self) -> AuthProviderType;
168}
169
170#[cfg(target_arch = "wasm32")]
171#[async_trait(?Send)]
172pub trait AuthProvider: Sync {
173 async fn authenticate(&self, credentials: &Credentials) -> Result<AuthResult>;
174 async fn refresh_token(&self, refresh_token: &str) -> Result<TokenPair>;
175 async fn validate_token(&self, token: &str) -> Result<Claims>;
176 fn provider_type(&self) -> AuthProviderType;
177}
178
179#[cfg(not(target_arch = "wasm32"))]
180#[async_trait]
181pub trait SessionStore: Send + Sync {
182 async fn create_session(&self, session: UserSession) -> Result<()>;
183 async fn get_session(&self, session_id: Uuid) -> Result<Option<UserSession>>;
184 async fn update_session(&self, session: UserSession) -> Result<()>;
185 async fn delete_session(&self, session_id: Uuid) -> Result<()>;
186 async fn cleanup_expired_sessions(&self) -> Result<u64>;
187}
188
189#[cfg(target_arch = "wasm32")]
190#[async_trait(?Send)]
191pub trait SessionStore: Sync {
192 async fn create_session(&self, session: UserSession) -> Result<()>;
193 async fn get_session(&self, session_id: Uuid) -> Result<Option<UserSession>>;
194 async fn update_session(&self, session: UserSession) -> Result<()>;
195 async fn delete_session(&self, session_id: Uuid) -> Result<()>;
196 async fn cleanup_expired_sessions(&self) -> Result<u64>;
197}
198
199#[cfg(not(target_arch = "wasm32"))]
200#[async_trait]
201pub trait UserStore: Send + Sync {
202 async fn create_user(&self, user: User) -> Result<()>;
203 async fn get_user(&self, user_id: UserId) -> Result<Option<User>>;
204 async fn get_user_by_username(&self, username: &str) -> Result<Option<User>>;
205 async fn get_user_by_email(&self, email: &str) -> Result<Option<User>>;
206 async fn update_user(&self, user: User) -> Result<()>;
207 async fn delete_user(&self, user_id: UserId) -> Result<()>;
208 async fn list_users(&self, limit: Option<u32>, offset: Option<u32>) -> Result<Vec<User>>;
209}
210
211#[cfg(target_arch = "wasm32")]
212#[async_trait(?Send)]
213pub trait UserStore: Sync {
214 async fn create_user(&self, user: User) -> Result<()>;
215 async fn get_user(&self, user_id: UserId) -> Result<Option<User>>;
216 async fn get_user_by_username(&self, username: &str) -> Result<Option<User>>;
217 async fn get_user_by_email(&self, email: &str) -> Result<Option<User>>;
218 async fn update_user(&self, user: User) -> Result<()>;
219 async fn delete_user(&self, user_id: UserId) -> Result<()>;
220 async fn list_users(&self, limit: Option<u32>, offset: Option<u32>) -> Result<Vec<User>>;
221}
222
223pub struct PermissionCache {
224 cache: HashMap<(UserId, String, String), bool>,
225 last_updated: DateTime<Utc>,
226}
227
228impl PermissionCache {
229 fn new() -> Self {
230 Self {
231 cache: HashMap::new(),
232 last_updated: Time::now(),
233 }
234 }
235
236 fn check_permission(&self, user_id: UserId, resource: &str, action: &str) -> Option<bool> {
237 self.cache
238 .get(&(user_id, resource.to_string(), action.to_string()))
239 .copied()
240 }
241
242 fn cache_permission(&mut self, user_id: UserId, resource: &str, action: &str, allowed: bool) {
243 self.cache
244 .insert((user_id, resource.to_string(), action.to_string()), allowed);
245 self.last_updated = Time::now();
246 }
247
248 fn clear_user_cache(&mut self, user_id: UserId) {
249 self.cache.retain(|(id, _, _), _value| *id != user_id);
250 self.last_updated = Time::now();
251 }
252}
253
254#[derive(Debug, Clone, Serialize, Deserialize)]
255pub struct SecurityPolicy {
256 pub password_min_length: u32,
257 pub password_require_uppercase: bool,
258 pub password_require_lowercase: bool,
259 pub password_require_numbers: bool,
260 pub password_require_symbols: bool,
261 pub session_timeout_minutes: u64,
262 pub max_login_attempts: u32,
263 pub lockout_duration_minutes: u64,
264 pub require_mfa: bool,
265 pub allowed_login_methods: Vec<AuthProviderType>,
266}
267
268impl Default for SecurityPolicy {
269 fn default() -> Self {
270 Self {
271 password_min_length: 8,
272 password_require_uppercase: true,
273 password_require_lowercase: true,
274 password_require_numbers: true,
275 password_require_symbols: false,
276 session_timeout_minutes: 480, max_login_attempts: 5,
278 lockout_duration_minutes: 30,
279 require_mfa: false,
280 allowed_login_methods: vec![AuthProviderType::Local],
281 }
282 }
283}
284
285pub struct AccountManager {
286 state: ManagedState,
287 auth_providers: HashMap<String, Box<dyn AuthProvider>>,
288 session_store: Box<dyn SessionStore>,
289 permission_cache: Arc<RwLock<PermissionCache>>,
290 user_store: Box<dyn UserStore>,
291 security_policy: SecurityPolicy,
292 current_user: Arc<RwLock<Option<User>>>,
293 current_session: Arc<RwLock<Option<UserSession>>>,
294}
295
296impl std::fmt::Debug for AccountManager {
297 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
298 f.debug_struct("AccountManager")
299 .field("security_policy", &self.security_policy)
300 .finish()
301 }
302}
303
304impl AccountManager {
305 pub fn new(
306 session_store: Box<dyn SessionStore>,
307 user_store: Box<dyn UserStore>,
308 security_policy: SecurityPolicy,
309 ) -> Self {
310 Self {
311 state: ManagedState::new(Uuid::new_v4(), "account_manager"),
312 auth_providers: HashMap::new(),
313 session_store,
314 permission_cache: Arc::new(RwLock::new(PermissionCache::new())),
315 user_store,
316 security_policy,
317 current_user: Arc::new(RwLock::new(None)),
318 current_session: Arc::new(RwLock::new(None)),
319 }
320 }
321
322 pub fn register_auth_provider(&mut self, name: String, provider: Box<dyn AuthProvider>) {
323 self.auth_providers.insert(name, provider);
324 }
325
326 pub async fn authenticate(
327 &self,
328 credentials: Credentials,
329 provider: Option<&str>,
330 ) -> Result<AuthResult> {
331 let provider_name = provider.unwrap_or("local");
332 let auth_provider = self.auth_providers.get(provider_name).ok_or_else(|| {
333 Error::authentication(format!(
334 "Authentication provider '{}' not found",
335 provider_name
336 ))
337 })?;
338
339 let auth_result = auth_provider.authenticate(&credentials).await?;
340
341 self.session_store
343 .create_session(auth_result.session.clone())
344 .await?;
345
346 *self.current_user.write().await = Some(auth_result.user.clone());
348 *self.current_session.write().await = Some(auth_result.session.clone());
349
350 self.permission_cache
352 .write()
353 .await
354 .clear_user_cache(auth_result.user.id);
355
356 Ok(auth_result)
357 }
358
359 pub async fn validate_token(&self, token: &str, provider: Option<&str>) -> Result<Claims> {
360 let provider_name = provider.unwrap_or("local");
361 let auth_provider = self.auth_providers.get(provider_name).ok_or_else(|| {
362 Error::authentication(format!(
363 "Authentication provider '{}' not found",
364 provider_name
365 ))
366 })?;
367
368 auth_provider.validate_token(token).await
369 }
370
371 pub async fn refresh_token(
372 &self,
373 refresh_token: &str,
374 provider: Option<&str>,
375 ) -> Result<TokenPair> {
376 let provider_name = provider.unwrap_or("local");
377 let auth_provider = self.auth_providers.get(provider_name).ok_or_else(|| {
378 Error::authentication(format!(
379 "Authentication provider '{}' not found",
380 provider_name
381 ))
382 })?;
383
384 auth_provider.refresh_token(refresh_token).await
385 }
386
387 pub async fn logout(&self, session_id: Option<Uuid>) -> Result<()> {
388 if let Some(id) = session_id {
389 self.session_store.delete_session(id).await?;
390 } else if let Some(session) = self.current_session.read().await.as_ref() {
391 self.session_store.delete_session(session.id).await?;
392 }
393
394 *self.current_user.write().await = None;
396 *self.current_session.write().await = None;
397
398 Ok(())
399 }
400
401 pub async fn current_user(&self) -> Option<User> {
402 self.current_user.read().await.clone()
403 }
404
405 pub async fn current_session(&self) -> Option<UserSession> {
406 self.current_session.read().await.clone()
407 }
408
409 pub async fn check_permission(
410 &self,
411 user_id: UserId,
412 resource: &str,
413 action: &str,
414 ) -> Result<bool> {
415 if let Some(cached) = self
417 .permission_cache
418 .read()
419 .await
420 .check_permission(user_id, resource, action)
421 {
422 return Ok(cached);
423 }
424
425 let user = self
427 .user_store
428 .get_user(user_id)
429 .await?
430 .ok_or_else(|| Error::authorization(resource, action, "User not found"))?;
431
432 let has_permission = self.user_has_permission(&user, resource, action);
433
434 self.permission_cache.write().await.cache_permission(
436 user_id,
437 resource,
438 action,
439 has_permission,
440 );
441
442 Ok(has_permission)
443 }
444
445 pub async fn check_current_user_permission(
446 &self,
447 resource: &str,
448 action: &str,
449 ) -> Result<bool> {
450 let user = self
451 .current_user()
452 .await
453 .ok_or_else(|| Error::authorization(resource, action, "No authenticated user"))?;
454
455 self.check_permission(user.id, resource, action).await
456 }
457
458 pub async fn create_user(&self, mut user: User) -> Result<()> {
459 user.created_at = Time::now();
461 user.id = Uuid::new_v4();
462
463 self.user_store.create_user(user).await?;
465
466 Ok(())
467 }
468
469 pub async fn update_user(&self, user: User) -> Result<()> {
470 self.user_store.update_user(user.clone()).await?;
471
472 self.permission_cache
474 .write()
475 .await
476 .clear_user_cache(user.id);
477
478 if let Some(current) = self.current_user.read().await.as_ref() {
480 if current.id == user.id {
481 *self.current_user.write().await = Some(user);
482 }
483 }
484
485 Ok(())
486 }
487
488 pub async fn get_user(&self, user_id: UserId) -> Result<Option<User>> {
489 self.user_store.get_user(user_id).await
490 }
491
492 pub async fn get_user_by_username(&self, username: &str) -> Result<Option<User>> {
493 self.user_store.get_user_by_username(username).await
494 }
495
496 pub async fn list_users(&self, limit: Option<u32>, offset: Option<u32>) -> Result<Vec<User>> {
497 self.user_store.list_users(limit, offset).await
498 }
499
500 pub async fn cleanup_expired_sessions(&self) -> Result<u64> {
501 self.session_store.cleanup_expired_sessions().await
502 }
503
504 fn user_has_permission(&self, user: &User, resource: &str, action: &str) -> bool {
505 for permission in &user.permissions {
507 if self.permission_matches(permission, resource, action) {
508 return true;
509 }
510 }
511
512 for role in &user.roles {
514 for permission in &role.permissions {
515 if self.permission_matches(permission, resource, action) {
516 return true;
517 }
518 }
519 }
520
521 false
522 }
523
524 fn permission_matches(&self, permission: &Permission, resource: &str, action: &str) -> bool {
525 (permission.resource == resource || permission.resource == "*")
527 && (permission.action == action || permission.action == "*")
528 }
529}
530
531#[cfg(not(target_arch = "wasm32"))]
532#[async_trait]
533impl Manager for AccountManager {
534 fn name(&self) -> &str {
535 "account_manager"
536 }
537
538 fn id(&self) -> Uuid {
539 self.state.id()
540 }
541
542 async fn initialize(&mut self) -> Result<()> {
543 self.state
544 .set_state(crate::manager::ManagerState::Initializing)
545 .await;
546
547 self.state
550 .set_state(crate::manager::ManagerState::Running)
551 .await;
552 Ok(())
553 }
554
555 async fn shutdown(&mut self) -> Result<()> {
556 self.state
557 .set_state(crate::manager::ManagerState::ShuttingDown)
558 .await;
559
560 let _ = self.cleanup_expired_sessions().await;
562
563 self.state
564 .set_state(crate::manager::ManagerState::Shutdown)
565 .await;
566 Ok(())
567 }
568
569 async fn status(&self) -> ManagerStatus {
570 let mut status = self.state.status().await;
571
572 let current_user_id = self
573 .current_user()
574 .await
575 .map(|u| u.id.to_string())
576 .unwrap_or_else(|| "none".to_string());
577 status.add_metadata("current_user", serde_json::Value::String(current_user_id));
578 status.add_metadata(
579 "auth_providers",
580 serde_json::Value::from(self.auth_providers.len()),
581 );
582 status.add_metadata(
583 "security_policy",
584 serde_json::to_value(&self.security_policy).unwrap_or_default(),
585 );
586
587 status
588 }
589
590 fn required_permissions(&self) -> Vec<String> {
591 vec![
592 "auth.login".to_string(),
593 "auth.logout".to_string(),
594 "auth.manage_users".to_string(),
595 ]
596 }
597
598 fn platform_requirements(&self) -> PlatformRequirements {
599 PlatformRequirements {
600 requires_filesystem: false,
601 requires_network: true,
602 requires_database: true,
603 requires_native_apis: false,
604 minimum_permissions: self.required_permissions(),
605 }
606 }
607}
608
609#[cfg(target_arch = "wasm32")]
610#[async_trait(?Send)]
611impl Manager for AccountManager {
612 fn name(&self) -> &str {
613 "account_manager"
614 }
615
616 fn id(&self) -> Uuid {
617 self.state.id()
618 }
619
620 async fn initialize(&mut self) -> Result<()> {
621 self.state
622 .set_state(crate::manager::ManagerState::Initializing)
623 .await;
624
625 self.state
628 .set_state(crate::manager::ManagerState::Running)
629 .await;
630 Ok(())
631 }
632
633 async fn shutdown(&mut self) -> Result<()> {
634 self.state
635 .set_state(crate::manager::ManagerState::ShuttingDown)
636 .await;
637
638 let _ = self.cleanup_expired_sessions().await;
640
641 self.state
642 .set_state(crate::manager::ManagerState::Shutdown)
643 .await;
644 Ok(())
645 }
646
647 async fn status(&self) -> ManagerStatus {
648 let mut status = self.state.status().await;
649
650 let current_user_id = self
651 .current_user()
652 .await
653 .map(|u| u.id.to_string())
654 .unwrap_or_else(|| "none".to_string());
655 status.add_metadata("current_user", serde_json::Value::String(current_user_id));
656 status.add_metadata(
657 "auth_providers",
658 serde_json::Value::from(self.auth_providers.len()),
659 );
660 status.add_metadata(
661 "security_policy",
662 serde_json::to_value(&self.security_policy).unwrap_or_default(),
663 );
664
665 status
666 }
667
668 fn required_permissions(&self) -> Vec<String> {
669 vec![
670 "auth.login".to_string(),
671 "auth.logout".to_string(),
672 "auth.manage_users".to_string(),
673 ]
674 }
675
676 fn platform_requirements(&self) -> PlatformRequirements {
677 PlatformRequirements {
678 requires_filesystem: false,
679 requires_network: true,
680 requires_database: true,
681 requires_native_apis: false,
682 minimum_permissions: self.required_permissions(),
683 }
684 }
685}
686
687pub struct MemorySessionStore {
688 sessions: Arc<RwLock<HashMap<Uuid, UserSession>>>,
689}
690
691impl Default for MemorySessionStore {
692 fn default() -> Self {
693 Self::new()
694 }
695}
696
697impl MemorySessionStore {
698 pub fn new() -> Self {
699 Self {
700 sessions: Arc::new(RwLock::new(HashMap::new())),
701 }
702 }
703
704 #[allow(dead_code)]
705 fn default() -> Self {
706 Self::new()
707 }
708}
709
710#[cfg(not(target_arch = "wasm32"))]
711#[async_trait]
712impl SessionStore for MemorySessionStore {
713 async fn create_session(&self, session: UserSession) -> Result<()> {
714 self.sessions.write().await.insert(session.id, session);
715 Ok(())
716 }
717
718 async fn get_session(&self, session_id: Uuid) -> Result<Option<UserSession>> {
719 Ok(self.sessions.read().await.get(&session_id).cloned())
720 }
721
722 async fn update_session(&self, session: UserSession) -> Result<()> {
723 self.sessions.write().await.insert(session.id, session);
724 Ok(())
725 }
726
727 async fn delete_session(&self, session_id: Uuid) -> Result<()> {
728 self.sessions.write().await.remove(&session_id);
729 Ok(())
730 }
731
732 async fn cleanup_expired_sessions(&self) -> Result<u64> {
733 let now = Time::now();
734 let mut sessions = self.sessions.write().await;
735 let original_count = sessions.len();
736
737 sessions.retain(|_, session| session.expires_at > now);
738
739 Ok((original_count - sessions.len()) as u64)
740 }
741}
742
743#[cfg(target_arch = "wasm32")]
744#[async_trait(?Send)]
745impl SessionStore for MemorySessionStore {
746 async fn create_session(&self, session: UserSession) -> Result<()> {
747 self.sessions.write().await.insert(session.id, session);
748 Ok(())
749 }
750
751 async fn get_session(&self, session_id: Uuid) -> Result<Option<UserSession>> {
752 Ok(self.sessions.read().await.get(&session_id).cloned())
753 }
754
755 async fn update_session(&self, session: UserSession) -> Result<()> {
756 self.sessions.write().await.insert(session.id, session);
757 Ok(())
758 }
759
760 async fn delete_session(&self, session_id: Uuid) -> Result<()> {
761 self.sessions.write().await.remove(&session_id);
762 Ok(())
763 }
764
765 async fn cleanup_expired_sessions(&self) -> Result<u64> {
766 let now = Time::now();
767 let mut sessions = self.sessions.write().await;
768 let original_count = sessions.len();
769
770 sessions.retain(|_, session| session.expires_at > now);
771
772 Ok((original_count - sessions.len()) as u64)
773 }
774}
775
776pub struct MemoryUserStore {
777 users: Arc<RwLock<HashMap<UserId, User>>>,
778}
779
780impl Default for MemoryUserStore {
781 fn default() -> Self {
782 Self::new()
783 }
784}
785
786impl MemoryUserStore {
787 pub fn new() -> Self {
788 Self {
789 users: Arc::new(RwLock::new(HashMap::new())),
790 }
791 }
792}
793
794#[cfg(not(target_arch = "wasm32"))]
795#[async_trait]
796impl UserStore for MemoryUserStore {
797 async fn create_user(&self, user: User) -> Result<()> {
798 self.users.write().await.insert(user.id, user);
799 Ok(())
800 }
801
802 async fn get_user(&self, user_id: UserId) -> Result<Option<User>> {
803 Ok(self.users.read().await.get(&user_id).cloned())
804 }
805
806 async fn get_user_by_username(&self, username: &str) -> Result<Option<User>> {
807 Ok(self
808 .users
809 .read()
810 .await
811 .values()
812 .find(|u| u.username == username)
813 .cloned())
814 }
815
816 async fn get_user_by_email(&self, email: &str) -> Result<Option<User>> {
817 Ok(self
818 .users
819 .read()
820 .await
821 .values()
822 .find(|u| u.email == email)
823 .cloned())
824 }
825
826 async fn update_user(&self, user: User) -> Result<()> {
827 self.users.write().await.insert(user.id, user);
828 Ok(())
829 }
830
831 async fn delete_user(&self, user_id: UserId) -> Result<()> {
832 self.users.write().await.remove(&user_id);
833 Ok(())
834 }
835
836 async fn list_users(&self, limit: Option<u32>, offset: Option<u32>) -> Result<Vec<User>> {
837 let users: Vec<User> = self.users.read().await.values().cloned().collect();
838
839 let offset = offset.unwrap_or(0) as usize;
840 let limit = limit.map(|l| l as usize);
841
842 let mut result: Vec<User> = users.into_iter().skip(offset).collect();
843
844 if let Some(limit) = limit {
845 result.truncate(limit);
846 }
847
848 Ok(result)
849 }
850}
851
852#[cfg(target_arch = "wasm32")]
853#[async_trait(?Send)]
854impl UserStore for MemoryUserStore {
855 async fn create_user(&self, user: User) -> Result<()> {
856 self.users.write().await.insert(user.id, user);
857 Ok(())
858 }
859
860 async fn get_user(&self, user_id: UserId) -> Result<Option<User>> {
861 Ok(self.users.read().await.get(&user_id).cloned())
862 }
863
864 async fn get_user_by_username(&self, username: &str) -> Result<Option<User>> {
865 Ok(self
866 .users
867 .read()
868 .await
869 .values()
870 .find(|u| u.username == username)
871 .cloned())
872 }
873
874 async fn get_user_by_email(&self, email: &str) -> Result<Option<User>> {
875 Ok(self
876 .users
877 .read()
878 .await
879 .values()
880 .find(|u| u.email == email)
881 .cloned())
882 }
883
884 async fn update_user(&self, user: User) -> Result<()> {
885 self.users.write().await.insert(user.id, user);
886 Ok(())
887 }
888
889 async fn delete_user(&self, user_id: UserId) -> Result<()> {
890 self.users.write().await.remove(&user_id);
891 Ok(())
892 }
893
894 async fn list_users(&self, limit: Option<u32>, offset: Option<u32>) -> Result<Vec<User>> {
895 let users: Vec<User> = self.users.read().await.values().cloned().collect();
896
897 let offset = offset.unwrap_or(0) as usize;
898 let limit = limit.map(|l| l as usize);
899
900 let mut result: Vec<User> = users.into_iter().skip(offset).collect();
901
902 if let Some(limit) = limit {
903 result.truncate(limit);
904 }
905
906 Ok(result)
907 }
908}
909
910#[cfg(test)]
911mod tests {
912 use super::*;
913
914 #[tokio::test]
915 async fn test_user_creation() {
916 let user_store = Box::new(MemoryUserStore::new());
917 let session_store = Box::new(MemorySessionStore::new());
918 let security_policy = SecurityPolicy::default();
919
920 let mut account_manager = AccountManager::new(session_store, user_store, security_policy);
921 account_manager.initialize().await.unwrap();
922
923 let user = User {
924 id: Uuid::new_v4(),
925 username: "testuser".to_string(),
926 email: "test@example.com".to_string(),
927 roles: vec![],
928 permissions: vec![],
929 preferences: UserPreferences::default(),
930 profile: UserProfile {
931 display_name: "Test User".to_string(),
932 avatar_url: None,
933 bio: None,
934 department: None,
935 title: None,
936 contact_info: ContactInfo {
937 phone: None,
938 address: None,
939 emergency_contact: None,
940 },
941 },
942 created_at: Time::now(),
943 last_login: None,
944 is_active: true,
945 };
946
947 account_manager.create_user(user.clone()).await.unwrap();
948
949 let retrieved_user = account_manager
950 .get_user_by_username("testuser")
951 .await
952 .unwrap();
953 assert!(retrieved_user.is_some());
954 assert_eq!(retrieved_user.unwrap().username, "testuser");
955 }
956
957 #[tokio::test]
958 async fn test_permission_checking() {
959 let user_store = Box::new(MemoryUserStore::new());
960 let session_store = Box::new(MemorySessionStore::new());
961 let security_policy = SecurityPolicy::default();
962
963 let account_manager = AccountManager::new(session_store, user_store, security_policy);
964
965 let permission = Permission {
966 resource: "user.profile".to_string(),
967 action: "read".to_string(),
968 scope: PermissionScope::Own,
969 };
970
971 let user = User {
972 id: Uuid::new_v4(),
973 username: "testuser".to_string(),
974 email: "test@example.com".to_string(),
975 roles: vec![],
976 permissions: vec![permission],
977 preferences: UserPreferences::default(),
978 profile: UserProfile {
979 display_name: "Test User".to_string(),
980 avatar_url: None,
981 bio: None,
982 department: None,
983 title: None,
984 contact_info: ContactInfo {
985 phone: None,
986 address: None,
987 emergency_contact: None,
988 },
989 },
990 created_at: Time::now(),
991 last_login: None,
992 is_active: true,
993 };
994
995 account_manager.create_user(user.clone()).await.unwrap();
996
997 let has_permission = account_manager
998 .check_permission(user.id, "user.profile", "read")
999 .await
1000 .unwrap();
1001 assert!(has_permission);
1002
1003 let no_permission = account_manager
1004 .check_permission(user.id, "admin.users", "write")
1005 .await
1006 .unwrap();
1007 assert!(!no_permission);
1008 }
1009}