mirror of
https://git.proxmox.com/git/proxmox
synced 2025-08-04 17:14:54 +00:00
notify: api: allow resetting built-in targets if used by a matcher
In the 'delete'-handler targets, we check if a target is still referenced by a matcher - if it is, we return an error. For built-in targets, this is actually not necessary, since 'deleting' a built-in only resets it to its default settings - it will continue to exist after that. The user could easily trigger this if 'mail-to-root', which is referenced by 'default-matcher' is modified and then reset to its defaults: An error is shown, the built-in target is not reset. This commit disables this check if it is a built-in target. Renamed the helper 'ensure_unused' to 'ensure_safe_to_delete' in the process. Also fixed the tests in api::test - they were never executed due to a faulty #[cfg] directive. Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
This commit is contained in:
parent
efa607f1b5
commit
50fa98e241
@ -136,7 +136,7 @@ pub fn update_endpoint(
|
||||
pub fn delete_gotify_endpoint(config: &mut Config, name: &str) -> Result<(), HttpError> {
|
||||
// Check if the endpoint exists
|
||||
let _ = get_endpoint(config, name)?;
|
||||
super::ensure_unused(config, name)?;
|
||||
super::ensure_safe_to_delete(config, name)?;
|
||||
|
||||
remove_private_config_entry(config, name)?;
|
||||
config.config.sections.remove(name);
|
||||
|
@ -1,9 +1,10 @@
|
||||
use serde::Serialize;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use proxmox_http_error::HttpError;
|
||||
|
||||
use crate::Config;
|
||||
use crate::{Config, Origin};
|
||||
|
||||
pub mod common;
|
||||
#[cfg(feature = "gotify")]
|
||||
@ -111,7 +112,20 @@ fn get_referrers(config: &Config, entity: &str) -> Result<HashSet<String>, HttpE
|
||||
Ok(referrers)
|
||||
}
|
||||
|
||||
fn ensure_unused(config: &Config, entity: &str) -> Result<(), HttpError> {
|
||||
fn ensure_safe_to_delete(config: &Config, entity: &str) -> Result<(), HttpError> {
|
||||
if let Some(entity_config) = config.config.sections.get(entity) {
|
||||
if let Ok(origin) = Origin::deserialize(&entity_config.1["origin"]) {
|
||||
// Built-ins are never actually removed, only reset to their default
|
||||
// It is thus safe to do the reset if another entity depends
|
||||
// on it
|
||||
if origin == Origin::Builtin || origin == Origin::ModifiedBuiltin {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
http_bail!(NOT_FOUND, "entity '{entity}' does not exist");
|
||||
}
|
||||
|
||||
let referrers = get_referrers(config, entity)?;
|
||||
|
||||
if !referrers.is_empty() {
|
||||
@ -191,25 +205,15 @@ mod test_helpers {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, gotify, sendmail))]
|
||||
#[cfg(all(test, feature = "gotify", feature = "sendmail"))]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::endpoints::gotify::{GotifyConfig, GotifyPrivateConfig};
|
||||
use crate::endpoints::sendmail::SendmailConfig;
|
||||
use crate::filter::FilterConfig;
|
||||
use crate::group::GroupConfig;
|
||||
use crate::matcher::MatcherConfig;
|
||||
|
||||
fn prepare_config() -> Result<Config, HttpError> {
|
||||
let mut config = super::test_helpers::empty_config();
|
||||
|
||||
matcher::add_matcher(
|
||||
&mut config,
|
||||
&MatcherConfig {
|
||||
name: "matcher".to_string(),
|
||||
target: Some(vec!["sendmail".to_string(), "gotify".to_string()])
|
||||
..Default::default(),
|
||||
},
|
||||
)?;
|
||||
let mut config = test_helpers::empty_config();
|
||||
|
||||
sendmail::add_endpoint(
|
||||
&mut config,
|
||||
@ -220,6 +224,16 @@ mod tests {
|
||||
},
|
||||
)?;
|
||||
|
||||
sendmail::add_endpoint(
|
||||
&mut config,
|
||||
&SendmailConfig {
|
||||
name: "builtin".to_string(),
|
||||
mailto: Some(vec!["foo@example.com".to_string()]),
|
||||
origin: Some(Origin::Builtin),
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
gotify::add_endpoint(
|
||||
&mut config,
|
||||
&GotifyConfig {
|
||||
@ -233,6 +247,19 @@ mod tests {
|
||||
},
|
||||
)?;
|
||||
|
||||
matcher::add_matcher(
|
||||
&mut config,
|
||||
&MatcherConfig {
|
||||
name: "matcher".to_string(),
|
||||
target: Some(vec![
|
||||
"sendmail".to_string(),
|
||||
"gotify".to_string(),
|
||||
"builtin".to_string(),
|
||||
]),
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
@ -245,6 +272,7 @@ mod tests {
|
||||
HashSet::from([
|
||||
"matcher".to_string(),
|
||||
"sendmail".to_string(),
|
||||
"builtin".to_string(),
|
||||
"gotify".to_string()
|
||||
])
|
||||
);
|
||||
@ -268,12 +296,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ensure_unused() {
|
||||
fn test_ensure_safe_to_delete() {
|
||||
let config = prepare_config().unwrap();
|
||||
|
||||
assert!(ensure_unused(&config, "gotify").is_err());
|
||||
assert!(ensure_unused(&config, "sendmail").is_err());
|
||||
assert!(ensure_unused(&config, "matcher").is_ok());
|
||||
assert!(ensure_safe_to_delete(&config, "gotify").is_err());
|
||||
assert!(ensure_safe_to_delete(&config, "sendmail").is_err());
|
||||
assert!(ensure_safe_to_delete(&config, "matcher").is_ok());
|
||||
|
||||
// built-ins are always safe to delete, since there is no way to actually
|
||||
// delete them... they will only be reset to their default settings and
|
||||
// will thus continue to exist
|
||||
assert!(ensure_safe_to_delete(&config, "builtin").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -281,7 +314,7 @@ mod tests {
|
||||
let config = prepare_config().unwrap();
|
||||
|
||||
assert!(ensure_unique(&config, "sendmail").is_err());
|
||||
assert!(ensure_unique(&config, "group").is_err());
|
||||
assert!(ensure_unique(&config, "matcher").is_err());
|
||||
assert!(ensure_unique(&config, "new").is_ok());
|
||||
}
|
||||
|
||||
@ -289,6 +322,6 @@ mod tests {
|
||||
fn test_ensure_endpoints_exist() {
|
||||
let config = prepare_config().unwrap();
|
||||
|
||||
assert!(ensure_endpoints_exist(&config, &vec!["sendmail", "gotify"]).is_ok());
|
||||
assert!(ensure_endpoints_exist(&config, &["sendmail", "gotify", "builtin"]).is_ok());
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ pub fn update_endpoint(
|
||||
pub fn delete_endpoint(config: &mut Config, name: &str) -> Result<(), HttpError> {
|
||||
// Check if the endpoint exists
|
||||
let _ = get_endpoint(config, name)?;
|
||||
super::ensure_unused(config, name)?;
|
||||
super::ensure_safe_to_delete(config, name)?;
|
||||
|
||||
config.config.sections.remove(name);
|
||||
|
||||
|
@ -192,7 +192,7 @@ pub fn update_endpoint(
|
||||
pub fn delete_endpoint(config: &mut Config, name: &str) -> Result<(), HttpError> {
|
||||
// Check if the endpoint exists
|
||||
let _ = get_endpoint(config, name)?;
|
||||
super::ensure_unused(config, name)?;
|
||||
super::ensure_safe_to_delete(config, name)?;
|
||||
|
||||
super::remove_private_config_entry(config, name)?;
|
||||
config.config.sections.remove(name);
|
||||
|
Loading…
Reference in New Issue
Block a user