mirror of
https://git.proxmox.com/git/proxmox
synced 2025-10-04 05:09:00 +00:00

Previously, notification templates could be modified by the user, but these were overwritten again with installing newer package versions of pve-manager and proxmox-backup. Now override templates can be created cluster-wide in the path “/etc/{pve,proxmox-backup}/notification-templates/{namespace}”, which are used with priority. The folder structure has to be created and populated manually (e.g. /etc/pve/notification-templates/default). If override templates are not existing or their rendering fails, the vendor templates in "/usr/share/{pve-manager,proxmox-backup}/templates/default/" are used. Sequence: [override html -> vendor html ->] override txt -> vendor txt An error is only returned if none of the template candidates could be used. Using an override template gets not logged. Signed-off-by: Alexander Zeidler <a.zeidler@proxmox.com> Reviewed-by: Lukas Wagner <l.wagner@proxmox.com> Tested-by: Lukas Wagner <l.wagner@proxmox.com> Link: https://lore.proxmox.com/20250321133341.151340-1-a.zeidler@proxmox.com
122 lines
3.6 KiB
Rust
122 lines
3.6 KiB
Rust
use crate::context::{common, Context};
|
|
use crate::renderer::TemplateSource;
|
|
use crate::Error;
|
|
use std::path::Path;
|
|
|
|
fn lookup_mail_address(content: &str, user: &str) -> Option<String> {
|
|
common::normalize_for_return(content.lines().find_map(|line| {
|
|
let fields: Vec<&str> = line.split(':').collect();
|
|
#[allow(clippy::get_first)] // to keep expression style consistent
|
|
match fields.get(0)?.trim() == "user" && fields.get(1)?.trim() == user {
|
|
true => fields.get(6).copied(),
|
|
false => None,
|
|
}
|
|
}))
|
|
}
|
|
|
|
const DEFAULT_CONFIG: &str = "\
|
|
sendmail: mail-to-root
|
|
comment Send mails to root@pam's email address
|
|
mailto-user root@pam
|
|
|
|
|
|
matcher: default-matcher
|
|
mode all
|
|
target mail-to-root
|
|
comment Route all notifications to mail-to-root
|
|
";
|
|
|
|
#[derive(Debug)]
|
|
pub struct PVEContext;
|
|
|
|
impl Context for PVEContext {
|
|
fn lookup_email_for_user(&self, user: &str) -> Option<String> {
|
|
let content = common::attempt_file_read("/etc/pve/user.cfg");
|
|
content.and_then(|content| lookup_mail_address(&content, user))
|
|
}
|
|
|
|
fn default_sendmail_author(&self) -> String {
|
|
"Proxmox VE".into()
|
|
}
|
|
|
|
fn default_sendmail_from(&self) -> String {
|
|
let content = common::attempt_file_read("/etc/pve/datacenter.cfg");
|
|
content
|
|
.and_then(|content| common::lookup_datacenter_config_key(&content, "email_from"))
|
|
.unwrap_or_else(|| String::from("root"))
|
|
}
|
|
|
|
fn http_proxy_config(&self) -> Option<String> {
|
|
let content = common::attempt_file_read("/etc/pve/datacenter.cfg");
|
|
content.and_then(|content| common::lookup_datacenter_config_key(&content, "http_proxy"))
|
|
}
|
|
|
|
fn default_config(&self) -> &'static str {
|
|
DEFAULT_CONFIG
|
|
}
|
|
|
|
fn lookup_template(
|
|
&self,
|
|
filename: &str,
|
|
namespace: Option<&str>,
|
|
source: TemplateSource,
|
|
) -> Result<Option<String>, Error> {
|
|
let path = match source {
|
|
TemplateSource::Vendor => "/usr/share/pve-manager/templates",
|
|
TemplateSource::Override => "/etc/pve/notification-templates",
|
|
};
|
|
|
|
let path = Path::new(&path)
|
|
.join(namespace.unwrap_or("default"))
|
|
.join(filename);
|
|
|
|
let template_string = proxmox_sys::fs::file_read_optional_string(path)
|
|
.map_err(|err| Error::Generic(format!("could not load template: {err}")))?;
|
|
Ok(template_string)
|
|
}
|
|
}
|
|
|
|
pub static PVE_CONTEXT: PVEContext = PVEContext;
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
const USER_CONFIG: &str = "
|
|
user:root@pam:1:0:::root@example.com:::
|
|
user:test@pve:1:0:::test@example.com:::
|
|
user:no-mail@pve:1:0::::::
|
|
";
|
|
|
|
#[test]
|
|
fn test_parse_mail() {
|
|
assert_eq!(
|
|
lookup_mail_address(USER_CONFIG, "root@pam"),
|
|
Some("root@example.com".to_string())
|
|
);
|
|
assert_eq!(
|
|
lookup_mail_address(USER_CONFIG, "test@pve"),
|
|
Some("test@example.com".to_string())
|
|
);
|
|
assert_eq!(lookup_mail_address(USER_CONFIG, "no-mail@pve"), None);
|
|
}
|
|
|
|
const DC_CONFIG: &str = "
|
|
email_from: user@example.com
|
|
http_proxy: http://localhost:1234
|
|
keyboard: en-us
|
|
";
|
|
#[test]
|
|
fn test_parse_dc_config() {
|
|
assert_eq!(
|
|
common::lookup_datacenter_config_key(DC_CONFIG, "email_from"),
|
|
Some("user@example.com".to_string())
|
|
);
|
|
assert_eq!(
|
|
common::lookup_datacenter_config_key(DC_CONFIG, "http_proxy"),
|
|
Some("http://localhost:1234".to_string())
|
|
);
|
|
assert_eq!(common::lookup_datacenter_config_key(DC_CONFIG, "foo"), None);
|
|
}
|
|
}
|