mirror of
https://git.proxmox.com/git/proxmox
synced 2025-08-05 02:18:16 +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> {
|
pub fn delete_gotify_endpoint(config: &mut Config, name: &str) -> Result<(), HttpError> {
|
||||||
// Check if the endpoint exists
|
// Check if the endpoint exists
|
||||||
let _ = get_endpoint(config, name)?;
|
let _ = get_endpoint(config, name)?;
|
||||||
super::ensure_unused(config, name)?;
|
super::ensure_safe_to_delete(config, name)?;
|
||||||
|
|
||||||
remove_private_config_entry(config, name)?;
|
remove_private_config_entry(config, name)?;
|
||||||
config.config.sections.remove(name);
|
config.config.sections.remove(name);
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use serde::Serialize;
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use proxmox_http_error::HttpError;
|
use proxmox_http_error::HttpError;
|
||||||
|
|
||||||
use crate::Config;
|
use crate::{Config, Origin};
|
||||||
|
|
||||||
pub mod common;
|
pub mod common;
|
||||||
#[cfg(feature = "gotify")]
|
#[cfg(feature = "gotify")]
|
||||||
@ -111,7 +112,20 @@ fn get_referrers(config: &Config, entity: &str) -> Result<HashSet<String>, HttpE
|
|||||||
Ok(referrers)
|
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)?;
|
let referrers = get_referrers(config, entity)?;
|
||||||
|
|
||||||
if !referrers.is_empty() {
|
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 {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::endpoints::gotify::{GotifyConfig, GotifyPrivateConfig};
|
use crate::endpoints::gotify::{GotifyConfig, GotifyPrivateConfig};
|
||||||
use crate::endpoints::sendmail::SendmailConfig;
|
use crate::endpoints::sendmail::SendmailConfig;
|
||||||
use crate::filter::FilterConfig;
|
use crate::matcher::MatcherConfig;
|
||||||
use crate::group::GroupConfig;
|
|
||||||
|
|
||||||
fn prepare_config() -> Result<Config, HttpError> {
|
fn prepare_config() -> Result<Config, HttpError> {
|
||||||
let mut config = super::test_helpers::empty_config();
|
let mut config = 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(),
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
sendmail::add_endpoint(
|
sendmail::add_endpoint(
|
||||||
&mut config,
|
&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(
|
gotify::add_endpoint(
|
||||||
&mut config,
|
&mut config,
|
||||||
&GotifyConfig {
|
&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)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,6 +272,7 @@ mod tests {
|
|||||||
HashSet::from([
|
HashSet::from([
|
||||||
"matcher".to_string(),
|
"matcher".to_string(),
|
||||||
"sendmail".to_string(),
|
"sendmail".to_string(),
|
||||||
|
"builtin".to_string(),
|
||||||
"gotify".to_string()
|
"gotify".to_string()
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
@ -268,12 +296,17 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ensure_unused() {
|
fn test_ensure_safe_to_delete() {
|
||||||
let config = prepare_config().unwrap();
|
let config = prepare_config().unwrap();
|
||||||
|
|
||||||
assert!(ensure_unused(&config, "gotify").is_err());
|
assert!(ensure_safe_to_delete(&config, "gotify").is_err());
|
||||||
assert!(ensure_unused(&config, "sendmail").is_err());
|
assert!(ensure_safe_to_delete(&config, "sendmail").is_err());
|
||||||
assert!(ensure_unused(&config, "matcher").is_ok());
|
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]
|
#[test]
|
||||||
@ -281,7 +314,7 @@ mod tests {
|
|||||||
let config = prepare_config().unwrap();
|
let config = prepare_config().unwrap();
|
||||||
|
|
||||||
assert!(ensure_unique(&config, "sendmail").is_err());
|
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());
|
assert!(ensure_unique(&config, "new").is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,6 +322,6 @@ mod tests {
|
|||||||
fn test_ensure_endpoints_exist() {
|
fn test_ensure_endpoints_exist() {
|
||||||
let config = prepare_config().unwrap();
|
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> {
|
pub fn delete_endpoint(config: &mut Config, name: &str) -> Result<(), HttpError> {
|
||||||
// Check if the endpoint exists
|
// Check if the endpoint exists
|
||||||
let _ = get_endpoint(config, name)?;
|
let _ = get_endpoint(config, name)?;
|
||||||
super::ensure_unused(config, name)?;
|
super::ensure_safe_to_delete(config, name)?;
|
||||||
|
|
||||||
config.config.sections.remove(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> {
|
pub fn delete_endpoint(config: &mut Config, name: &str) -> Result<(), HttpError> {
|
||||||
// Check if the endpoint exists
|
// Check if the endpoint exists
|
||||||
let _ = get_endpoint(config, name)?;
|
let _ = get_endpoint(config, name)?;
|
||||||
super::ensure_unused(config, name)?;
|
super::ensure_safe_to_delete(config, name)?;
|
||||||
|
|
||||||
super::remove_private_config_entry(config, name)?;
|
super::remove_private_config_entry(config, name)?;
|
||||||
config.config.sections.remove(name);
|
config.config.sections.remove(name);
|
||||||
|
Loading…
Reference in New Issue
Block a user