all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced
@ 2023-12-14 12:42 Lukas Wagner
  2023-12-14 12:42 ` [pve-devel] [PATCH proxmox 2/2] notify: add separate context for unit-tests Lukas Wagner
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Lukas Wagner @ 2023-12-14 12:42 UTC (permalink / raw)
  To: pve-devel

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>
---
 proxmox-notify/src/api/gotify.rs   |  2 +-
 proxmox-notify/src/api/mod.rs      | 74 ++++++++++++++++++++++--------
 proxmox-notify/src/api/sendmail.rs |  2 +-
 proxmox-notify/src/api/smtp.rs     |  2 +-
 4 files changed, 59 insertions(+), 21 deletions(-)

diff --git a/proxmox-notify/src/api/gotify.rs b/proxmox-notify/src/api/gotify.rs
index 98ff255..a93a024 100644
--- a/proxmox-notify/src/api/gotify.rs
+++ b/proxmox-notify/src/api/gotify.rs
@@ -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);
diff --git a/proxmox-notify/src/api/mod.rs b/proxmox-notify/src/api/mod.rs
index 762d448..919dcb9 100644
--- a/proxmox-notify/src/api/mod.rs
+++ b/proxmox-notify/src/api/mod.rs
@@ -3,7 +3,7 @@ use std::collections::HashSet;
 
 use proxmox_http_error::HttpError;
 
-use crate::Config;
+use crate::{Config, Origin};
 
 pub mod common;
 #[cfg(feature = "gotify")]
@@ -111,7 +111,26 @@ 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) {
+        let origin: Option<Origin> = entity_config
+            .1
+            .as_object()
+            .and_then(|obj| obj.get("origin"))
+            .cloned()
+            .and_then(|origin_value| serde_json::from_value(origin_value).ok());
+        if let Some(origin) = 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,31 +210,31 @@ 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();
+        let mut config = test_helpers::empty_config();
 
-        matcher::add_matcher(
+        sendmail::add_endpoint(
             &mut config,
-            &MatcherConfig {
-                name: "matcher".to_string(),
-                target: Some(vec!["sendmail".to_string(), "gotify".to_string()])
-                    ..Default::default(),
+            &SendmailConfig {
+                name: "sendmail".to_string(),
+                mailto: Some(vec!["foo@example.com".to_string()]),
+                ..Default::default()
             },
         )?;
 
         sendmail::add_endpoint(
             &mut config,
             &SendmailConfig {
-                name: "sendmail".to_string(),
+                name: "builtin".to_string(),
                 mailto: Some(vec!["foo@example.com".to_string()]),
+                origin: Some(Origin::Builtin),
                 ..Default::default()
             },
         )?;
@@ -233,6 +252,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 +277,7 @@ mod tests {
             HashSet::from([
                 "matcher".to_string(),
                 "sendmail".to_string(),
+                "builtin".to_string(),
                 "gotify".to_string()
             ])
         );
@@ -268,12 +301,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 +319,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 +327,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());
     }
 }
diff --git a/proxmox-notify/src/api/sendmail.rs b/proxmox-notify/src/api/sendmail.rs
index 0f40178..e911505 100644
--- a/proxmox-notify/src/api/sendmail.rs
+++ b/proxmox-notify/src/api/sendmail.rs
@@ -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);
 
diff --git a/proxmox-notify/src/api/smtp.rs b/proxmox-notify/src/api/smtp.rs
index 14b301c..6bd0c4b 100644
--- a/proxmox-notify/src/api/smtp.rs
+++ b/proxmox-notify/src/api/smtp.rs
@@ -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);
-- 
2.39.2





^ permalink raw reply	[flat|nested] 5+ messages in thread

* [pve-devel] [PATCH proxmox 2/2] notify: add separate context for unit-tests
  2023-12-14 12:42 [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced Lukas Wagner
@ 2023-12-14 12:42 ` Lukas Wagner
  2024-01-08 10:44 ` [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced Lukas Wagner
  2024-01-09 13:18 ` Wolfgang Bumiller
  2 siblings, 0 replies; 5+ messages in thread
From: Lukas Wagner @ 2023-12-14 12:42 UTC (permalink / raw)
  To: pve-devel

