1 #[perlmod::package(name = "Proxmox::RS::Notify")]
3 use std
::collections
::HashMap
;
6 use anyhow
::{bail, Error}
;
7 use serde_json
::Value
as JSONValue
;
10 use proxmox_http_error
::HttpError
;
11 use proxmox_notify
::endpoints
::gotify
::{
12 DeleteableGotifyProperty
, GotifyConfig
, GotifyConfigUpdater
, GotifyPrivateConfig
,
13 GotifyPrivateConfigUpdater
,
15 use proxmox_notify
::endpoints
::sendmail
::{
16 DeleteableSendmailProperty
, SendmailConfig
, SendmailConfigUpdater
,
18 use proxmox_notify
::endpoints
::smtp
::{
19 DeleteableSmtpProperty
, SmtpConfig
, SmtpConfigUpdater
, SmtpMode
, SmtpPrivateConfig
,
20 SmtpPrivateConfigUpdater
,
22 use proxmox_notify
::matcher
::{
23 CalendarMatcher
, DeleteableMatcherProperty
, FieldMatcher
, MatchModeOperator
, MatcherConfig
,
24 MatcherConfigUpdater
, SeverityMatcher
,
26 use proxmox_notify
::{api, Config, Notification, Severity}
;
28 pub struct NotificationConfig
{
29 config
: Mutex
<Config
>,
32 perlmod
::declare_magic
!(Box
<NotificationConfig
> : &NotificationConfig
as "Proxmox::RS::Notify");
34 /// Support `dclone` so this can be put into the `ccache` of `PVE::Cluster`.
35 #[export(name = "STORABLE_freeze", raw_return)]
37 #[try_from_ref] this: &NotificationConfig,
39 ) -> Result
<Value
, Error
> {
41 bail
!("freezing Notification config not supported!");
44 let mut cloned
= Box
::new(NotificationConfig
{
45 config
: Mutex
::new(this
.config
.lock().unwrap().clone()),
47 let value
= Value
::new_pointer
::<NotificationConfig
>(&mut *cloned
);
48 let _perl
= Box
::leak(cloned
);
52 /// Instead of `thaw` we implement `attach` for `dclone`.
53 #[export(name = "STORABLE_attach", raw_return)]
57 #[raw] serialized: Value,
58 ) -> Result
<Value
, Error
> {
60 bail
!("STORABLE_attach called with cloning=false");
62 let data
= unsafe { Box::from_raw(serialized.pv_raw::<NotificationConfig>()?) }
;
63 Ok(perlmod
::instantiate_magic
!(&class
, MAGIC
=> data
))
70 raw_private_config
: &[u8],
71 ) -> Result
<Value
, Error
> {
72 let raw_config
= std
::str::from_utf8(raw_config
)?
;
73 let raw_private_config
= std
::str::from_utf8(raw_private_config
)?
;
75 Ok(perlmod
::instantiate_magic
!(&class
, MAGIC
=> Box
::new(
77 config
: Mutex
::new(Config
::new(raw_config
, raw_private_config
)?
)
83 fn write_config(#[try_from_ref] this: &NotificationConfig) -> Result<(String, String), Error> {
84 Ok(this
.config
.lock().unwrap().write()?
)
88 fn digest(#[try_from_ref] this: &NotificationConfig) -> String {
89 let config
= this
.config
.lock().unwrap();
90 hex
::encode(config
.digest())
93 #[export(serialize_error)]
95 #[try_from_ref] this: &NotificationConfig,
99 template_data
: Option
<JSONValue
>,
100 fields
: Option
<HashMap
<String
, String
>>,
101 ) -> Result
<(), HttpError
> {
102 let config
= this
.config
.lock().unwrap();
103 let notification
= Notification
::new_templated(
107 template_data
.unwrap_or_default(),
108 fields
.unwrap_or_default(),
111 api
::common
::send(&config
, ¬ification
)
114 #[export(serialize_error)]
116 #[try_from_ref] this: &NotificationConfig,
118 ) -> Result
<(), HttpError
> {
119 let config
= this
.config
.lock().unwrap();
120 api
::common
::test_target(&config
, target
)
123 #[export(serialize_error)]
124 fn get_sendmail_endpoints(
125 #[try_from_ref] this: &NotificationConfig,
126 ) -> Result
<Vec
<SendmailConfig
>, HttpError
> {
127 let config
= this
.config
.lock().unwrap();
128 api
::sendmail
::get_endpoints(&config
)
131 #[export(serialize_error)]
132 fn get_sendmail_endpoint(
133 #[try_from_ref] this: &NotificationConfig,
135 ) -> Result
<SendmailConfig
, HttpError
> {
136 let config
= this
.config
.lock().unwrap();
137 api
::sendmail
::get_endpoint(&config
, id
)
140 #[export(serialize_error)]
141 #[allow(clippy::too_many_arguments)]
142 fn add_sendmail_endpoint(
143 #[try_from_ref] this: &NotificationConfig,
145 mailto
: Option
<Vec
<String
>>,
146 mailto_user
: Option
<Vec
<String
>>,
147 from_address
: Option
<String
>,
148 author
: Option
<String
>,
149 comment
: Option
<String
>,
150 disable
: Option
<bool
>,
151 ) -> Result
<(), HttpError
> {
152 let mut config
= this
.config
.lock().unwrap();
154 api
::sendmail
::add_endpoint(
170 #[export(serialize_error)]
171 #[allow(clippy::too_many_arguments)]
172 fn update_sendmail_endpoint(
173 #[try_from_ref] this: &NotificationConfig,
175 mailto
: Option
<Vec
<String
>>,
176 mailto_user
: Option
<Vec
<String
>>,
177 from_address
: Option
<String
>,
178 author
: Option
<String
>,
179 comment
: Option
<String
>,
180 disable
: Option
<bool
>,
181 delete
: Option
<Vec
<DeleteableSendmailProperty
>>,
182 digest
: Option
<&str>,
183 ) -> Result
<(), HttpError
> {
184 let mut config
= this
.config
.lock().unwrap();
185 let digest
= decode_digest(digest
)?
;
187 api
::sendmail
::update_endpoint(
190 &SendmailConfigUpdater
{
203 #[export(serialize_error)]
204 fn delete_sendmail_endpoint(
205 #[try_from_ref] this: &NotificationConfig,
207 ) -> Result
<(), HttpError
> {
208 let mut config
= this
.config
.lock().unwrap();
209 api
::sendmail
::delete_endpoint(&mut config
, name
)
212 #[export(serialize_error)]
213 fn get_gotify_endpoints(
214 #[try_from_ref] this: &NotificationConfig,
215 ) -> Result
<Vec
<GotifyConfig
>, HttpError
> {
216 let config
= this
.config
.lock().unwrap();
217 api
::gotify
::get_endpoints(&config
)
220 #[export(serialize_error)]
221 fn get_gotify_endpoint(
222 #[try_from_ref] this: &NotificationConfig,
224 ) -> Result
<GotifyConfig
, HttpError
> {
225 let config
= this
.config
.lock().unwrap();
226 api
::gotify
::get_endpoint(&config
, id
)
229 #[export(serialize_error)]
230 fn add_gotify_endpoint(
231 #[try_from_ref] this: &NotificationConfig,
235 comment
: Option
<String
>,
236 disable
: Option
<bool
>,
237 ) -> Result
<(), HttpError
> {
238 let mut config
= this
.config
.lock().unwrap();
239 api
::gotify
::add_endpoint(
249 &GotifyPrivateConfig { name, token }
,
253 #[export(serialize_error)]
254 #[allow(clippy::too_many_arguments)]
255 fn update_gotify_endpoint(
256 #[try_from_ref] this: &NotificationConfig,
258 server
: Option
<String
>,
259 token
: Option
<String
>,
260 comment
: Option
<String
>,
261 disable
: Option
<bool
>,
262 delete
: Option
<Vec
<DeleteableGotifyProperty
>>,
263 digest
: Option
<&str>,
264 ) -> Result
<(), HttpError
> {
265 let mut config
= this
.config
.lock().unwrap();
266 let digest
= decode_digest(digest
)?
;
268 api
::gotify
::update_endpoint(
271 &GotifyConfigUpdater
{
276 &GotifyPrivateConfigUpdater { token }
,
282 #[export(serialize_error)]
283 fn delete_gotify_endpoint(
284 #[try_from_ref] this: &NotificationConfig,
286 ) -> Result
<(), HttpError
> {
287 let mut config
= this
.config
.lock().unwrap();
288 api
::gotify
::delete_gotify_endpoint(&mut config
, name
)
291 #[export(serialize_error)]
292 fn get_smtp_endpoints(
293 #[try_from_ref] this: &NotificationConfig,
294 ) -> Result
<Vec
<SmtpConfig
>, HttpError
> {
295 let config
= this
.config
.lock().unwrap();
296 api
::smtp
::get_endpoints(&config
)
299 #[export(serialize_error)]
300 fn get_smtp_endpoint(
301 #[try_from_ref] this: &NotificationConfig,
303 ) -> Result
<SmtpConfig
, HttpError
> {
304 let config
= this
.config
.lock().unwrap();
305 api
::smtp
::get_endpoint(&config
, id
)
308 #[export(serialize_error)]
309 #[allow(clippy::too_many_arguments)]
310 fn add_smtp_endpoint(
311 #[try_from_ref] this: &NotificationConfig,
315 mode
: Option
<SmtpMode
>,
316 username
: Option
<String
>,
317 password
: Option
<String
>,
318 mailto
: Option
<Vec
<String
>>,
319 mailto_user
: Option
<Vec
<String
>>,
320 from_address
: String
,
321 author
: Option
<String
>,
322 comment
: Option
<String
>,
323 disable
: Option
<bool
>,
324 ) -> Result
<(), HttpError
> {
325 let mut config
= this
.config
.lock().unwrap();
326 api
::smtp
::add_endpoint(
342 &SmtpPrivateConfig { name, password }
,
346 #[export(serialize_error)]
347 #[allow(clippy::too_many_arguments)]
348 fn update_smtp_endpoint(
349 #[try_from_ref] this: &NotificationConfig,
351 server
: Option
<String
>,
353 mode
: Option
<SmtpMode
>,
354 username
: Option
<String
>,
355 password
: Option
<String
>,
356 mailto
: Option
<Vec
<String
>>,
357 mailto_user
: Option
<Vec
<String
>>,
358 from_address
: Option
<String
>,
359 author
: Option
<String
>,
360 comment
: Option
<String
>,
361 disable
: Option
<bool
>,
362 delete
: Option
<Vec
<DeleteableSmtpProperty
>>,
363 digest
: Option
<&str>,
364 ) -> Result
<(), HttpError
> {
365 let mut config
= this
.config
.lock().unwrap();
366 let digest
= decode_digest(digest
)?
;
368 api
::smtp
::update_endpoint(
383 &SmtpPrivateConfigUpdater { password }
,
389 #[export(serialize_error)]
390 fn delete_smtp_endpoint(
391 #[try_from_ref] this: &NotificationConfig,
393 ) -> Result
<(), HttpError
> {
394 let mut config
= this
.config
.lock().unwrap();
395 api
::smtp
::delete_endpoint(&mut config
, name
)
398 #[export(serialize_error)]
400 #[try_from_ref] this: &NotificationConfig,
401 ) -> Result
<Vec
<MatcherConfig
>, HttpError
> {
402 let config
= this
.config
.lock().unwrap();
403 api
::matcher
::get_matchers(&config
)
406 #[export(serialize_error)]
408 #[try_from_ref] this: &NotificationConfig,
410 ) -> Result
<MatcherConfig
, HttpError
> {
411 let config
= this
.config
.lock().unwrap();
412 api
::matcher
::get_matcher(&config
, id
)
415 #[export(serialize_error)]
416 #[allow(clippy::too_many_arguments)]
418 #[try_from_ref] this: &NotificationConfig,
420 target
: Option
<Vec
<String
>>,
421 match_severity
: Option
<Vec
<SeverityMatcher
>>,
422 match_field
: Option
<Vec
<FieldMatcher
>>,
423 match_calendar
: Option
<Vec
<CalendarMatcher
>>,
424 mode
: Option
<MatchModeOperator
>,
425 invert_match
: Option
<bool
>,
426 comment
: Option
<String
>,
427 disable
: Option
<bool
>,
428 ) -> Result
<(), HttpError
> {
429 let mut config
= this
.config
.lock().unwrap();
430 api
::matcher
::add_matcher(
447 #[export(serialize_error)]
448 #[allow(clippy::too_many_arguments)]
450 #[try_from_ref] this: &NotificationConfig,
452 target
: Option
<Vec
<String
>>,
453 match_severity
: Option
<Vec
<SeverityMatcher
>>,
454 match_field
: Option
<Vec
<FieldMatcher
>>,
455 match_calendar
: Option
<Vec
<CalendarMatcher
>>,
456 mode
: Option
<MatchModeOperator
>,
457 invert_match
: Option
<bool
>,
458 comment
: Option
<String
>,
459 disable
: Option
<bool
>,
460 delete
: Option
<Vec
<DeleteableMatcherProperty
>>,
461 digest
: Option
<&str>,
462 ) -> Result
<(), HttpError
> {
463 let mut config
= this
.config
.lock().unwrap();
464 let digest
= decode_digest(digest
)?
;
466 api
::matcher
::update_matcher(
469 &MatcherConfigUpdater
{
484 #[export(serialize_error)]
486 #[try_from_ref] this: &NotificationConfig,
488 ) -> Result
<(), HttpError
> {
489 let mut config
= this
.config
.lock().unwrap();
490 api
::matcher
::delete_matcher(&mut config
, name
)
494 fn get_referenced_entities(
495 #[try_from_ref] this: &NotificationConfig,
497 ) -> Result
<Vec
<String
>, HttpError
> {
498 let config
= this
.config
.lock().unwrap();
499 api
::common
::get_referenced_entities(&config
, name
)
502 fn decode_digest(digest
: Option
<&str>) -> Result
<Option
<Vec
<u8>>, HttpError
> {
506 .map_err(|e
| api
::http_err
!(BAD_REQUEST
, "invalid digest: {e}"))