1 use proxmox_http_error
::HttpError
;
3 use crate::api
::{http_bail, http_err}
;
4 use crate::endpoints
::sendmail
::{
5 DeleteableSendmailProperty
, SendmailConfig
, SendmailConfigUpdater
, SENDMAIL_TYPENAME
,
9 /// Get a list of all sendmail endpoints.
11 /// The caller is responsible for any needed permission checks.
12 /// Returns a list of all sendmail endpoints or a `HttpError` if the config is
13 /// erroneous (`500 Internal server error`).
14 pub fn get_endpoints(config
: &Config
) -> Result
<Vec
<SendmailConfig
>, HttpError
> {
17 .convert_to_typed_array(SENDMAIL_TYPENAME
)
18 .map_err(|e
| http_err
!(NOT_FOUND
, "Could not fetch endpoints: {e}"))
21 /// Get sendmail endpoint with given `name`.
23 /// The caller is responsible for any needed permission checks.
24 /// Returns the endpoint or a `HttpError` if the endpoint was not found (`404 Not found`).
25 pub fn get_endpoint(config
: &Config
, name
: &str) -> Result
<SendmailConfig
, HttpError
> {
28 .lookup(SENDMAIL_TYPENAME
, name
)
29 .map_err(|_
| http_err
!(NOT_FOUND
, "endpoint '{name}' not found"))
32 /// Add a new sendmail endpoint.
34 /// The caller is responsible for any needed permission checks.
35 /// The caller also responsible for locking the configuration files.
36 /// Returns a `HttpError` if:
37 /// - an entity with the same name already exists (`400 Bad request`)
38 /// - the configuration could not be saved (`500 Internal server error`)
39 /// - mailto *and* mailto_user are both set to `None`
40 pub fn add_endpoint(config
: &mut Config
, endpoint
: &SendmailConfig
) -> Result
<(), HttpError
> {
41 super::ensure_unique(config
, &endpoint
.name
)?
;
43 if endpoint
.mailto
.is_none() && endpoint
.mailto_user
.is_none() {
46 "must at least provide one recipient, either in mailto or in mailto-user"
52 .set_data(&endpoint
.name
, SENDMAIL_TYPENAME
, endpoint
)
55 INTERNAL_SERVER_ERROR
,
56 "could not save endpoint '{}': {e}",
62 /// Update existing sendmail endpoint
64 /// The caller is responsible for any needed permission checks.
65 /// The caller also responsible for locking the configuration files.
66 /// Returns a `HttpError` if:
67 /// - the configuration could not be saved (`500 Internal server error`)
68 /// - mailto *and* mailto_user are both set to `None`
69 pub fn update_endpoint(
72 updater
: &SendmailConfigUpdater
,
73 delete
: Option
<&[DeleteableSendmailProperty
]>,
74 digest
: Option
<&[u8]>,
75 ) -> Result
<(), HttpError
> {
76 super::verify_digest(config
, digest
)?
;
78 let mut endpoint
= get_endpoint(config
, name
)?
;
80 if let Some(delete
) = delete
{
81 for deleteable_property
in delete
{
82 match deleteable_property
{
83 DeleteableSendmailProperty
::FromAddress
=> endpoint
.from_address
= None
,
84 DeleteableSendmailProperty
::Author
=> endpoint
.author
= None
,
85 DeleteableSendmailProperty
::Comment
=> endpoint
.comment
= None
,
86 DeleteableSendmailProperty
::Mailto
=> endpoint
.mailto
= None
,
87 DeleteableSendmailProperty
::MailtoUser
=> endpoint
.mailto_user
= None
,
88 DeleteableSendmailProperty
::Disable
=> endpoint
.disable
= None
,
93 if let Some(mailto
) = &updater
.mailto
{
94 endpoint
.mailto
= Some(mailto
.iter().map(String
::from
).collect());
97 if let Some(mailto_user
) = &updater
.mailto_user
{
98 endpoint
.mailto_user
= Some(mailto_user
.iter().map(String
::from
).collect());
101 if let Some(from_address
) = &updater
.from_address
{
102 endpoint
.from_address
= Some(from_address
.into());
105 if let Some(author
) = &updater
.author
{
106 endpoint
.author
= Some(author
.into());
109 if let Some(comment
) = &updater
.comment
{
110 endpoint
.comment
= Some(comment
.into());
113 if let Some(disable
) = &updater
.disable
{
114 endpoint
.disable
= Some(*disable
);
117 if endpoint
.mailto
.is_none() && endpoint
.mailto_user
.is_none() {
120 "must at least provide one recipient, either in mailto or in mailto-user"
126 .set_data(name
, SENDMAIL_TYPENAME
, &endpoint
)
129 INTERNAL_SERVER_ERROR
,
130 "could not save endpoint '{}': {e}",
136 /// Delete existing sendmail endpoint
138 /// The caller is responsible for any needed permission checks.
139 /// The caller also responsible for locking the configuration files.
140 /// Returns a `HttpError` if:
141 /// - an entity with the same name already exists (`400 Bad request`)
142 /// - a referenced filter does not exist (`400 Bad request`)
143 /// - the configuration could not be saved (`500 Internal server error`)
144 pub fn delete_endpoint(config
: &mut Config
, name
: &str) -> Result
<(), HttpError
> {
145 // Check if the endpoint exists
146 let _
= get_endpoint(config
, name
)?
;
147 super::ensure_safe_to_delete(config
, name
)?
;
149 config
.config
.sections
.remove(name
);
154 #[cfg(all(feature = "pve-context", test))]
157 use crate::api
::test_helpers
::*;
159 pub fn add_sendmail_endpoint_for_test(
162 ) -> Result
<(), HttpError
> {
167 mailto
: Some(vec
!["user1@example.com".into()]),
169 from_address
: Some("from@example.com".into()),
170 author
: Some("root".into()),
171 comment
: Some("Comment".into()),
177 assert
!(get_endpoint(config
, name
).is_ok());
182 fn test_sendmail_create() -> Result
<(), HttpError
> {
183 let mut config
= empty_config();
185 add_sendmail_endpoint_for_test(&mut config
, "sendmail-endpoint")?
;
187 // Endpoints must have a unique name
188 assert
!(add_sendmail_endpoint_for_test(&mut config
, "sendmail-endpoint").is_err());
193 fn test_update_not_existing_returns_error() -> Result
<(), HttpError
> {
194 let mut config
= empty_config();
196 assert
!(update_endpoint(&mut config
, "test", &Default
::default(), None
, None
,).is_err());
202 fn test_update_invalid_digest_returns_error() -> Result
<(), HttpError
> {
203 let mut config
= empty_config();
204 add_sendmail_endpoint_for_test(&mut config
, "sendmail-endpoint")?
;
206 assert
!(update_endpoint(
209 &SendmailConfigUpdater
{
210 mailto
: Some(vec
!["user2@example.com".into(), "user3@example.com".into()]),
212 from_address
: Some("root@example.com".into()),
213 author
: Some("newauthor".into()),
214 comment
: Some("new comment".into()),
226 fn test_sendmail_update() -> Result
<(), HttpError
> {
227 let mut config
= empty_config();
228 add_sendmail_endpoint_for_test(&mut config
, "sendmail-endpoint")?
;
230 let digest
= config
.digest
;
235 &SendmailConfigUpdater
{
236 mailto
: Some(vec
!["user2@example.com".into(), "user3@example.com".into()]),
237 mailto_user
: Some(vec
!["root@pam".into()]),
238 from_address
: Some("root@example.com".into()),
239 author
: Some("newauthor".into()),
240 comment
: Some("new comment".into()),
247 let endpoint
= get_endpoint(&config
, "sendmail-endpoint")?
;
252 "user2@example.com".to_string(),
253 "user3@example.com".to_string()
256 assert_eq
!(endpoint
.mailto_user
, Some(vec
!["root@pam".to_string(),]));
257 assert_eq
!(endpoint
.from_address
, Some("root@example.com".to_string()));
258 assert_eq
!(endpoint
.author
, Some("newauthor".to_string()));
259 assert_eq
!(endpoint
.comment
, Some("new comment".to_string()));
261 // Test property deletion
267 DeleteableSendmailProperty
::FromAddress
,
268 DeleteableSendmailProperty
::Author
,
273 let endpoint
= get_endpoint(&config
, "sendmail-endpoint")?
;
275 assert_eq
!(endpoint
.from_address
, None
);
276 assert_eq
!(endpoint
.author
, None
);
282 fn test_sendmail_delete() -> Result
<(), HttpError
> {
283 let mut config
= empty_config();
284 add_sendmail_endpoint_for_test(&mut config
, "sendmail-endpoint")?
;
286 delete_endpoint(&mut config
, "sendmail-endpoint")?
;
287 assert
!(delete_endpoint(&mut config
, "sendmail-endpoint").is_err());