1use serde::{Deserialize, Serialize};
7use std::collections::{HashMap, HashSet};
8use std::time::{SystemTime, UNIX_EPOCH};
9use torsh_core::error::{Result, TorshError};
10use uuid::Uuid;
11
12pub type OrganizationId = String;
14
15pub type UserId = String;
17
18pub type RepositoryId = String;
20
21pub type RoleId = String;
23
24pub type PermissionId = String;
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct PrivateRepository {
30 pub id: RepositoryId,
31 pub name: String,
32 pub description: Option<String>,
33 pub organization_id: OrganizationId,
34 pub owner_id: UserId,
35 pub created_at: u64,
36 pub updated_at: u64,
37 pub visibility: RepositoryVisibility,
38 pub access_control: RepositoryAccessControl,
39 pub storage_config: StorageConfig,
40 pub backup_config: BackupConfig,
41 pub compliance_labels: Vec<ComplianceLabel>,
42 pub data_classification: DataClassification,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
47pub enum RepositoryVisibility {
48 Private,
49 Internal, Public,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct RepositoryAccessControl {
56 pub allowed_users: HashSet<UserId>,
57 pub allowed_roles: HashSet<RoleId>,
58 pub collaborators: HashMap<UserId, CollaboratorPermission>,
59 pub ip_whitelist: Vec<String>,
60 pub require_mfa: bool,
61 pub session_timeout_minutes: u32,
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
66pub enum CollaboratorPermission {
67 Read,
68 Write,
69 Admin,
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct StorageConfig {
75 pub encryption_enabled: bool,
76 pub encryption_algorithm: EncryptionAlgorithm,
77 pub compression_enabled: bool,
78 pub retention_policy: RetentionPolicy,
79 pub storage_class: StorageClass,
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
84pub enum EncryptionAlgorithm {
85 AES256,
86 ChaCha20Poly1305,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct RetentionPolicy {
92 pub retention_days: u32,
93 pub auto_delete_enabled: bool,
94 pub legal_hold: bool,
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
99pub enum StorageClass {
100 Hot, Cool, Archive, }
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct BackupConfig {
108 pub enabled: bool,
109 pub frequency: BackupFrequency,
110 pub retention_days: u32,
111 pub cross_region_backup: bool,
112 pub encryption_enabled: bool,
113}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
117pub enum BackupFrequency {
118 Hourly,
119 Daily,
120 Weekly,
121 Monthly,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct Role {
127 pub id: RoleId,
128 pub name: String,
129 pub description: String,
130 pub organization_id: OrganizationId,
131 pub permissions: HashSet<PermissionId>,
132 pub created_at: u64,
133 pub updated_at: u64,
134 pub is_system_role: bool,
135 pub inheritance: Vec<RoleId>, }
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct Permission {
141 pub id: PermissionId,
142 pub name: String,
143 pub description: String,
144 pub resource_type: ResourceType,
145 pub action: Action,
146 pub scope: PermissionScope,
147}
148
149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
151pub enum ResourceType {
152 Repository,
153 Model,
154 Organization,
155 User,
156 Role,
157 AuditLog,
158 Billing,
159 Analytics,
160}
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
164pub enum Action {
165 Create,
166 Read,
167 Update,
168 Delete,
169 List,
170 Execute,
171 Download,
172 Upload,
173 Share,
174 Manage,
175}
176
177#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
179pub enum PermissionScope {
180 Global,
181 Organization(OrganizationId),
182 Repository(RepositoryId),
183 User(UserId),
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct UserRoleAssignment {
189 pub user_id: UserId,
190 pub role_id: RoleId,
191 pub organization_id: OrganizationId,
192 pub assigned_at: u64,
193 pub assigned_by: UserId,
194 pub expires_at: Option<u64>,
195 pub conditions: Vec<AssignmentCondition>,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
200pub enum AssignmentCondition {
201 IpRange(String),
202 TimeRange { start_hour: u8, end_hour: u8 },
203 MfaRequired,
204 DeviceRegistered,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct AuditLogEntry {
210 pub id: String,
211 pub timestamp: u64,
212 pub user_id: Option<UserId>,
213 pub organization_id: OrganizationId,
214 pub action: AuditAction,
215 pub resource_type: ResourceType,
216 pub resource_id: String,
217 pub details: AuditDetails,
218 pub ip_address: Option<String>,
219 pub user_agent: Option<String>,
220 pub session_id: Option<String>,
221 pub risk_score: RiskScore,
222 pub compliance_tags: Vec<String>,
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
227pub enum AuditAction {
228 Login,
229 Logout,
230 CreateResource,
231 UpdateResource,
232 DeleteResource,
233 AccessResource,
234 DownloadModel,
235 UploadModel,
236 ShareModel,
237 ChangePermissions,
238 CreateUser,
239 DeleteUser,
240 AssignRole,
241 RevokeRole,
242 ConfigurationChange,
243 SecurityEvent,
244 ComplianceEvent,
245}
246
247#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct AuditDetails {
250 pub description: String,
251 pub old_values: Option<HashMap<String, String>>,
252 pub new_values: Option<HashMap<String, String>>,
253 pub additional_data: HashMap<String, String>,
254}
255
256#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
258pub enum RiskScore {
259 Low = 1,
260 Medium = 2,
261 High = 3,
262 Critical = 4,
263}
264
265#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
267pub enum ComplianceLabel {
268 GDPR,
269 HIPAA,
270 SOX,
271 PciDss,
272 ISO27001,
273 FedRAMP,
274 SOC2,
275}
276
277#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
279pub enum DataClassification {
280 Public,
281 Internal,
282 Confidential,
283 Restricted,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
288pub struct ComplianceReport {
289 pub id: String,
290 pub organization_id: OrganizationId,
291 pub framework: ComplianceLabel,
292 pub generated_at: u64,
293 pub period_start: u64,
294 pub period_end: u64,
295 pub compliance_score: f64,
296 pub findings: Vec<ComplianceFinding>,
297 pub recommendations: Vec<String>,
298 pub status: ComplianceStatus,
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize)]
303pub struct ComplianceFinding {
304 pub control_id: String,
305 pub description: String,
306 pub severity: Severity,
307 pub status: FindingStatus,
308 pub remediation: String,
309 pub evidence: Vec<String>,
310}
311
312#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
314pub enum Severity {
315 Low,
316 Medium,
317 High,
318 Critical,
319}
320
321#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
323pub enum FindingStatus {
324 Open,
325 InProgress,
326 Resolved,
327 Accepted, }
329
330#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
332pub enum ComplianceStatus {
333 Compliant,
334 NonCompliant,
335 PartiallyCompliant,
336 UnderReview,
337}
338
339#[derive(Debug, Clone, Serialize, Deserialize)]
341pub struct ServiceLevelAgreement {
342 pub id: String,
343 pub name: String,
344 pub organization_id: OrganizationId,
345 pub tier: ServiceTier,
346 pub metrics: Vec<SlaMetric>,
347 pub penalties: Vec<SlaPenalty>,
348 pub effective_date: u64,
349 pub expiration_date: Option<u64>,
350 pub auto_renewal: bool,
351}
352
353#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
355pub enum ServiceTier {
356 Basic,
357 Professional,
358 Enterprise,
359 Premium,
360}
361
362#[derive(Debug, Clone, Serialize, Deserialize)]
364pub struct SlaMetric {
365 pub name: String,
366 pub description: String,
367 pub target_value: f64,
368 pub threshold_value: f64,
369 pub unit: String,
370 pub measurement_period: MeasurementPeriod,
371}
372
373#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
375pub enum MeasurementPeriod {
376 Hourly,
377 Daily,
378 Weekly,
379 Monthly,
380 Quarterly,
381 Annually,
382}
383
384#[derive(Debug, Clone, Serialize, Deserialize)]
386pub struct SlaPenalty {
387 pub metric_name: String,
388 pub threshold_breach: f64,
389 pub penalty_type: PenaltyType,
390 pub penalty_amount: f64,
391 pub max_penalty_per_period: Option<f64>,
392}
393
394#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
396pub enum PenaltyType {
397 ServiceCredit,
398 Discount,
399 Refund,
400}
401
402#[derive(Debug, Clone, Serialize, Deserialize)]
404pub struct SlaPerformanceReport {
405 pub id: String,
406 pub sla_id: String,
407 pub organization_id: OrganizationId,
408 pub period_start: u64,
409 pub period_end: u64,
410 pub metric_results: Vec<MetricResult>,
411 pub overall_compliance: f64,
412 pub penalties_applied: Vec<AppliedPenalty>,
413 pub credits_earned: f64,
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize)]
418pub struct MetricResult {
419 pub metric_name: String,
420 pub actual_value: f64,
421 pub target_value: f64,
422 pub achievement_percentage: f64,
423 pub compliant: bool,
424 pub measurements: Vec<MetricMeasurement>,
425}
426
427#[derive(Debug, Clone, Serialize, Deserialize)]
429pub struct MetricMeasurement {
430 pub timestamp: u64,
431 pub value: f64,
432 pub context: HashMap<String, String>,
433}
434
435#[derive(Debug, Clone, Serialize, Deserialize)]
437pub struct AppliedPenalty {
438 pub metric_name: String,
439 pub penalty_type: PenaltyType,
440 pub amount: f64,
441 pub period: String,
442 pub justification: String,
443}
444
445pub struct EnterpriseManager {
447 repositories: HashMap<RepositoryId, PrivateRepository>,
448 roles: HashMap<RoleId, Role>,
449 permissions: HashMap<PermissionId, Permission>,
450 user_roles: HashMap<UserId, Vec<UserRoleAssignment>>,
451 audit_logs: Vec<AuditLogEntry>,
452 compliance_reports: HashMap<String, ComplianceReport>,
453 slas: HashMap<String, ServiceLevelAgreement>,
454 sla_reports: HashMap<String, SlaPerformanceReport>,
455}
456
457impl EnterpriseManager {
458 pub fn new() -> Self {
460 let mut manager = Self {
461 repositories: HashMap::new(),
462 roles: HashMap::new(),
463 permissions: HashMap::new(),
464 user_roles: HashMap::new(),
465 audit_logs: Vec::new(),
466 compliance_reports: HashMap::new(),
467 slas: HashMap::new(),
468 sla_reports: HashMap::new(),
469 };
470
471 manager.initialize_default_permissions();
472 manager.initialize_default_roles();
473
474 manager
475 }
476
477 pub fn create_private_repository(
479 &mut self,
480 mut repo: PrivateRepository,
481 ) -> Result<RepositoryId> {
482 if repo.name.trim().is_empty() {
483 return Err(TorshError::InvalidArgument(
484 "Repository name cannot be empty".to_string(),
485 ));
486 }
487
488 repo.id = Uuid::new_v4().to_string();
489 repo.created_at = current_timestamp();
490 repo.updated_at = repo.created_at;
491
492 let repo_id = repo.id.clone();
493 self.repositories.insert(repo_id.clone(), repo);
494
495 self.log_audit_event(AuditLogEntry {
496 id: Uuid::new_v4().to_string(),
497 timestamp: current_timestamp(),
498 user_id: Some(self.repositories[&repo_id].owner_id.clone()),
499 organization_id: self.repositories[&repo_id].organization_id.clone(),
500 action: AuditAction::CreateResource,
501 resource_type: ResourceType::Repository,
502 resource_id: repo_id.clone(),
503 details: AuditDetails {
504 description: "Private repository created".to_string(),
505 old_values: None,
506 new_values: Some(
507 [
508 ("name".to_string(), self.repositories[&repo_id].name.clone()),
509 (
510 "visibility".to_string(),
511 format!("{:?}", self.repositories[&repo_id].visibility),
512 ),
513 ]
514 .iter()
515 .cloned()
516 .collect(),
517 ),
518 additional_data: HashMap::new(),
519 },
520 ip_address: None,
521 user_agent: None,
522 session_id: None,
523 risk_score: RiskScore::Low,
524 compliance_tags: vec!["repository_creation".to_string()],
525 });
526
527 Ok(repo_id)
528 }
529
530 pub fn check_repository_access(&self, repo_id: &str, user_id: &str) -> Result<bool> {
532 let repo = self
533 .repositories
534 .get(repo_id)
535 .ok_or_else(|| TorshError::InvalidArgument("Repository not found".to_string()))?;
536
537 if repo.owner_id == user_id {
539 return Ok(true);
540 }
541
542 if repo.access_control.allowed_users.contains(user_id) {
544 return Ok(true);
545 }
546
547 if let Some(user_roles) = self.user_roles.get(user_id) {
549 for assignment in user_roles {
550 if repo
551 .access_control
552 .allowed_roles
553 .contains(&assignment.role_id)
554 {
555 if let Some(expires_at) = assignment.expires_at {
557 if expires_at < current_timestamp() {
558 continue;
559 }
560 }
561
562 if self.check_assignment_conditions(&assignment.conditions) {
564 return Ok(true);
565 }
566 }
567 }
568 }
569
570 Ok(false)
571 }
572
573 pub fn create_role(&mut self, mut role: Role) -> Result<RoleId> {
575 if role.name.trim().is_empty() {
576 return Err(TorshError::InvalidArgument(
577 "Role name cannot be empty".to_string(),
578 ));
579 }
580
581 role.id = Uuid::new_v4().to_string();
582 role.created_at = current_timestamp();
583 role.updated_at = role.created_at;
584
585 let role_id = role.id.clone();
586 self.roles.insert(role_id.clone(), role);
587
588 self.log_audit_event(AuditLogEntry {
589 id: Uuid::new_v4().to_string(),
590 timestamp: current_timestamp(),
591 user_id: None, organization_id: self.roles[&role_id].organization_id.clone(),
593 action: AuditAction::CreateResource,
594 resource_type: ResourceType::Role,
595 resource_id: role_id.clone(),
596 details: AuditDetails {
597 description: "Role created".to_string(),
598 old_values: None,
599 new_values: Some(
600 [
601 ("name".to_string(), self.roles[&role_id].name.clone()),
602 (
603 "permissions_count".to_string(),
604 self.roles[&role_id].permissions.len().to_string(),
605 ),
606 ]
607 .iter()
608 .cloned()
609 .collect(),
610 ),
611 additional_data: HashMap::new(),
612 },
613 ip_address: None,
614 user_agent: None,
615 session_id: None,
616 risk_score: RiskScore::Medium,
617 compliance_tags: vec!["rbac".to_string()],
618 });
619
620 Ok(role_id)
621 }
622
623 pub fn assign_role(&mut self, assignment: UserRoleAssignment) -> Result<()> {
625 if !self.roles.contains_key(&assignment.role_id) {
627 return Err(TorshError::InvalidArgument("Role not found".to_string()));
628 }
629
630 let user_roles = self
631 .user_roles
632 .entry(assignment.user_id.clone())
633 .or_default();
634
635 user_roles.retain(|a| a.role_id != assignment.role_id);
637
638 user_roles.push(assignment.clone());
639
640 self.log_audit_event(AuditLogEntry {
641 id: Uuid::new_v4().to_string(),
642 timestamp: current_timestamp(),
643 user_id: Some(assignment.assigned_by.clone()),
644 organization_id: assignment.organization_id.clone(),
645 action: AuditAction::AssignRole,
646 resource_type: ResourceType::User,
647 resource_id: assignment.user_id.clone(),
648 details: AuditDetails {
649 description: "Role assigned to user".to_string(),
650 old_values: None,
651 new_values: Some(
652 [
653 ("role_id".to_string(), assignment.role_id.clone()),
654 ("assigned_by".to_string(), assignment.assigned_by.clone()),
655 ]
656 .iter()
657 .cloned()
658 .collect(),
659 ),
660 additional_data: HashMap::new(),
661 },
662 ip_address: None,
663 user_agent: None,
664 session_id: None,
665 risk_score: RiskScore::Medium,
666 compliance_tags: vec!["rbac".to_string()],
667 });
668
669 Ok(())
670 }
671
672 pub fn check_permission(
674 &self,
675 user_id: &str,
676 permission_id: &str,
677 resource_id: Option<&str>,
678 ) -> bool {
679 if let Some(user_roles) = self.user_roles.get(user_id) {
680 for assignment in user_roles {
681 if let Some(expires_at) = assignment.expires_at {
683 if expires_at < current_timestamp() {
684 continue;
685 }
686 }
687
688 if !self.check_assignment_conditions(&assignment.conditions) {
690 continue;
691 }
692
693 if let Some(role) = self.roles.get(&assignment.role_id) {
695 if role.permissions.contains(permission_id) {
696 if let (Some(resource_id), Some(permission)) =
698 (resource_id, self.permissions.get(permission_id))
699 {
700 match &permission.scope {
701 PermissionScope::Global => return true,
702 PermissionScope::Organization(org_id) => {
703 if org_id == &assignment.organization_id {
704 return true;
705 }
706 }
707 PermissionScope::Repository(repo_id) => {
708 if repo_id == resource_id {
709 return true;
710 }
711 }
712 PermissionScope::User(target_user_id) => {
713 if target_user_id == resource_id {
714 return true;
715 }
716 }
717 }
718 } else {
719 return true;
720 }
721 }
722
723 for inherited_role_id in &role.inheritance {
725 if let Some(inherited_role) = self.roles.get(inherited_role_id) {
726 if inherited_role.permissions.contains(permission_id) {
727 return true;
728 }
729 }
730 }
731 }
732 }
733 }
734
735 false
736 }
737
738 pub fn log_audit_event(&mut self, audit_entry: AuditLogEntry) {
740 self.audit_logs.push(audit_entry);
741 }
742
743 pub fn generate_compliance_report(
745 &mut self,
746 org_id: &str,
747 framework: ComplianceLabel,
748 period_start: u64,
749 period_end: u64,
750 ) -> Result<String> {
751 let report_id = Uuid::new_v4().to_string();
752
753 let findings = self.assess_compliance(org_id, framework, period_start, period_end)?;
754 let compliance_score = self.calculate_compliance_score(&findings);
755 let status = if compliance_score >= 0.9 {
756 ComplianceStatus::Compliant
757 } else if compliance_score >= 0.7 {
758 ComplianceStatus::PartiallyCompliant
759 } else {
760 ComplianceStatus::NonCompliant
761 };
762
763 let report = ComplianceReport {
764 id: report_id.clone(),
765 organization_id: org_id.to_string(),
766 framework,
767 generated_at: current_timestamp(),
768 period_start,
769 period_end,
770 compliance_score,
771 findings,
772 recommendations: self.generate_compliance_recommendations(framework),
773 status,
774 };
775
776 self.compliance_reports.insert(report_id.clone(), report);
777
778 self.log_audit_event(AuditLogEntry {
779 id: Uuid::new_v4().to_string(),
780 timestamp: current_timestamp(),
781 user_id: None,
782 organization_id: org_id.to_string(),
783 action: AuditAction::ComplianceEvent,
784 resource_type: ResourceType::Organization,
785 resource_id: org_id.to_string(),
786 details: AuditDetails {
787 description: "Compliance report generated".to_string(),
788 old_values: None,
789 new_values: Some(
790 [
791 ("framework".to_string(), format!("{:?}", framework)),
792 ("compliance_score".to_string(), compliance_score.to_string()),
793 ]
794 .iter()
795 .cloned()
796 .collect(),
797 ),
798 additional_data: HashMap::new(),
799 },
800 ip_address: None,
801 user_agent: None,
802 session_id: None,
803 risk_score: RiskScore::Low,
804 compliance_tags: vec!["compliance_report".to_string()],
805 });
806
807 Ok(report_id)
808 }
809
810 pub fn create_sla(&mut self, mut sla: ServiceLevelAgreement) -> Result<String> {
812 sla.id = Uuid::new_v4().to_string();
813
814 let sla_id = sla.id.clone();
815 self.slas.insert(sla_id.clone(), sla);
816
817 Ok(sla_id)
818 }
819
820 pub fn generate_sla_report(
822 &mut self,
823 sla_id: &str,
824 period_start: u64,
825 period_end: u64,
826 ) -> Result<String> {
827 let sla = self
828 .slas
829 .get(sla_id)
830 .ok_or_else(|| TorshError::InvalidArgument("SLA not found".to_string()))?;
831
832 let report_id = Uuid::new_v4().to_string();
833
834 let metric_results = sla
836 .metrics
837 .iter()
838 .map(|metric| {
839 MetricResult {
840 metric_name: metric.name.clone(),
841 actual_value: metric.target_value * 0.95, target_value: metric.target_value,
843 achievement_percentage: 95.0,
844 compliant: true,
845 measurements: vec![],
846 }
847 })
848 .collect();
849
850 let overall_compliance = 95.0;
851
852 let report = SlaPerformanceReport {
853 id: report_id.clone(),
854 sla_id: sla_id.to_string(),
855 organization_id: sla.organization_id.clone(),
856 period_start,
857 period_end,
858 metric_results,
859 overall_compliance,
860 penalties_applied: vec![],
861 credits_earned: 0.0,
862 };
863
864 self.sla_reports.insert(report_id.clone(), report);
865 Ok(report_id)
866 }
867
868 pub fn get_audit_logs(
870 &self,
871 org_id: &str,
872 start_time: Option<u64>,
873 end_time: Option<u64>,
874 ) -> Vec<&AuditLogEntry> {
875 self.audit_logs
876 .iter()
877 .filter(|log| {
878 log.organization_id == org_id
879 && start_time.map_or(true, |start| log.timestamp >= start)
880 && end_time.map_or(true, |end| log.timestamp <= end)
881 })
882 .collect()
883 }
884
885 fn initialize_default_permissions(&mut self) {
886 let permissions = vec![
887 Permission {
888 id: "repo.read".to_string(),
889 name: "Read Repository".to_string(),
890 description: "Read access to repository".to_string(),
891 resource_type: ResourceType::Repository,
892 action: Action::Read,
893 scope: PermissionScope::Global,
894 },
895 Permission {
896 id: "repo.write".to_string(),
897 name: "Write Repository".to_string(),
898 description: "Write access to repository".to_string(),
899 resource_type: ResourceType::Repository,
900 action: Action::Update,
901 scope: PermissionScope::Global,
902 },
903 Permission {
904 id: "repo.admin".to_string(),
905 name: "Admin Repository".to_string(),
906 description: "Admin access to repository".to_string(),
907 resource_type: ResourceType::Repository,
908 action: Action::Manage,
909 scope: PermissionScope::Global,
910 },
911 ];
912
913 for permission in permissions {
914 self.permissions.insert(permission.id.clone(), permission);
915 }
916 }
917
918 fn initialize_default_roles(&mut self) {
919 let roles = vec![
920 Role {
921 id: "viewer".to_string(),
922 name: "Viewer".to_string(),
923 description: "Can view repositories".to_string(),
924 organization_id: "system".to_string(),
925 permissions: ["repo.read"].iter().map(|s| s.to_string()).collect(),
926 created_at: current_timestamp(),
927 updated_at: current_timestamp(),
928 is_system_role: true,
929 inheritance: vec![],
930 },
931 Role {
932 id: "contributor".to_string(),
933 name: "Contributor".to_string(),
934 description: "Can read and write repositories".to_string(),
935 organization_id: "system".to_string(),
936 permissions: ["repo.read", "repo.write"]
937 .iter()
938 .map(|s| s.to_string())
939 .collect(),
940 created_at: current_timestamp(),
941 updated_at: current_timestamp(),
942 is_system_role: true,
943 inheritance: vec!["viewer".to_string()],
944 },
945 Role {
946 id: "admin".to_string(),
947 name: "Administrator".to_string(),
948 description: "Full access to repositories".to_string(),
949 organization_id: "system".to_string(),
950 permissions: ["repo.read", "repo.write", "repo.admin"]
951 .iter()
952 .map(|s| s.to_string())
953 .collect(),
954 created_at: current_timestamp(),
955 updated_at: current_timestamp(),
956 is_system_role: true,
957 inheritance: vec!["contributor".to_string()],
958 },
959 ];
960
961 for role in roles {
962 self.roles.insert(role.id.clone(), role);
963 }
964 }
965
966 fn check_assignment_conditions(&self, _conditions: &[AssignmentCondition]) -> bool {
967 true
969 }
970
971 fn assess_compliance(
972 &self,
973 _org_id: &str,
974 framework: ComplianceLabel,
975 _period_start: u64,
976 _period_end: u64,
977 ) -> Result<Vec<ComplianceFinding>> {
978 match framework {
980 ComplianceLabel::GDPR => Ok(vec![ComplianceFinding {
981 control_id: "GDPR.32".to_string(),
982 description: "Data encryption in transit and at rest".to_string(),
983 severity: Severity::High,
984 status: FindingStatus::Resolved,
985 remediation: "Encryption is properly implemented".to_string(),
986 evidence: vec![
987 "TLS 1.3 enabled".to_string(),
988 "AES-256 encryption".to_string(),
989 ],
990 }]),
991 ComplianceLabel::SOC2 => Ok(vec![ComplianceFinding {
992 control_id: "CC6.1".to_string(),
993 description: "Logical and physical access controls".to_string(),
994 severity: Severity::Medium,
995 status: FindingStatus::Resolved,
996 remediation: "Access controls are properly configured".to_string(),
997 evidence: vec!["RBAC implemented".to_string(), "MFA enforced".to_string()],
998 }]),
999 _ => Ok(vec![]),
1000 }
1001 }
1002
1003 fn calculate_compliance_score(&self, findings: &[ComplianceFinding]) -> f64 {
1004 if findings.is_empty() {
1005 return 1.0;
1006 }
1007
1008 let total_findings = findings.len() as f64;
1009 let resolved_findings = findings
1010 .iter()
1011 .filter(|f| f.status == FindingStatus::Resolved)
1012 .count() as f64;
1013
1014 resolved_findings / total_findings
1015 }
1016
1017 fn generate_compliance_recommendations(&self, framework: ComplianceLabel) -> Vec<String> {
1018 match framework {
1019 ComplianceLabel::GDPR => vec![
1020 "Implement data retention policies".to_string(),
1021 "Ensure data subject rights are supported".to_string(),
1022 "Regular privacy impact assessments".to_string(),
1023 ],
1024 ComplianceLabel::SOC2 => vec![
1025 "Regular access reviews".to_string(),
1026 "Implement monitoring and alerting".to_string(),
1027 "Document security procedures".to_string(),
1028 ],
1029 _ => vec!["Follow industry best practices".to_string()],
1030 }
1031 }
1032}
1033
1034impl Default for EnterpriseManager {
1035 fn default() -> Self {
1036 Self::new()
1037 }
1038}
1039
1040fn current_timestamp() -> u64 {
1042 SystemTime::now()
1043 .duration_since(UNIX_EPOCH)
1044 .unwrap_or_default()
1045 .as_secs()
1046}
1047
1048#[cfg(test)]
1049mod tests {
1050 use super::*;
1051
1052 #[test]
1053 fn test_create_private_repository() {
1054 let mut manager = EnterpriseManager::new();
1055
1056 let repo = PrivateRepository {
1057 id: String::new(),
1058 name: "test-repo".to_string(),
1059 description: Some("Test repository".to_string()),
1060 organization_id: "org1".to_string(),
1061 owner_id: "user1".to_string(),
1062 created_at: 0,
1063 updated_at: 0,
1064 visibility: RepositoryVisibility::Private,
1065 access_control: RepositoryAccessControl {
1066 allowed_users: HashSet::new(),
1067 allowed_roles: HashSet::new(),
1068 collaborators: HashMap::new(),
1069 ip_whitelist: vec![],
1070 require_mfa: false,
1071 session_timeout_minutes: 60,
1072 },
1073 storage_config: StorageConfig {
1074 encryption_enabled: true,
1075 encryption_algorithm: EncryptionAlgorithm::AES256,
1076 compression_enabled: true,
1077 retention_policy: RetentionPolicy {
1078 retention_days: 365,
1079 auto_delete_enabled: false,
1080 legal_hold: false,
1081 },
1082 storage_class: StorageClass::Hot,
1083 },
1084 backup_config: BackupConfig {
1085 enabled: true,
1086 frequency: BackupFrequency::Daily,
1087 retention_days: 30,
1088 cross_region_backup: true,
1089 encryption_enabled: true,
1090 },
1091 compliance_labels: vec![ComplianceLabel::SOC2],
1092 data_classification: DataClassification::Confidential,
1093 };
1094
1095 let repo_id = manager.create_private_repository(repo).unwrap();
1096 assert!(!repo_id.is_empty());
1097 assert!(manager.repositories.contains_key(&repo_id));
1098 }
1099
1100 #[test]
1101 fn test_role_assignment() {
1102 let mut manager = EnterpriseManager::new();
1103
1104 let assignment = UserRoleAssignment {
1105 user_id: "user1".to_string(),
1106 role_id: "viewer".to_string(),
1107 organization_id: "org1".to_string(),
1108 assigned_at: current_timestamp(),
1109 assigned_by: "admin1".to_string(),
1110 expires_at: None,
1111 conditions: vec![],
1112 };
1113
1114 assert!(manager.assign_role(assignment).is_ok());
1115 assert!(manager.check_permission("user1", "repo.read", None));
1116 assert!(!manager.check_permission("user1", "repo.write", None));
1117 }
1118
1119 #[test]
1120 fn test_compliance_report() {
1121 let mut manager = EnterpriseManager::new();
1122
1123 let report_id = manager
1124 .generate_compliance_report(
1125 "org1",
1126 ComplianceLabel::GDPR,
1127 current_timestamp() - 86400 * 30,
1128 current_timestamp(),
1129 )
1130 .unwrap();
1131
1132 assert!(!report_id.is_empty());
1133 assert!(manager.compliance_reports.contains_key(&report_id));
1134 }
1135}