cfgd_core/composition/
permissions.rs1use std::collections::HashMap;
2
3use crate::config::PolicyItems;
4
5use super::CompositionInput;
6
7#[derive(Debug, Clone)]
9pub struct PermissionChange {
10 pub source: String,
11 pub description: String,
12}
13
14pub fn detect_permission_changes(
17 old_sources: &[CompositionInput],
18 new_sources: &[CompositionInput],
19) -> Vec<PermissionChange> {
20 let mut changes = Vec::new();
21
22 let old_map: HashMap<&str, &CompositionInput> = old_sources
23 .iter()
24 .map(|s| (s.source_name.as_str(), s))
25 .collect();
26
27 for new_src in new_sources {
28 let name = &new_src.source_name;
29 match old_map.get(name.as_str()) {
30 None => {
31 changes.push(PermissionChange {
32 source: name.clone(),
33 description: "New source added".to_string(),
34 });
35 }
36 Some(old_src) => {
37 let old_locked = count_policy_tier_items(&old_src.policy.locked);
39 let new_locked = count_policy_tier_items(&new_src.policy.locked);
40 if new_locked > old_locked {
41 changes.push(PermissionChange {
42 source: name.clone(),
43 description: format!(
44 "Locked items increased from {} to {}",
45 old_locked, new_locked
46 ),
47 });
48 }
49
50 let old_required = count_policy_tier_items(&old_src.policy.required);
52 let new_required = count_policy_tier_items(&new_src.policy.required);
53 if new_required > old_required {
54 changes.push(PermissionChange {
55 source: name.clone(),
56 description: format!(
57 "Required items increased from {} to {}",
58 old_required, new_required
59 ),
60 });
61 }
62
63 let old_c = &old_src.constraints;
65 let new_c = &new_src.constraints;
66 if old_c.no_scripts && !new_c.no_scripts {
67 changes.push(PermissionChange {
68 source: name.clone(),
69 description: "Scripts have been enabled".to_string(),
70 });
71 }
72 if new_c.allowed_target_paths.len() > old_c.allowed_target_paths.len() {
73 changes.push(PermissionChange {
74 source: name.clone(),
75 description: "Allowed target paths expanded".to_string(),
76 });
77 }
78 }
79 }
80 }
81
82 changes
83}
84
85pub(super) fn count_policy_tier_items(items: &PolicyItems) -> usize {
86 let mut count = 0;
87 if let Some(ref pkgs) = items.packages {
88 if let Some(ref brew) = pkgs.brew {
89 count += brew.formulae.len() + brew.casks.len() + brew.taps.len();
90 }
91 if let Some(ref apt) = pkgs.apt {
92 count += apt.packages.len();
93 }
94 if let Some(ref cargo) = pkgs.cargo {
95 count += cargo.packages.len();
96 }
97 count += pkgs.pipx.len() + pkgs.dnf.len();
98 if let Some(ref npm) = pkgs.npm {
99 count += npm.global.len();
100 }
101 }
102 count += items.files.len();
103 count += items.env.len();
104 count += items.aliases.len();
105 count += items.system.len();
106 count += items.modules.len();
107 count
108}