#![allow(dead_code)]
use super::permission_rule_parser::{
permission_rule_value_from_string, permission_rule_value_to_string,
};
use crate::types::permissions::{
PermissionBehavior, PermissionRule, PermissionRuleSource, PermissionRuleValue,
};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashSet;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SettingsPermissions {
#[serde(skip_serializing_if = "Option::is_none")]
pub allow: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub deny: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ask: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "additionalDirectories")]
pub additional_directories: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SettingsJson {
#[serde(skip_serializing_if = "Option::is_none")]
pub permissions: Option<SettingsPermissions>,
}
pub fn should_allow_managed_permission_rules_only() -> bool {
false
}
pub fn should_show_always_allow_options() -> bool {
!should_allow_managed_permission_rules_only()
}
const SUPPORTED_RULE_BEHAVIORS: &[&str] = &["allow", "deny", "ask"];
fn settings_json_to_rules(
data: Option<&SettingsJson>,
source: PermissionRuleSource,
) -> Vec<PermissionRule> {
let Some(settings) = data else {
return vec![];
};
let Some(permissions) = &settings.permissions else {
return vec![];
};
let mut rules = Vec::new();
let behavior_map = [
("allow", &permissions.allow),
("deny", &permissions.deny),
("ask", &permissions.ask),
];
for (behavior_str, rules_opt) in &behavior_map {
if let Some(rule_strings) = rules_opt {
let behavior = match *behavior_str {
"allow" => PermissionBehavior::Allow,
"deny" => PermissionBehavior::Deny,
"ask" => PermissionBehavior::Ask,
_ => continue,
};
for rule_string in rule_strings {
rules.push(PermissionRule {
source: source.clone(),
rule_behavior: behavior.clone(),
rule_value: permission_rule_value_from_string(rule_string),
});
}
}
}
rules
}
pub fn load_all_permission_rules_from_disk() -> Vec<PermissionRule> {
if should_allow_managed_permission_rules_only() {
return get_permission_rules_for_source(&PermissionRuleSource::PolicySettings);
}
let mut rules = Vec::new();
let sources = [
PermissionRuleSource::UserSettings,
PermissionRuleSource::ProjectSettings,
PermissionRuleSource::LocalSettings,
];
for source in sources {
rules.extend(get_permission_rules_for_source(&source));
}
rules
}
pub fn get_permission_rules_for_source(source: &PermissionRuleSource) -> Vec<PermissionRule> {
let settings = get_settings_for_source(source);
settings_json_to_rules(settings.as_ref(), source.clone())
}
fn get_settings_for_source(_source: &PermissionRuleSource) -> Option<SettingsJson> {
None
}
pub fn delete_permission_rule_from_settings(rule: &PermissionRule) -> bool {
if !matches!(
rule.source,
PermissionRuleSource::UserSettings
| PermissionRuleSource::ProjectSettings
| PermissionRuleSource::LocalSettings
) {
return false;
}
let rule_string = permission_rule_value_to_string(&rule.rule_value);
let settings = match get_settings_for_source(&rule.source) {
Some(s) => s,
None => return false,
};
let permissions = match &settings.permissions {
Some(p) => p,
None => return false,
};
let existing_rules = match rule.rule_behavior {
PermissionBehavior::Allow => &permissions.allow,
PermissionBehavior::Deny => &permissions.deny,
PermissionBehavior::Ask => &permissions.ask,
};
let Some(existing) = existing_rules else {
return false;
};
let normalize_entry = |raw: &str| -> String {
permission_rule_value_to_string(&permission_rule_value_from_string(raw))
};
if !existing
.iter()
.any(|raw| normalize_entry(raw) == rule_string)
{
return false;
}
log::debug!("Deleted permission rule: {}", rule_string);
true
}
pub fn add_permission_rules_to_settings(
rule_values: &[PermissionRuleValue],
rule_behavior: &PermissionBehavior,
source: &PermissionRuleSource,
) -> bool {
if should_allow_managed_permission_rules_only() {
return false;
}
if rule_values.is_empty() {
return true;
}
let rule_strings: Vec<String> = rule_values
.iter()
.map(permission_rule_value_to_string)
.collect();
let settings = get_settings_for_source(source).unwrap_or(SettingsJson { permissions: None });
let mut permissions = settings.permissions.unwrap_or(SettingsPermissions {
allow: None,
deny: None,
ask: None,
additional_directories: None,
});
let existing_rules = match rule_behavior {
PermissionBehavior::Allow => &mut permissions.allow,
PermissionBehavior::Deny => &mut permissions.deny,
PermissionBehavior::Ask => &mut permissions.ask,
};
let existing_set: HashSet<String> = existing_rules
.as_ref()
.map(|rules| {
rules
.iter()
.map(|raw| permission_rule_value_to_string(&permission_rule_value_from_string(raw)))
.collect()
})
.unwrap_or_default();
let new_rules: Vec<String> = rule_strings
.iter()
.filter(|rule| {
!existing_set.contains(&permission_rule_value_to_string(
&permission_rule_value_from_string(rule),
))
})
.cloned()
.collect();
if new_rules.is_empty() {
return true;
}
if let Some(rules) = existing_rules {
rules.extend(new_rules);
} else {
*existing_rules = Some(new_rules);
}
log::debug!("Added permission rules to {:?}", source);
true
}