use super::*;
impl BucketWarden {
pub fn console_api_preferences_read(
&mut self,
access_key_id: &str,
) -> Result<ConsoleApiPreferences, RuntimeError> {
let principal = self.console_api_principal(access_key_id)?;
self.require_operator_action(
&principal,
OperatorAction::ReadDiagnostics,
"*",
"ui:GetPreferences",
)?;
Ok(ConsoleApiPreferences {
values: self
.console_preferences
.get(&principal)
.cloned()
.unwrap_or_default(),
})
}
pub fn console_api_preferences_write(
&mut self,
access_key_id: &str,
preferences: ConsoleApiPreferences,
) -> Result<ConsoleApiPreferences, RuntimeError> {
let principal = self.console_api_principal(access_key_id)?;
self.require_operator_action(
&principal,
OperatorAction::ReadDiagnostics,
"*",
"ui:PutPreferences",
)?;
validate_preferences(&preferences.values)?;
self.console_preferences
.insert(principal.clone(), preferences.values.clone());
self.audit.append(
&principal,
"ui:PutPreferences",
"*",
AuditOutcome::Allowed,
Some(format!("keys={}", preferences.values.len())),
);
Ok(preferences)
}
}
fn validate_preferences(values: &BTreeMap<String, String>) -> Result<(), RuntimeError> {
if values.len() > 64 {
return Err(invalid_preference("count", values.len().to_string()));
}
for (key, value) in values {
if key.trim().is_empty() || key.len() > 128 {
return Err(invalid_preference("key", key.clone()));
}
if value.len() > 4096 {
return Err(invalid_preference("value", key.clone()));
}
if !key
.chars()
.all(|ch| ch.is_ascii_alphanumeric() || matches!(ch, '.' | '-' | '_'))
{
return Err(invalid_preference("key", key.clone()));
}
}
Ok(())
}
fn invalid_preference(name: &str, value: String) -> RuntimeError {
RuntimeError::InvalidListParameter {
name: format!("preference-{name}"),
value,
}
}