... as using PVEContext for tests is brittle and annoying for some
tests.

Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
 proxmox-notify/src/context/mod.rs  | 10 +++++-----
 proxmox-notify/src/context/test.rs | 26 ++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 5 deletions(-)
 create mode 100644 proxmox-notify/src/context/test.rs

diff --git a/proxmox-notify/src/context/mod.rs b/proxmox-notify/src/context/mod.rs
index b419641..cc68603 100644
--- a/proxmox-notify/src/context/mod.rs
+++ b/proxmox-notify/src/context/mod.rs
@@ -7,6 +7,8 @@ pub mod common;
 pub mod pbs;
 #[cfg(feature = "pve-context")]
 pub mod pve;
+#[cfg(test)]
+mod test;
 
 /// Product-specific context
 pub trait Context: Send + Sync + Debug {
@@ -22,12 +24,10 @@ pub trait Context: Send + Sync + Debug {
     fn default_config(&self) -> &'static str;
 }
 
-#[cfg(not(feature = "pve-context"))]
+#[cfg(not(test))]
 static CONTEXT: Mutex<Option<&'static dyn Context>> = Mutex::new(None);
-// The test unfortunately require context...
-// TODO: Check if we can make this nicer...
-#[cfg(feature = "pve-context")]
-static CONTEXT: Mutex<Option<&'static dyn Context>> = Mutex::new(Some(&pve::PVE_CONTEXT));
+#[cfg(test)]
+static CONTEXT: Mutex<Option<&'static dyn Context>> = Mutex::new(Some(&test::TestContext));
 
 /// Set the product-specific context
 pub fn set_context(context: &'static dyn Context) {
diff --git a/proxmox-notify/src/context/test.rs b/proxmox-notify/src/context/test.rs
new file mode 100644
index 0000000..61f794a
--- /dev/null
+++ b/proxmox-notify/src/context/test.rs
@@ -0,0 +1,26 @@
+use crate::context::Context;
+
+#[derive(Debug)]
+pub struct TestContext;
+
+impl Context for TestContext {
+    fn lookup_email_for_user(&self, _user: &str) -> Option<String> {
+        Some("test@example.com".into())
+    }
+
+    fn default_sendmail_author(&self) -> String {
+        "Proxmox VE".into()
+    }
+
+    fn default_sendmail_from(&self) -> String {
+        "root".into()
+    }
+
+    fn http_proxy_config(&self) -> Option<String> {
+        None
+    }
+
+    fn default_config(&self) -> &'static str {
+        ""
+    }
+}
-- 
2.39.2




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced
  2023-12-14 12:42 [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced Lukas Wagner
  2023-12-14 12:42 ` [pve-devel] [PATCH proxmox 2/2] notify: add separate context for unit-tests Lukas Wagner
@ 2024-01-08 10:44 ` Lukas Wagner
  2024-01-09 13:18 ` Wolfgang Bumiller
  2 siblings, 0 replies; 5+ messages in thread
From: Lukas Wagner @ 2024-01-08 10:44 UTC (permalink / raw)
  To: pve-devel

ping

On 12/14/23 13:42, Lukas Wagner wrote:
> 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>
> ---
>   proxmox-notify/src/api/gotify.rs   |  2 +-
>   proxmox-notify/src/api/mod.rs      | 74 ++++++++++++++++++++++--------
>   proxmox-notify/src/api/sendmail.rs |  2 +-
>   proxmox-notify/src/api/smtp.rs     |  2 +-
>   4 files changed, 59 insertions(+), 21 deletions(-)
> 
> diff --git a/proxmox-notify/src/api/gotify.rs b/proxmox-notify/src/api/gotify.rs
> index 98ff255..a93a024 100644
> --- a/proxmox-notify/src/api/gotify.rs
> +++ b/proxmox-notify/src/api/gotify.rs
> @@ -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);
> diff --git a/proxmox-notify/src/api/mod.rs b/proxmox-notify/src/api/mod.rs
> index 762d448..919dcb9 100644
> --- a/proxmox-notify/src/api/mod.rs
> +++ b/proxmox-notify/src/api/mod.rs
> @@ -3,7 +3,7 @@ use std::collections::HashSet;
>   
>   use proxmox_http_error::HttpError;
>   
> -use crate::Config;
> +use crate::{Config, Origin};
>   
>   pub mod common;
>   #[cfg(feature = "gotify")]
> @@ -111,7 +111,26 @@ 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) {
> +        let origin: Option<Origin> = entity_config
> +            .1
> +            .as_object()
> +            .and_then(|obj| obj.get("origin"))
> +            .cloned()
> +            .and_then(|origin_value| serde_json::from_value(origin_value).ok());
> +        if let Some(origin) = 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,31 +210,31 @@ 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();
> +        let mut config = test_helpers::empty_config();
>   
> -        matcher::add_matcher(
> +        sendmail::add_endpoint(
>               &mut config,
> -            &MatcherConfig {
> -                name: "matcher".to_string(),
> -                target: Some(vec!["sendmail".to_string(), "gotify".to_string()])
> -                    ..Default::default(),
> +            &SendmailConfig {
> +                name: "sendmail".to_string(),
> +                mailto: Some(vec!["foo@example.com".to_string()]),
> +                ..Default::default()
>               },
>           )?;
>   
>           sendmail::add_endpoint(
>               &mut config,
>               &SendmailConfig {
> -                name: "sendmail".to_string(),
> +                name: "builtin".to_string(),
>                   mailto: Some(vec!["foo@example.com".to_string()]),
> +                origin: Some(Origin::Builtin),
>                   ..Default::default()
>               },
>           )?;
> @@ -233,6 +252,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 +277,7 @@ mod tests {
>               HashSet::from([
>                   "matcher".to_string(),
>                   "sendmail".to_string(),
> +                "builtin".to_string(),
>                   "gotify".to_string()
>               ])
>           );
> @@ -268,12 +301,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 +319,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 +327,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());
>       }
>   }
> diff --git a/proxmox-notify/src/api/sendmail.rs b/proxmox-notify/src/api/sendmail.rs
> index 0f40178..e911505 100644
> --- a/proxmox-notify/src/api/sendmail.rs
> +++ b/proxmox-notify/src/api/sendmail.rs
> @@ -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);
>   
> diff --git a/proxmox-notify/src/api/smtp.rs b/proxmox-notify/src/api/smtp.rs
> index 14b301c..6bd0c4b 100644
> --- a/proxmox-notify/src/api/smtp.rs
> +++ b/proxmox-notify/src/api/smtp.rs
> @@ -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);

-- 
- Lukas




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced
  2023-12-14 12:42 [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced Lukas Wagner
  2023-12-14 12:42 ` [pve-devel] [PATCH proxmox 2/2] notify: add separate context for unit-tests Lukas Wagner
  2024-01-08 10:44 ` [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced Lukas Wagner
@ 2024-01-09 13:18 ` Wolfgang Bumiller
  2024-01-10  8:29   ` Lukas Wagner
  2 siblings, 1 reply; 5+ messages in thread
From: Wolfgang Bumiller @ 2024-01-09 13:18 UTC (permalink / raw)
  To: Lukas Wagner; +Cc: pve-devel

On Thu, Dec 14, 2023 at 01:42:07PM +0100, Lukas Wagner wrote:
> by a matcher.

^ this line should be part of the subject

> 
> 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>
> ---
>  proxmox-notify/src/api/gotify.rs   |  2 +-
>  proxmox-notify/src/api/mod.rs      | 74 ++++++++++++++++++++++--------
>  proxmox-notify/src/api/sendmail.rs |  2 +-
>  proxmox-notify/src/api/smtp.rs     |  2 +-
>  4 files changed, 59 insertions(+), 21 deletions(-)
> 
> diff --git a/proxmox-notify/src/api/gotify.rs b/proxmox-notify/src/api/gotify.rs
> index 98ff255..a93a024 100644
> --- a/proxmox-notify/src/api/gotify.rs
> +++ b/proxmox-notify/src/api/gotify.rs
> @@ -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);
> diff --git a/proxmox-notify/src/api/mod.rs b/proxmox-notify/src/api/mod.rs
> index 762d448..919dcb9 100644
> --- a/proxmox-notify/src/api/mod.rs
> +++ b/proxmox-notify/src/api/mod.rs
> @@ -3,7 +3,7 @@ use std::collections::HashSet;
>  
>  use proxmox_http_error::HttpError;
>  
> -use crate::Config;
> +use crate::{Config, Origin};
>  
>  pub mod common;
>  #[cfg(feature = "gotify")]
> @@ -111,7 +111,26 @@ 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) {
> +        let origin: Option<Origin> = entity_config
> +            .1
> +            .as_object()
> +            .and_then(|obj| obj.get("origin"))
> +            .cloned()
> +            .and_then(|origin_value| serde_json::from_value(origin_value).ok());

^ .cloned() should not be necessary, Value and &Value implement
`Deserialize_r_`, so you can use:

    .and_then(|origin_value| Origin::deserialize(origin_value).ok());

Additionally, Value returns a valid `Null` value when trying to index a
non-object as well as when the key does not exist in the object, so it
should be possible to do replace all of the above and the line below
with:

    if let Some(origin) = Origin::deserialize(&entity_config.1["origin"]) {

> +        if let Some(origin) = 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,31 +210,31 @@ mod test_helpers {




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced
  2024-01-09 13:18 ` Wolfgang Bumiller
@ 2024-01-10  8:29   ` Lukas Wagner
  0 siblings, 0 replies; 5+ messages in thread
From: Lukas Wagner @ 2024-01-10  8:29 UTC (permalink / raw)
  To: Wolfgang Bumiller; +Cc: pve-devel



On 1/9/24 14:18, Wolfgang Bumiller wrote:
> On Thu, Dec 14, 2023 at 01:42:07PM +0100, Lukas Wagner wrote:
>> by a matcher.
> 
> ^ this line should be part of the subject
> 
>>
>> 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>
>> ---
>>   proxmox-notify/src/api/gotify.rs   |  2 +-
>>   proxmox-notify/src/api/mod.rs      | 74 ++++++++++++++++++++++--------
>>   proxmox-notify/src/api/sendmail.rs |  2 +-
>>   proxmox-notify/src/api/smtp.rs     |  2 +-
>>   4 files changed, 59 insertions(+), 21 deletions(-)
>>
>> diff --git a/proxmox-notify/src/api/gotify.rs b/proxmox-notify/src/api/gotify.rs
>> index 98ff255..a93a024 100644
>> --- a/proxmox-notify/src/api/gotify.rs
>> +++ b/proxmox-notify/src/api/gotify.rs
>> @@ -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);
>> diff --git a/proxmox-notify/src/api/mod.rs b/proxmox-notify/src/api/mod.rs
>> index 762d448..919dcb9 100644
>> --- a/proxmox-notify/src/api/mod.rs
>> +++ b/proxmox-notify/src/api/mod.rs
>> @@ -3,7 +3,7 @@ use std::collections::HashSet;
>>   
>>   use proxmox_http_error::HttpError;
>>   
>> -use crate::Config;
>> +use crate::{Config, Origin};
>>   
>>   pub mod common;
>>   #[cfg(feature = "gotify")]
>> @@ -111,7 +111,26 @@ 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) {
>> +        let origin: Option<Origin> = entity_config
>> +            .1
>> +            .as_object()
>> +            .and_then(|obj| obj.get("origin"))
>> +            .cloned()
>> +            .and_then(|origin_value| serde_json::from_value(origin_value).ok());
> 
> ^ .cloned() should not be necessary, Value and &Value implement
> `Deserialize_r_`, so you can use:
> 
>      .and_then(|origin_value| Origin::deserialize(origin_value).ok());
> 
> Additionally, Value returns a valid `Null` value when trying to index a
> non-object as well as when the key does not exist in the object, so it
> should be possible to do replace all of the above and the line below
> with:
> 
>      if let Some(origin) = Origin::deserialize(&entity_config.1["origin"]) {
> 

I'll try that, thanks!

>> +        if let Some(origin) = 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,31 +210,31 @@ mod test_helpers {

-- 
- Lukas




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-01-10  8:30 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-14 12:42 [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced Lukas Wagner
2023-12-14 12:42 ` [pve-devel] [PATCH proxmox 2/2] notify: add separate context for unit-tests Lukas Wagner
2024-01-08 10:44 ` [pve-devel] [PATCH proxmox 1/2] notify: api: allow resetting built-in targets when they are referenced Lukas Wagner
2024-01-09 13:18 ` Wolfgang Bumiller
2024-01-10  8:29   ` Lukas Wagner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal