1use std::{
87 collections::HashMap,
88 sync::Arc,
89 time::{Duration, SystemTime},
90};
91
92use tokio::sync::RwLock;
93use log::{debug, error, warn};
94use serde::{Deserialize, Serialize};
95
96use super::super::{
97 Audit::LogEvent::SecurityEventType,
98 Role::ManageRole::{Permission, Role},
99};
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct SecurityContext {
104 pub UserId:String,
106
107 pub Roles:Vec<String>,
109
110 pub Permissions:Vec<String>,
112
113 pub IpAddress:String,
115
116 pub Timestamp:SystemTime,
118}
119
120pub struct PermissionValidator {
122 Roles:Arc<RwLock<HashMap<String, Role>>>,
124
125 Permissions:Arc<RwLock<HashMap<String, Permission>>>,
127
128 OperationPermissions:HashMap<String, Vec<String>>,
130
131 ValidationTimeoutMillis:u64,
133}
134
135impl PermissionValidator {
136 pub fn New(ValidationTimeoutMillis:u64) -> Self {
145 let OperationPermissions = Self::BuildOperationMapping();
146
147 Self {
148 Roles:Arc::new(RwLock::new(HashMap::new())),
149 Permissions:Arc::new(RwLock::new(HashMap::new())),
150 OperationPermissions,
151 ValidationTimeoutMillis,
152 }
153 }
154
155 fn BuildOperationMapping() -> HashMap<String, Vec<String>> {
160 let mut mapping = HashMap::new();
161
162 mapping.insert("file:write".to_string(), vec!["file.write".to_string()]);
163 mapping.insert("file:delete".to_string(), vec!["file.write".to_string()]);
164 mapping.insert("file:read".to_string(), vec!["file.read".to_string()]);
165 mapping.insert("configuration:update".to_string(), vec!["config.update".to_string()]);
166 mapping.insert("configuration:read".to_string(), vec!["config.read".to_string()]);
167 mapping.insert("storage:set".to_string(), vec!["storage.write".to_string()]);
168 mapping.insert("storage:get".to_string(), vec!["storage.read".to_string()]);
169 mapping.insert("native:openExternal".to_string(), vec!["system.external".to_string()]);
170 mapping.insert("system:execute".to_string(), vec!["system.execute".to_string()]);
171 mapping.insert("admin:manage".to_string(), vec!["admin.manage".to_string()]);
172
173 mapping
174 }
175
176 pub fn CreateSecurityContext(
187 UserId:String,
188 Roles:Vec<String>,
189 IpAddress:String,
190 DirectPermissions:Vec<String>,
191 ) -> SecurityContext {
192 let ValidRoles = if Roles.is_empty() { vec!["user".to_string()] } else { Roles };
193
194 let ValidIpAddress = if IpAddress.is_empty() { "127.0.0.1".to_string() } else { IpAddress };
195
196 SecurityContext {
197 UserId,
198 Roles:ValidRoles,
199 Permissions:DirectPermissions,
200 IpAddress:ValidIpAddress,
201 Timestamp:SystemTime::now(),
202 }
203 }
204
205 pub async fn ValidatePermission(&self, Operation:&str, Context:&SecurityContext) -> Result<(), String> {
220 let timeout_duration = Duration::from_millis(self.ValidationTimeoutMillis);
222
223 let result = tokio::time::timeout(timeout_duration, async {
225 self.ValidatePermissionInternal(Operation, Context).await
226 })
227 .await;
228
229 match result {
230 Ok(validation_result) => validation_result,
231 Err(_) => {
232 error!(
233 "[PermissionValidator] Permission validation timed out for operation: {}",
234 Operation
235 );
236 Err("Permission validation timeout".to_string())
237 },
238 }
239 }
240
241 async fn ValidatePermissionInternal(&self, Operation:&str, Context:&SecurityContext) -> Result<(), String> {
250 if Operation.is_empty() {
252 warn!("[PermissionValidator] Empty operation name provided");
253 return Err("Operation name cannot be empty".to_string());
254 }
255
256 if Context.UserId.is_empty() {
257 warn!("[PermissionValidator] Empty user ID in security context");
258 return Err("User ID cannot be empty".to_string());
259 }
260
261 if Context.Roles.is_empty() && Context.Permissions.is_empty() {
262 warn!("[PermissionValidator] User has no roles or permissions: {}", Context.UserId);
263 return Err("User has no assigned roles or permissions".to_string());
264 }
265
266 let RequiredPermissions = match self.OperationPermissions.get(Operation) {
268 Some(perms) => perms.clone(),
269 None => {
270 debug!(
272 "[PermissionValidator] No specific permissions required for operation: {}",
273 Operation
274 );
275 return Ok(());
276 },
277 };
278
279 if RequiredPermissions.is_empty() {
280 debug!(
282 "[PermissionValidator] Access granted (no permissions required): {} by {}",
283 Operation, Context.UserId
284 );
285 Ok(())
286 } else {
287 let UserPermissions = self.AggregateUserPermissions(Context).await?;
289
290 for RequiredPermission in &RequiredPermissions {
292 if !UserPermissions.contains(RequiredPermission) {
293 warn!(
294 "[PermissionValidator] Permission denied: {} required, user {} has {:?}",
295 RequiredPermission, Context.UserId, UserPermissions
296 );
297 return Err(format!("Missing required permission: {}", RequiredPermission));
298 }
299 }
300
301 debug!("[PermissionValidator] Access granted: {} by {}", Operation, Context.UserId);
303 Ok(())
304 }
305 }
306
307 async fn AggregateUserPermissions(&self, Context:&SecurityContext) -> Result<Vec<String>, String> {
315 let mut UserPermissions:Vec<String> = Context.Permissions.clone();
316
317 let roles_read = self.Roles.read().await;
319 for RoleName in &Context.Roles {
320 if let Some(role) = roles_read.get(RoleName) {
321 for Permission in &role.Permissions {
322 if !UserPermissions.contains(Permission) {
323 UserPermissions.push(Permission.clone());
324 }
325 }
326 } else {
327 debug!("[PermissionValidator] Role not found: {}, skipping", RoleName);
328 }
329 }
330
331 Ok(UserPermissions)
332 }
333
334 pub async fn RegisterRole(&self, Role:Role) -> Result<(), String> {
342 if Role.Name.is_empty() {
344 return Err("Role name cannot be empty".to_string());
345 }
346
347 if Role.Permissions.is_empty() {
348 warn!("[PermissionValidator] Role '{}' has no permissions", Role.Name);
349 }
350
351 let mut roles = self.Roles.write().await;
352
353 let permissions_read = self.Permissions.read().await;
355 for PermissionName in &Role.Permissions {
356 if !permissions_read.contains_key(PermissionName) {
357 warn!(
358 "[PermissionValidator] Permission '{}' referenced by role '{}' does not exist",
359 PermissionName, Role.Name
360 );
361 }
362 }
363 drop(permissions_read);
364
365 let RoleName = Role.Name.clone();
366 roles.insert(RoleName.clone(), Role);
367 debug!("[PermissionValidator] Role registered: {}", RoleName);
368 Ok(())
369 }
370
371 pub async fn RegisterPermission(&self, Permission:Permission) -> Result<(), String> {
379 if Permission.Name.is_empty() {
381 return Err("Permission name cannot be empty".to_string());
382 }
383
384 if Permission.Description.is_empty() {
385 return Err("Permission description cannot be empty".to_string());
386 }
387
388 let mut permissions = self.Permissions.write().await;
389 let PermissionName = Permission.Name.clone();
390 permissions.insert(PermissionName.clone(), Permission);
391 debug!("[PermissionValidator] Permission registered: {}", PermissionName);
392 Ok(())
393 }
394
395 pub async fn GetRolePermissions(&self, RoleName:&str) -> Vec<String> {
403 let roles = self.Roles.read().await;
404 roles.get(RoleName).map(|role| role.Permissions.clone()).unwrap_or_default()
405 }
406
407 pub async fn HasPermission(&self, Context:&SecurityContext, PermissionName:&str) -> bool {
416 if Context.Permissions.contains(&PermissionName.to_string()) {
418 return true;
419 }
420
421 let roles = self.Roles.read().await;
423 for RoleName in &Context.Roles {
424 if let Some(role) = roles.get(RoleName) {
425 if role.Permissions.contains(&PermissionName.to_string()) {
426 return true;
427 }
428 }
429 }
430
431 false
432 }
433
434 pub async fn InitializeDefaults(&self) -> Result<(), String> {
444 debug!("[PermissionValidator] Initializing default roles and permissions");
445
446 let DefaultPermissions = vec![
448 Permission {
449 Name:"file.read".to_string(),
450 Description:"Read file operations".to_string(),
451 Category:"file".to_string(),
452 IsSensitive:false,
453 },
454 Permission {
455 Name:"file.write".to_string(),
456 Description:"Write file operations".to_string(),
457 Category:"file".to_string(),
458 IsSensitive:false,
459 },
460 Permission {
461 Name:"config.read".to_string(),
462 Description:"Read configuration".to_string(),
463 Category:"config".to_string(),
464 IsSensitive:false,
465 },
466 Permission {
467 Name:"config.update".to_string(),
468 Description:"Update configuration".to_string(),
469 Category:"config".to_string(),
470 IsSensitive:false,
471 },
472 Permission {
473 Name:"storage.read".to_string(),
474 Description:"Read storage".to_string(),
475 Category:"storage".to_string(),
476 IsSensitive:false,
477 },
478 Permission {
479 Name:"storage.write".to_string(),
480 Description:"Write storage".to_string(),
481 Category:"storage".to_string(),
482 IsSensitive:false,
483 },
484 Permission {
485 Name:"system.external".to_string(),
486 Description:"Access external system resources".to_string(),
487 Category:"system".to_string(),
488 IsSensitive:true,
489 },
490 Permission {
491 Name:"system.execute".to_string(),
492 Description:"Execute system commands".to_string(),
493 Category:"system".to_string(),
494 IsSensitive:true,
495 },
496 Permission {
497 Name:"admin.manage".to_string(),
498 Description:"Administrative management operations".to_string(),
499 Category:"admin".to_string(),
500 IsSensitive:true,
501 },
502 ];
503
504 for Permission in DefaultPermissions {
506 self.RegisterPermission(Permission).await?;
507 }
508
509 let DefaultRoles = vec![
511 Role {
512 Name:"user".to_string(),
513 Permissions:vec!["file.read".to_string(), "config.read".to_string(), "storage.read".to_string()],
514 Description:"Standard user with read access".to_string(),
515 ParentRole:None,
516 Priority:0,
517 },
518 Role {
519 Name:"developer".to_string(),
520 Permissions:vec![
521 "file.read".to_string(),
522 "file.write".to_string(),
523 "config.read".to_string(),
524 "storage.read".to_string(),
525 "storage.write".to_string(),
526 ],
527 Description:"Developer with read/write access".to_string(),
528 ParentRole:None,
529 Priority:1,
530 },
531 Role {
532 Name:"admin".to_string(),
533 Permissions:vec![
534 "file.read".to_string(),
535 "file.write".to_string(),
536 "config.read".to_string(),
537 "config.update".to_string(),
538 "storage.read".to_string(),
539 "storage.write".to_string(),
540 "system.external".to_string(),
541 "system.execute".to_string(),
542 "admin.manage".to_string(),
543 ],
544 Description:"Administrator with full access".to_string(),
545 ParentRole:None,
546 Priority:2,
547 },
548 ];
549
550 for Role in DefaultRoles {
552 self.RegisterRole(Role).await?;
553 }
554
555 debug!("[PermissionValidator] Default roles and permissions initialized successfully");
556 Ok(())
557 }
558}
559
560#[cfg(test)]
561mod Tests {
562 use super::*;
563
564 #[tokio::test]
565 async fn TestCreateSecurityContext() {
566 let context = PermissionValidator::CreateSecurityContext(
567 "test-user".to_string(),
568 vec!["user".to_string(), "admin".to_string()],
569 "192.168.1.1".to_string(),
570 vec!["custom.permission".to_string()],
571 );
572
573 assert_eq!(context.UserId, "test-user".to_string());
574 assert_eq!(context.Roles, vec!["user".to_string(), "admin".to_string()]);
575 assert_eq!(context.IpAddress, "192.168.1.1".to_string());
576 assert_eq!(context.Permissions, vec!["custom.permission".to_string()]);
577 }
578
579 #[tokio::test]
580 async fn TestCreateSecurityContextDefaults() {
581 let context =
582 PermissionValidator::CreateSecurityContext("test-user".to_string(), vec![], "".to_string(), vec![]);
583
584 assert_eq!(context.UserId, "test-user".to_string());
585 assert_eq!(context.Roles, vec!["user".to_string()]);
586 assert_eq!(context.IpAddress, "127.0.0.1".to_string());
587 }
588
589 #[tokio::test]
590 async fn TestValidatePermissionNoPermissionsRequired() {
591 let validator = PermissionValidator::New(1000);
592 let context = SecurityContext {
593 UserId:"test-user".to_string(),
594 Roles:vec!["user".to_string()],
595 Permissions:vec![],
596 IpAddress:"127.0.0.1".to_string(),
597 Timestamp:SystemTime::now(),
598 };
599
600 let result = validator.ValidatePermission("unknown:operation", &context).await;
601 assert!(result.is_ok(), "Should succeed when no permissions are required");
602 }
603
604 #[tokio::test]
605 async fn TestValidatePermissionMissingPermission() {
606 let validator = PermissionValidator::New(1000);
607 let context = SecurityContext {
608 UserId:"test-user".to_string(),
609 Roles:vec!["user".to_string()],
610 Permissions:vec![],
611 IpAddress:"127.0.0.1".to_string(),
612 Timestamp:SystemTime::now(),
613 };
614
615 let result = validator.ValidatePermission("file:write", &context).await;
616 assert!(result.is_err(), "Should fail without required permission");
617 assert!(result.unwrap_err().contains("Missing required permission"));
618 }
619
620 #[tokio::test]
621 async fn TestValidatePermissionWithDirectPermission() {
622 let validator = PermissionValidator::New(1000);
623 let context = SecurityContext {
624 UserId:"test-user".to_string(),
625 Roles:vec![],
626 Permissions:vec!["file.write".to_string()],
627 IpAddress:"127.0.0.1".to_string(),
628 Timestamp:SystemTime::now(),
629 };
630
631 let result = validator.ValidatePermission("file:write", &context).await;
632 assert!(result.is_ok(), "Should succeed with direct permission");
633 }
634
635 #[tokio::test]
636 async fn TestValidatePermissionViaRole() {
637 let validator = PermissionValidator::New(1000);
638 validator.InitializeDefaults().await.unwrap();
639
640 let context = SecurityContext {
641 UserId:"test-user".to_string(),
642 Roles:vec!["admin".to_string()],
643 Permissions:vec![],
644 IpAddress:"127.0.0.1".to_string(),
645 Timestamp:SystemTime::now(),
646 };
647
648 let result = validator.ValidatePermission("file:write", &context).await;
649 assert!(result.is_ok(), "Should succeed via role permission");
650 }
651
652 #[tokio::test]
653 async fn TestValidatePermissionEmptyOperation() {
654 let validator = PermissionValidator::New(1000);
655 let context = SecurityContext {
656 UserId:"test-user".to_string(),
657 Roles:vec!["user".to_string()],
658 Permissions:vec![],
659 IpAddress:"127.0.0.1".to_string(),
660 Timestamp:SystemTime::now(),
661 };
662
663 let result = validator.ValidatePermission("", &context).await;
664 assert!(result.is_err(), "Should fail with empty operation name");
665 }
666
667 #[tokio::test]
668 async fn TestValidatePermissionEmptyUserId() {
669 let validator = PermissionValidator::New(1000);
670 let context = SecurityContext {
671 UserId:"".to_string(),
672 Roles:vec!["user".to_string()],
673 Permissions:vec![],
674 IpAddress:"127.0.0.1".to_string(),
675 Timestamp:SystemTime::now(),
676 };
677
678 let result = validator.ValidatePermission("file:read", &context).await;
679 assert!(result.is_err(), "Should fail with empty user ID");
680 }
681
682 #[tokio::test]
683 async fn TestInitializeDefaults() {
684 let validator = PermissionValidator::New(1000);
685 let result = validator.InitializeDefaults().await;
686 assert!(result.is_ok(), "Should initialize defaults successfully");
687
688 let user_perms = validator.GetRolePermissions("user").await;
690 assert!(user_perms.contains(&"file.read".to_string()));
691
692 let admin_perms = validator.GetRolePermissions("admin").await;
693 assert_ne!(admin_perms.len(), 0, "Admin should have many permissions");
694 }
695
696 #[tokio::test]
697 async fn TestGetRolePermissions() {
698 let validator = PermissionValidator::New(1000);
699 validator.InitializeDefaults().await.unwrap();
700
701 let role_perms = validator.GetRolePermissions("developer").await;
702 assert!(role_perms.contains(&"file.read".to_string()));
703 assert!(role_perms.contains(&"file.write".to_string()));
704 }
705
706 #[tokio::test]
707 async fn TestHasPermissionWithRole() {
708 let validator = PermissionValidator::New(1000);
709 validator.InitializeDefaults().await.unwrap();
710
711 let context = SecurityContext {
712 UserId:"test-user".to_string(),
713 Roles:vec!["admin".to_string()],
714 Permissions:vec![],
715 IpAddress:"127.0.0.1".to_string(),
716 Timestamp:SystemTime::now(),
717 };
718
719 assert!(validator.HasPermission(&context, "file.read").await);
720 assert!(validator.HasPermission(&context, "config.update").await);
721 }
722
723 #[tokio::test]
724 async fn TestHasPermissionDirect() {
725 let validator = PermissionValidator::New(1000);
726
727 let context = SecurityContext {
728 UserId:"test-user".to_string(),
729 Roles:vec![],
730 Permissions:vec!["custom.perm".to_string()],
731 IpAddress:"127.0.0.1".to_string(),
732 Timestamp:SystemTime::now(),
733 };
734
735 assert!(validator.HasPermission(&context, "custom.perm").await);
736 assert!(!validator.HasPermission(&context, "file.read").await);
737 }
738}