]>
Commit | Line | Data |
---|---|---|
b6fa29f3 LW |
1 | package PVE::API2::Cluster::Notifications; |
2 | ||
3 | use warnings; | |
4 | use strict; | |
5 | ||
6 | use Storable qw(dclone); | |
7 | use JSON; | |
8 | ||
1ba1988d | 9 | use PVE::Exception qw(raise_param_exc); |
b6fa29f3 LW |
10 | use PVE::Tools qw(extract_param); |
11 | use PVE::JSONSchema qw(get_standard_option); | |
12 | use PVE::RESTHandler; | |
13 | use PVE::Notify; | |
14 | ||
15 | use base qw(PVE::RESTHandler); | |
16 | ||
17 | sub make_properties_optional { | |
18 | my ($properties) = @_; | |
19 | $properties = dclone($properties); | |
20 | ||
21 | for my $key (keys %$properties) { | |
22 | $properties->{$key}->{optional} = 1 if $key ne 'name'; | |
23 | } | |
24 | ||
25 | return $properties; | |
26 | } | |
27 | ||
aed4eff9 LW |
28 | sub remove_protected_properties { |
29 | my ($properties, $to_remove) = @_; | |
30 | $properties = dclone($properties); | |
31 | ||
32 | for my $key (keys %$properties) { | |
33 | if (grep /^$key$/, @$to_remove) { | |
34 | delete $properties->{$key}; | |
35 | } | |
36 | } | |
37 | ||
38 | return $properties; | |
39 | } | |
40 | ||
b6fa29f3 LW |
41 | sub raise_api_error { |
42 | my ($api_error) = @_; | |
43 | ||
44 | if (!(ref($api_error) eq 'HASH' && $api_error->{message} && $api_error->{code})) { | |
45 | die $api_error; | |
46 | } | |
47 | ||
48 | my $msg = "$api_error->{message}\n"; | |
49 | my $exc = PVE::Exception->new($msg, code => $api_error->{code}); | |
50 | ||
51 | my (undef, $filename, $line) = caller; | |
52 | ||
53 | $exc->{filename} = $filename; | |
54 | $exc->{line} = $line; | |
55 | ||
56 | die $exc; | |
57 | } | |
58 | ||
95c2dc1b LW |
59 | sub filter_entities_by_privs { |
60 | my ($rpcenv, $entities) = @_; | |
61 | my $authuser = $rpcenv->get_user(); | |
62 | ||
63 | my $can_see_mapping_privs = ['Mapping.Modify', 'Mapping.Use', 'Mapping.Audit']; | |
64 | ||
65 | my $filtered = [grep { | |
66 | $rpcenv->check_any( | |
67 | $authuser, | |
68 | "/mapping/notification/$_->{name}", | |
69 | $can_see_mapping_privs, | |
70 | 1 | |
71 | ) | |
72 | } @$entities]; | |
73 | ||
74 | return $filtered; | |
75 | } | |
76 | ||
1ba1988d LW |
77 | sub target_used_by { |
78 | my ($target) = @_; | |
79 | ||
80 | my $used_by = []; | |
81 | ||
82 | # Check keys in datacenter.cfg | |
83 | my $dc_conf = PVE::Cluster::cfs_read_file('datacenter.cfg'); | |
84 | for my $key (qw(target-package-updates target-replication target-fencing)) { | |
85 | if ($dc_conf->{notify} && $dc_conf->{notify}->{$key} eq $target) { | |
86 | push @$used_by, $key; | |
87 | } | |
88 | } | |
89 | ||
90 | # Check backup jobs | |
91 | my $jobs_conf = PVE::Cluster::cfs_read_file('jobs.cfg'); | |
92 | for my $key (keys %{$jobs_conf->{ids}}) { | |
93 | my $job = $jobs_conf->{ids}->{$key}; | |
94 | if ($job->{'notification-target'} eq $target) { | |
95 | push @$used_by, $key; | |
96 | } | |
97 | } | |
98 | ||
99 | return join(', ', @$used_by); | |
100 | } | |
101 | ||
b6fa29f3 LW |
102 | __PACKAGE__->register_method ({ |
103 | name => 'index', | |
104 | path => '', | |
105 | method => 'GET', | |
106 | description => 'Index for notification-related API endpoints.', | |
107 | permissions => { user => 'all' }, | |
108 | parameters => { | |
109 | additionalProperties => 0, | |
110 | properties => {}, | |
111 | }, | |
112 | returns => { | |
113 | type => 'array', | |
114 | items => { | |
115 | type => 'object', | |
116 | properties => {}, | |
117 | }, | |
118 | links => [ { rel => 'child', href => '{name}' } ], | |
119 | }, | |
120 | code => sub { | |
121 | my $result = [ | |
c2c31251 | 122 | { name => 'endpoints' }, |
56977d48 | 123 | { name => 'filters' }, |
95c2dc1b | 124 | { name => 'groups' }, |
e678a5db | 125 | { name => 'targets' }, |
b6fa29f3 LW |
126 | ]; |
127 | ||
128 | return $result; | |
129 | } | |
130 | }); | |
131 | ||
c2c31251 LW |
132 | __PACKAGE__->register_method ({ |
133 | name => 'endpoints_index', | |
134 | path => 'endpoints', | |
135 | method => 'GET', | |
136 | description => 'Index for all available endpoint types.', | |
137 | permissions => { user => 'all' }, | |
138 | parameters => { | |
139 | additionalProperties => 0, | |
140 | properties => {}, | |
141 | }, | |
142 | returns => { | |
143 | type => 'array', | |
144 | items => { | |
145 | type => 'object', | |
146 | properties => {}, | |
147 | }, | |
148 | links => [ { rel => 'child', href => '{name}' } ], | |
149 | }, | |
150 | code => sub { | |
151 | my $result = [ | |
aed4eff9 | 152 | { name => 'gotify' }, |
c2c31251 LW |
153 | { name => 'sendmail' }, |
154 | ]; | |
155 | ||
156 | return $result; | |
157 | } | |
158 | }); | |
159 | ||
e678a5db LW |
160 | __PACKAGE__->register_method ({ |
161 | name => 'get_all_targets', | |
162 | path => 'targets', | |
163 | method => 'GET', | |
164 | description => 'Returns a list of all entities that can be used as notification targets' . | |
165 | ' (endpoints and groups).', | |
166 | permissions => { | |
167 | description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or" | |
168 | . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.", | |
169 | user => 'all', | |
170 | }, | |
171 | protected => 1, | |
172 | parameters => { | |
173 | additionalProperties => 0, | |
174 | properties => {}, | |
175 | }, | |
176 | returns => { | |
177 | type => 'array', | |
178 | items => { | |
179 | type => 'object', | |
180 | properties => { | |
181 | name => { | |
182 | description => 'Name of the endpoint/group.', | |
183 | type => 'string', | |
184 | format => 'pve-configid', | |
185 | }, | |
186 | 'type' => { | |
187 | description => 'Type of the endpoint or group.', | |
188 | type => 'string', | |
189 | enum => [qw(sendmail gotify group)], | |
190 | }, | |
191 | 'comment' => { | |
192 | description => 'Comment', | |
193 | type => 'string', | |
194 | optional => 1, | |
195 | }, | |
196 | }, | |
197 | }, | |
198 | links => [ { rel => 'child', href => '{name}' } ], | |
199 | }, | |
200 | code => sub { | |
201 | my $config = PVE::Notify::read_config(); | |
202 | my $rpcenv = PVE::RPCEnvironment::get(); | |
203 | ||
204 | my $targets = eval { | |
205 | my $result = []; | |
206 | ||
207 | for my $target (@{$config->get_sendmail_endpoints()}) { | |
208 | push @$result, { | |
209 | name => $target->{name}, | |
210 | comment => $target->{comment}, | |
211 | type => 'sendmail', | |
212 | }; | |
213 | } | |
214 | ||
215 | for my $target (@{$config->get_gotify_endpoints()}) { | |
216 | push @$result, { | |
217 | name => $target->{name}, | |
218 | comment => $target->{comment}, | |
219 | type => 'gotify', | |
220 | }; | |
221 | } | |
222 | ||
223 | for my $target (@{$config->get_groups()}) { | |
224 | push @$result, { | |
225 | name => $target->{name}, | |
226 | comment => $target->{comment}, | |
227 | type => 'group', | |
228 | }; | |
229 | } | |
230 | ||
231 | $result | |
232 | }; | |
233 | ||
234 | raise_api_error($@) if $@; | |
235 | ||
236 | return filter_entities_by_privs($rpcenv, $targets); | |
237 | } | |
238 | }); | |
239 | ||
7e6efd39 LW |
240 | __PACKAGE__->register_method ({ |
241 | name => 'test_target', | |
242 | path => 'targets/{name}/test', | |
243 | protected => 1, | |
244 | method => 'POST', | |
245 | description => 'Send a test notification to a provided target.', | |
246 | permissions => { | |
247 | check => ['or', | |
248 | ['perm', '/mapping/notification/{name}', ['Mapping.Use']], | |
249 | ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
250 | ['perm', '/mapping/notification/{name}', ['Mapping.Audit']], | |
251 | ], | |
252 | }, | |
253 | parameters => { | |
254 | additionalProperties => 0, | |
255 | properties => { | |
256 | name => { | |
257 | description => 'Name of the target.', | |
258 | type => 'string', | |
259 | format => 'pve-configid' | |
260 | }, | |
261 | }, | |
262 | }, | |
263 | returns => { type => 'null' }, | |
264 | code => sub { | |
265 | my ($param) = @_; | |
266 | my $name = extract_param($param, 'name'); | |
267 | ||
268 | my $config = PVE::Notify::read_config(); | |
269 | ||
270 | eval { | |
271 | $config->test_target($name); | |
272 | }; | |
273 | ||
274 | raise_api_error($@) if $@; | |
275 | ||
276 | return; | |
277 | } | |
278 | }); | |
279 | ||
95c2dc1b LW |
280 | my $group_properties = { |
281 | name => { | |
282 | description => 'Name of the group.', | |
283 | type => 'string', | |
284 | format => 'pve-configid', | |
285 | }, | |
286 | 'endpoint' => { | |
287 | type => 'array', | |
288 | items => { | |
289 | type => 'string', | |
290 | format => 'pve-configid', | |
291 | }, | |
292 | description => 'List of included endpoints', | |
293 | }, | |
294 | 'comment' => { | |
295 | description => 'Comment', | |
296 | type => 'string', | |
297 | optional => 1, | |
298 | }, | |
299 | filter => { | |
300 | description => 'Name of the filter that should be applied.', | |
301 | type => 'string', | |
302 | format => 'pve-configid', | |
303 | optional => 1, | |
304 | }, | |
305 | }; | |
306 | ||
307 | __PACKAGE__->register_method ({ | |
308 | name => 'get_groups', | |
309 | path => 'groups', | |
310 | method => 'GET', | |
311 | description => 'Returns a list of all groups', | |
312 | protected => 1, | |
313 | permissions => { | |
314 | description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or" | |
315 | . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.", | |
316 | user => 'all', | |
317 | }, | |
318 | parameters => { | |
319 | additionalProperties => 0, | |
320 | properties => {}, | |
321 | }, | |
322 | returns => { | |
323 | type => 'array', | |
324 | items => { | |
325 | type => 'object', | |
326 | properties => $group_properties, | |
327 | }, | |
328 | links => [ { rel => 'child', href => '{name}' } ], | |
329 | }, | |
330 | code => sub { | |
331 | my $config = PVE::Notify::read_config(); | |
332 | my $rpcenv = PVE::RPCEnvironment::get(); | |
333 | ||
334 | my $entities = eval { | |
335 | $config->get_groups(); | |
336 | }; | |
337 | raise_api_error($@) if $@; | |
338 | ||
339 | return filter_entities_by_privs($rpcenv, $entities); | |
340 | } | |
341 | }); | |
342 | ||
343 | __PACKAGE__->register_method ({ | |
344 | name => 'get_group', | |
345 | path => 'groups/{name}', | |
346 | method => 'GET', | |
347 | description => 'Return a specific group', | |
348 | protected => 1, | |
349 | permissions => { | |
350 | check => ['or', | |
351 | ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
352 | ['perm', '/mapping/notification/{name}', ['Mapping.Audit']], | |
353 | ], | |
354 | }, | |
355 | parameters => { | |
356 | additionalProperties => 0, | |
357 | properties => { | |
358 | name => { | |
359 | type => 'string', | |
360 | format => 'pve-configid', | |
361 | }, | |
362 | } | |
363 | }, | |
364 | returns => { | |
365 | type => 'object', | |
366 | properties => { | |
367 | %$group_properties, | |
368 | digest => get_standard_option('pve-config-digest'), | |
369 | }, | |
370 | }, | |
371 | code => sub { | |
372 | my ($param) = @_; | |
373 | my $name = extract_param($param, 'name'); | |
374 | ||
375 | my $config = PVE::Notify::read_config(); | |
376 | ||
377 | my $group = eval { | |
378 | $config->get_group($name) | |
379 | }; | |
380 | ||
381 | raise_api_error($@) if $@; | |
382 | $group->{digest} = $config->digest(); | |
383 | ||
384 | return $group; | |
385 | } | |
386 | }); | |
387 | ||
388 | __PACKAGE__->register_method ({ | |
389 | name => 'create_group', | |
390 | path => 'groups', | |
391 | protected => 1, | |
392 | method => 'POST', | |
393 | description => 'Create a new group', | |
394 | permissions => { | |
395 | check => ['perm', '/mapping/notification', ['Mapping.Modify']], | |
396 | }, | |
397 | parameters => { | |
398 | additionalProperties => 0, | |
399 | properties => $group_properties, | |
400 | }, | |
401 | returns => { type => 'null' }, | |
402 | code => sub { | |
403 | my ($param) = @_; | |
404 | ||
405 | my $name = extract_param($param, 'name'); | |
406 | my $endpoint = extract_param($param, 'endpoint'); | |
407 | my $comment = extract_param($param, 'comment'); | |
408 | my $filter = extract_param($param, 'filter'); | |
409 | ||
410 | eval { | |
411 | PVE::Notify::lock_config(sub { | |
412 | my $config = PVE::Notify::read_config(); | |
413 | ||
414 | $config->add_group( | |
415 | $name, | |
416 | $endpoint, | |
417 | $comment, | |
418 | $filter, | |
419 | ); | |
420 | ||
421 | PVE::Notify::write_config($config); | |
422 | }); | |
423 | }; | |
424 | ||
425 | raise_api_error($@) if $@; | |
426 | return; | |
427 | } | |
428 | }); | |
429 | ||
430 | __PACKAGE__->register_method ({ | |
431 | name => 'update_group', | |
432 | path => 'groups/{name}', | |
433 | protected => 1, | |
434 | method => 'PUT', | |
435 | description => 'Update existing group', | |
436 | permissions => { | |
437 | check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
438 | }, | |
439 | parameters => { | |
440 | additionalProperties => 0, | |
441 | properties => { | |
442 | %{ make_properties_optional($group_properties) }, | |
443 | delete => { | |
444 | type => 'array', | |
445 | items => { | |
446 | type => 'string', | |
447 | format => 'pve-configid', | |
448 | }, | |
449 | optional => 1, | |
450 | description => 'A list of settings you want to delete.', | |
451 | }, | |
452 | digest => get_standard_option('pve-config-digest'), | |
453 | }, | |
454 | }, | |
455 | returns => { type => 'null' }, | |
456 | code => sub { | |
457 | my ($param) = @_; | |
458 | ||
459 | my $name = extract_param($param, 'name'); | |
460 | my $endpoint = extract_param($param, 'endpoint'); | |
461 | my $comment = extract_param($param, 'comment'); | |
462 | my $filter = extract_param($param, 'filter'); | |
463 | my $digest = extract_param($param, 'digest'); | |
464 | my $delete = extract_param($param, 'delete'); | |
465 | ||
466 | eval { | |
467 | PVE::Notify::lock_config(sub { | |
468 | my $config = PVE::Notify::read_config(); | |
469 | ||
470 | $config->update_group( | |
471 | $name, | |
472 | $endpoint, | |
473 | $comment, | |
474 | $filter, | |
475 | $delete, | |
476 | $digest, | |
477 | ); | |
478 | ||
479 | PVE::Notify::write_config($config); | |
480 | }); | |
481 | }; | |
482 | ||
483 | raise_api_error($@) if $@; | |
484 | return; | |
485 | } | |
486 | }); | |
487 | ||
488 | __PACKAGE__->register_method ({ | |
489 | name => 'delete_group', | |
490 | protected => 1, | |
491 | path => 'groups/{name}', | |
492 | method => 'DELETE', | |
493 | description => 'Remove group', | |
494 | permissions => { | |
495 | check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
496 | }, | |
497 | parameters => { | |
498 | additionalProperties => 0, | |
499 | properties => { | |
500 | name => { | |
501 | type => 'string', | |
502 | format => 'pve-configid', | |
503 | }, | |
504 | } | |
505 | }, | |
506 | returns => { type => 'null' }, | |
507 | code => sub { | |
508 | my ($param) = @_; | |
509 | my $name = extract_param($param, 'name'); | |
510 | ||
1ba1988d LW |
511 | my $used_by = target_used_by($name); |
512 | if ($used_by) { | |
513 | raise_param_exc({'name' => "Cannot remove $name, used by: $used_by"}); | |
514 | } | |
515 | ||
95c2dc1b LW |
516 | eval { |
517 | PVE::Notify::lock_config(sub { | |
518 | my $config = PVE::Notify::read_config(); | |
519 | $config->delete_group($name); | |
520 | PVE::Notify::write_config($config); | |
521 | }); | |
522 | }; | |
523 | ||
524 | raise_api_error($@) if $@; | |
525 | return; | |
526 | } | |
527 | }); | |
528 | ||
c2c31251 LW |
529 | my $sendmail_properties = { |
530 | name => { | |
531 | description => 'The name of the endpoint.', | |
532 | type => 'string', | |
533 | format => 'pve-configid', | |
534 | }, | |
535 | mailto => { | |
536 | type => 'array', | |
537 | items => { | |
538 | type => 'string', | |
539 | format => 'email-or-username', | |
540 | }, | |
541 | description => 'List of email recipients', | |
542 | optional => 1, | |
543 | }, | |
544 | 'mailto-user' => { | |
545 | type => 'array', | |
546 | items => { | |
547 | type => 'string', | |
548 | format => 'pve-userid', | |
549 | }, | |
550 | description => 'List of users', | |
551 | optional => 1, | |
552 | }, | |
553 | 'from-address' => { | |
554 | description => '`From` address for the mail', | |
555 | type => 'string', | |
556 | optional => 1, | |
557 | }, | |
558 | author => { | |
559 | description => 'Author of the mail', | |
560 | type => 'string', | |
561 | optional => 1, | |
562 | }, | |
563 | 'comment' => { | |
564 | description => 'Comment', | |
565 | type => 'string', | |
566 | optional => 1, | |
567 | }, | |
568 | filter => { | |
569 | description => 'Name of the filter that should be applied.', | |
570 | type => 'string', | |
571 | format => 'pve-configid', | |
572 | optional => 1, | |
573 | }, | |
574 | }; | |
575 | ||
576 | __PACKAGE__->register_method ({ | |
577 | name => 'get_sendmail_endpoints', | |
578 | path => 'endpoints/sendmail', | |
579 | method => 'GET', | |
580 | description => 'Returns a list of all sendmail endpoints', | |
581 | permissions => { | |
582 | description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or" | |
583 | . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.", | |
584 | user => 'all', | |
585 | }, | |
586 | protected => 1, | |
587 | parameters => { | |
588 | additionalProperties => 0, | |
589 | properties => {}, | |
590 | }, | |
591 | returns => { | |
592 | type => 'array', | |
593 | items => { | |
594 | type => 'object', | |
595 | properties => $sendmail_properties, | |
596 | }, | |
597 | links => [ { rel => 'child', href => '{name}' } ], | |
598 | }, | |
599 | code => sub { | |
600 | my $config = PVE::Notify::read_config(); | |
601 | my $rpcenv = PVE::RPCEnvironment::get(); | |
602 | ||
603 | my $entities = eval { | |
604 | $config->get_sendmail_endpoints(); | |
605 | }; | |
606 | raise_api_error($@) if $@; | |
607 | ||
608 | return filter_entities_by_privs($rpcenv, $entities); | |
609 | } | |
610 | }); | |
611 | ||
612 | __PACKAGE__->register_method ({ | |
613 | name => 'get_sendmail_endpoint', | |
614 | path => 'endpoints/sendmail/{name}', | |
615 | method => 'GET', | |
616 | description => 'Return a specific sendmail endpoint', | |
617 | permissions => { | |
618 | check => ['or', | |
619 | ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
620 | ['perm', '/mapping/notification/{name}', ['Mapping.Audit']], | |
621 | ], | |
622 | }, | |
623 | protected => 1, | |
624 | parameters => { | |
625 | additionalProperties => 0, | |
626 | properties => { | |
627 | name => { | |
628 | type => 'string', | |
629 | format => 'pve-configid', | |
630 | }, | |
631 | } | |
632 | }, | |
633 | returns => { | |
634 | type => 'object', | |
635 | properties => { | |
636 | %$sendmail_properties, | |
637 | digest => get_standard_option('pve-config-digest'), | |
638 | } | |
639 | ||
640 | }, | |
641 | code => sub { | |
642 | my ($param) = @_; | |
643 | my $name = extract_param($param, 'name'); | |
644 | ||
645 | my $config = PVE::Notify::read_config(); | |
646 | my $endpoint = eval { | |
647 | $config->get_sendmail_endpoint($name) | |
648 | }; | |
649 | ||
650 | raise_api_error($@) if $@; | |
651 | $endpoint->{digest} = $config->digest(); | |
652 | ||
653 | return $endpoint; | |
654 | } | |
655 | }); | |
656 | ||
657 | __PACKAGE__->register_method ({ | |
658 | name => 'create_sendmail_endpoint', | |
659 | path => 'endpoints/sendmail', | |
660 | protected => 1, | |
661 | method => 'POST', | |
662 | description => 'Create a new sendmail endpoint', | |
663 | permissions => { | |
664 | check => ['perm', '/mapping/notification', ['Mapping.Modify']], | |
665 | }, | |
666 | parameters => { | |
667 | additionalProperties => 0, | |
668 | properties => $sendmail_properties, | |
669 | }, | |
670 | returns => { type => 'null' }, | |
671 | code => sub { | |
672 | my ($param) = @_; | |
673 | ||
674 | my $name = extract_param($param, 'name'); | |
675 | my $mailto = extract_param($param, 'mailto'); | |
676 | my $mailto_user = extract_param($param, 'mailto-user'); | |
677 | my $from_address = extract_param($param, 'from-address'); | |
678 | my $author = extract_param($param, 'author'); | |
679 | my $comment = extract_param($param, 'comment'); | |
680 | my $filter = extract_param($param, 'filter'); | |
681 | ||
682 | eval { | |
683 | PVE::Notify::lock_config(sub { | |
684 | my $config = PVE::Notify::read_config(); | |
685 | ||
686 | $config->add_sendmail_endpoint( | |
687 | $name, | |
688 | $mailto, | |
689 | $mailto_user, | |
690 | $from_address, | |
691 | $author, | |
692 | $comment, | |
693 | $filter | |
694 | ); | |
695 | ||
696 | PVE::Notify::write_config($config); | |
697 | }); | |
698 | }; | |
699 | ||
700 | raise_api_error($@) if $@; | |
701 | return; | |
702 | } | |
703 | }); | |
704 | ||
705 | __PACKAGE__->register_method ({ | |
706 | name => 'update_sendmail_endpoint', | |
707 | path => 'endpoints/sendmail/{name}', | |
708 | protected => 1, | |
709 | method => 'PUT', | |
710 | description => 'Update existing sendmail endpoint', | |
711 | permissions => { | |
712 | check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
713 | }, | |
714 | parameters => { | |
715 | additionalProperties => 0, | |
716 | properties => { | |
717 | %{ make_properties_optional($sendmail_properties) }, | |
718 | delete => { | |
719 | type => 'array', | |
720 | items => { | |
721 | type => 'string', | |
722 | format => 'pve-configid', | |
723 | }, | |
724 | optional => 1, | |
725 | description => 'A list of settings you want to delete.', | |
726 | }, | |
727 | digest => get_standard_option('pve-config-digest'), | |
728 | ||
729 | } | |
730 | }, | |
731 | returns => { type => 'null' }, | |
732 | code => sub { | |
733 | my ($param) = @_; | |
734 | ||
735 | my $name = extract_param($param, 'name'); | |
736 | my $mailto = extract_param($param, 'mailto'); | |
737 | my $mailto_user = extract_param($param, 'mailto-user'); | |
738 | my $from_address = extract_param($param, 'from-address'); | |
739 | my $author = extract_param($param, 'author'); | |
740 | my $comment = extract_param($param, 'comment'); | |
741 | my $filter = extract_param($param, 'filter'); | |
742 | ||
743 | my $delete = extract_param($param, 'delete'); | |
744 | my $digest = extract_param($param, 'digest'); | |
745 | ||
746 | eval { | |
747 | PVE::Notify::lock_config(sub { | |
748 | my $config = PVE::Notify::read_config(); | |
749 | ||
750 | $config->update_sendmail_endpoint( | |
751 | $name, | |
752 | $mailto, | |
753 | $mailto_user, | |
754 | $from_address, | |
755 | $author, | |
756 | $comment, | |
757 | $filter, | |
758 | $delete, | |
759 | $digest, | |
760 | ); | |
761 | ||
762 | PVE::Notify::write_config($config); | |
763 | }); | |
764 | }; | |
765 | ||
766 | raise_api_error($@) if $@; | |
767 | return; | |
768 | } | |
769 | }); | |
770 | ||
771 | __PACKAGE__->register_method ({ | |
772 | name => 'delete_sendmail_endpoint', | |
773 | protected => 1, | |
774 | path => 'endpoints/sendmail/{name}', | |
775 | method => 'DELETE', | |
776 | description => 'Remove sendmail endpoint', | |
777 | permissions => { | |
778 | check => ['perm', '/mapping/notification', ['Mapping.Modify']], | |
779 | }, | |
780 | parameters => { | |
781 | additionalProperties => 0, | |
782 | properties => { | |
783 | name => { | |
784 | type => 'string', | |
785 | format => 'pve-configid', | |
786 | }, | |
787 | } | |
788 | }, | |
789 | returns => { type => 'null' }, | |
790 | code => sub { | |
791 | my ($param) = @_; | |
1ba1988d LW |
792 | my $name = extract_param($param, 'name'); |
793 | ||
794 | my $used_by = target_used_by($name); | |
795 | if ($used_by) { | |
796 | raise_param_exc({'name' => "Cannot remove $name, used by: $used_by"}); | |
797 | } | |
c2c31251 LW |
798 | |
799 | eval { | |
800 | PVE::Notify::lock_config(sub { | |
801 | my $config = PVE::Notify::read_config(); | |
1ba1988d | 802 | $config->delete_sendmail_endpoint($name); |
c2c31251 LW |
803 | PVE::Notify::write_config($config); |
804 | }); | |
805 | }; | |
806 | ||
807 | raise_api_error($@) if ($@); | |
808 | return; | |
809 | } | |
810 | }); | |
811 | ||
aed4eff9 LW |
812 | my $gotify_properties = { |
813 | name => { | |
814 | description => 'The name of the endpoint.', | |
815 | type => 'string', | |
816 | format => 'pve-configid', | |
817 | }, | |
818 | 'server' => { | |
819 | description => 'Server URL', | |
820 | type => 'string', | |
821 | }, | |
822 | 'token' => { | |
823 | description => 'Secret token', | |
824 | type => 'string', | |
825 | }, | |
826 | 'comment' => { | |
827 | description => 'Comment', | |
828 | type => 'string', | |
829 | optional => 1, | |
830 | }, | |
831 | 'filter' => { | |
832 | description => 'Name of the filter that should be applied.', | |
833 | type => 'string', | |
834 | format => 'pve-configid', | |
835 | optional => 1, | |
836 | } | |
837 | }; | |
838 | ||
839 | __PACKAGE__->register_method ({ | |
840 | name => 'get_gotify_endpoints', | |
841 | path => 'endpoints/gotify', | |
842 | method => 'GET', | |
843 | description => 'Returns a list of all gotify endpoints', | |
844 | protected => 1, | |
845 | permissions => { | |
846 | description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or" | |
847 | . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.", | |
848 | user => 'all', | |
849 | }, | |
850 | parameters => { | |
851 | additionalProperties => 0, | |
852 | properties => {}, | |
853 | }, | |
854 | returns => { | |
855 | type => 'array', | |
856 | items => { | |
857 | type => 'object', | |
858 | properties => remove_protected_properties($gotify_properties, ['token']), | |
859 | }, | |
860 | links => [ { rel => 'child', href => '{name}' } ], | |
861 | }, | |
862 | code => sub { | |
863 | my $config = PVE::Notify::read_config(); | |
864 | my $rpcenv = PVE::RPCEnvironment::get(); | |
865 | ||
866 | my $entities = eval { | |
867 | $config->get_gotify_endpoints(); | |
868 | }; | |
869 | raise_api_error($@) if $@; | |
870 | ||
871 | return filter_entities_by_privs($rpcenv, $entities); | |
872 | } | |
873 | }); | |
874 | ||
875 | __PACKAGE__->register_method ({ | |
876 | name => 'get_gotify_endpoint', | |
877 | path => 'endpoints/gotify/{name}', | |
878 | method => 'GET', | |
879 | description => 'Return a specific gotify endpoint', | |
880 | protected => 1, | |
881 | permissions => { | |
882 | check => ['or', | |
883 | ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
884 | ['perm', '/mapping/notification/{name}', ['Mapping.Audit']], | |
885 | ], | |
886 | }, | |
887 | parameters => { | |
888 | additionalProperties => 0, | |
889 | properties => { | |
890 | name => { | |
891 | type => 'string', | |
892 | format => 'pve-configid', | |
893 | description => 'Name of the endpoint.' | |
894 | }, | |
895 | } | |
896 | }, | |
897 | returns => { | |
898 | type => 'object', | |
899 | properties => { | |
900 | %{ remove_protected_properties($gotify_properties, ['token']) }, | |
901 | digest => get_standard_option('pve-config-digest'), | |
902 | } | |
903 | }, | |
904 | code => sub { | |
905 | my ($param) = @_; | |
906 | my $name = extract_param($param, 'name'); | |
907 | ||
908 | my $config = PVE::Notify::read_config(); | |
909 | my $endpoint = eval { | |
910 | $config->get_gotify_endpoint($name) | |
911 | }; | |
912 | ||
913 | raise_api_error($@) if $@; | |
914 | $endpoint->{digest} = $config->digest(); | |
915 | ||
916 | return $endpoint; | |
917 | } | |
918 | }); | |
919 | ||
920 | __PACKAGE__->register_method ({ | |
921 | name => 'create_gotify_endpoint', | |
922 | path => 'endpoints/gotify', | |
923 | protected => 1, | |
924 | method => 'POST', | |
925 | description => 'Create a new gotify endpoint', | |
926 | permissions => { | |
927 | check => ['perm', '/mapping/notification', ['Mapping.Modify']], | |
928 | }, | |
929 | parameters => { | |
930 | additionalProperties => 0, | |
931 | properties => $gotify_properties, | |
932 | }, | |
933 | returns => { type => 'null' }, | |
934 | code => sub { | |
935 | my ($param) = @_; | |
936 | ||
937 | my $name = extract_param($param, 'name'); | |
938 | my $server = extract_param($param, 'server'); | |
939 | my $token = extract_param($param, 'token'); | |
940 | my $comment = extract_param($param, 'comment'); | |
941 | my $filter = extract_param($param, 'filter'); | |
942 | ||
943 | eval { | |
944 | PVE::Notify::lock_config(sub { | |
945 | my $config = PVE::Notify::read_config(); | |
946 | ||
947 | $config->add_gotify_endpoint( | |
948 | $name, | |
949 | $server, | |
950 | $token, | |
951 | $comment, | |
952 | $filter | |
953 | ); | |
954 | ||
955 | PVE::Notify::write_config($config); | |
956 | }); | |
957 | }; | |
958 | ||
959 | raise_api_error($@) if $@; | |
960 | return; | |
961 | } | |
962 | }); | |
963 | ||
964 | __PACKAGE__->register_method ({ | |
965 | name => 'update_gotify_endpoint', | |
966 | path => 'endpoints/gotify/{name}', | |
967 | protected => 1, | |
968 | method => 'PUT', | |
969 | description => 'Update existing gotify endpoint', | |
970 | permissions => { | |
971 | check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
972 | }, | |
973 | parameters => { | |
974 | additionalProperties => 0, | |
975 | properties => { | |
976 | %{ make_properties_optional($gotify_properties) }, | |
977 | delete => { | |
978 | type => 'array', | |
979 | items => { | |
980 | type => 'string', | |
981 | format => 'pve-configid', | |
982 | }, | |
983 | optional => 1, | |
984 | description => 'A list of settings you want to delete.', | |
985 | }, | |
986 | digest => get_standard_option('pve-config-digest'), | |
987 | } | |
988 | }, | |
989 | returns => { type => 'null' }, | |
990 | code => sub { | |
991 | my ($param) = @_; | |
992 | ||
993 | my $name = extract_param($param, 'name'); | |
994 | my $server = extract_param($param, 'server'); | |
995 | my $token = extract_param($param, 'token'); | |
996 | my $comment = extract_param($param, 'comment'); | |
997 | my $filter = extract_param($param, 'filter'); | |
998 | ||
999 | my $delete = extract_param($param, 'delete'); | |
1000 | my $digest = extract_param($param, 'digest'); | |
1001 | ||
1002 | eval { | |
1003 | PVE::Notify::lock_config(sub { | |
1004 | my $config = PVE::Notify::read_config(); | |
1005 | ||
1006 | $config->update_gotify_endpoint( | |
1007 | $name, | |
1008 | $server, | |
1009 | $token, | |
1010 | $comment, | |
1011 | $filter, | |
1012 | $delete, | |
1013 | $digest, | |
1014 | ); | |
1015 | ||
1016 | PVE::Notify::write_config($config); | |
1017 | }); | |
1018 | }; | |
1019 | ||
1020 | raise_api_error($@) if $@; | |
1021 | return; | |
1022 | } | |
1023 | }); | |
1024 | ||
1025 | __PACKAGE__->register_method ({ | |
1026 | name => 'delete_gotify_endpoint', | |
1027 | protected => 1, | |
1028 | path => 'endpoints/gotify/{name}', | |
1029 | method => 'DELETE', | |
1030 | description => 'Remove gotify endpoint', | |
1031 | permissions => { | |
1032 | check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
1033 | }, | |
1034 | parameters => { | |
1035 | additionalProperties => 0, | |
1036 | properties => { | |
1037 | name => { | |
1038 | type => 'string', | |
1039 | format => 'pve-configid', | |
1040 | }, | |
1041 | } | |
1042 | }, | |
1043 | returns => { type => 'null' }, | |
1044 | code => sub { | |
1045 | my ($param) = @_; | |
1046 | my $name = extract_param($param, 'name'); | |
1047 | ||
1ba1988d LW |
1048 | my $used_by = target_used_by($name); |
1049 | if ($used_by) { | |
1050 | raise_param_exc({'name' => "Cannot remove $name, used by: $used_by"}); | |
1051 | } | |
1052 | ||
aed4eff9 LW |
1053 | eval { |
1054 | PVE::Notify::lock_config(sub { | |
1055 | my $config = PVE::Notify::read_config(); | |
1056 | $config->delete_gotify_endpoint($name); | |
1057 | PVE::Notify::write_config($config); | |
1058 | }); | |
1059 | }; | |
1060 | ||
1061 | raise_api_error($@) if $@; | |
1062 | return; | |
1063 | } | |
1064 | }); | |
56977d48 LW |
1065 | |
1066 | my $filter_properties = { | |
1067 | name => { | |
1068 | description => 'Name of the endpoint.', | |
1069 | type => 'string', | |
1070 | format => 'pve-configid', | |
1071 | }, | |
1072 | 'min-severity' => { | |
1073 | type => 'string', | |
1074 | description => 'Minimum severity to match', | |
1075 | optional => 1, | |
1076 | enum => [qw(info notice warning error)], | |
1077 | }, | |
1078 | mode => { | |
1079 | type => 'string', | |
1080 | description => "Choose between 'and' and 'or' for when multiple properties are specified", | |
1081 | optional => 1, | |
1082 | enum => [qw(and or)], | |
1083 | default => 'and', | |
1084 | }, | |
1085 | 'invert-match' => { | |
1086 | type => 'boolean', | |
1087 | description => 'Invert match of the whole filter', | |
1088 | optional => 1, | |
1089 | }, | |
1090 | 'comment' => { | |
1091 | description => 'Comment', | |
1092 | type => 'string', | |
1093 | optional => 1, | |
1094 | }, | |
1095 | }; | |
1096 | ||
1097 | __PACKAGE__->register_method ({ | |
1098 | name => 'get_filters', | |
1099 | path => 'filters', | |
1100 | method => 'GET', | |
1101 | description => 'Returns a list of all filters', | |
1102 | protected => 1, | |
1103 | permissions => { | |
1104 | description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or" | |
1105 | . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.", | |
1106 | user => 'all', | |
1107 | }, | |
1108 | parameters => { | |
1109 | additionalProperties => 0, | |
1110 | properties => {}, | |
1111 | }, | |
1112 | returns => { | |
1113 | type => 'array', | |
1114 | items => { | |
1115 | type => 'object', | |
1116 | properties => $filter_properties, | |
1117 | }, | |
1118 | links => [ { rel => 'child', href => '{name}' } ], | |
1119 | }, | |
1120 | code => sub { | |
1121 | my $config = PVE::Notify::read_config(); | |
1122 | my $rpcenv = PVE::RPCEnvironment::get(); | |
1123 | ||
1124 | my $entities = eval { | |
1125 | $config->get_filters(); | |
1126 | }; | |
1127 | raise_api_error($@) if $@; | |
1128 | ||
1129 | return filter_entities_by_privs($rpcenv, $entities); | |
1130 | } | |
1131 | }); | |
1132 | ||
1133 | __PACKAGE__->register_method ({ | |
1134 | name => 'get_filter', | |
1135 | path => 'filters/{name}', | |
1136 | method => 'GET', | |
1137 | description => 'Return a specific filter', | |
1138 | protected => 1, | |
1139 | permissions => { | |
1140 | check => ['or', | |
1141 | ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
1142 | ['perm', '/mapping/notification/{name}', ['Mapping.Audit']], | |
1143 | ], | |
1144 | }, | |
1145 | parameters => { | |
1146 | additionalProperties => 0, | |
1147 | properties => { | |
1148 | name => { | |
1149 | type => 'string', | |
1150 | format => 'pve-configid', | |
1151 | }, | |
1152 | } | |
1153 | }, | |
1154 | returns => { | |
1155 | type => 'object', | |
1156 | properties => { | |
1157 | %$filter_properties, | |
1158 | digest => get_standard_option('pve-config-digest'), | |
1159 | }, | |
1160 | }, | |
1161 | code => sub { | |
1162 | my ($param) = @_; | |
1163 | my $name = extract_param($param, 'name'); | |
1164 | ||
1165 | my $config = PVE::Notify::read_config(); | |
1166 | ||
1167 | my $filter = eval { | |
1168 | $config->get_filter($name) | |
1169 | }; | |
1170 | ||
1171 | raise_api_error($@) if $@; | |
1172 | $filter->{digest} = $config->digest(); | |
1173 | ||
1174 | return $filter; | |
1175 | } | |
1176 | }); | |
1177 | ||
1178 | __PACKAGE__->register_method ({ | |
1179 | name => 'create_filter', | |
1180 | path => 'filters', | |
1181 | protected => 1, | |
1182 | method => 'POST', | |
1183 | description => 'Create a new filter', | |
1184 | protected => 1, | |
1185 | permissions => { | |
1186 | check => ['perm', '/mapping/notification', ['Mapping.Modify']], | |
1187 | }, | |
1188 | parameters => { | |
1189 | additionalProperties => 0, | |
1190 | properties => $filter_properties, | |
1191 | }, | |
1192 | returns => { type => 'null' }, | |
1193 | code => sub { | |
1194 | my ($param) = @_; | |
1195 | ||
1196 | my $name = extract_param($param, 'name'); | |
1197 | my $min_severity = extract_param($param, 'min-severity'); | |
1198 | my $mode = extract_param($param, 'mode'); | |
1199 | my $invert_match = extract_param($param, 'invert-match'); | |
1200 | my $comment = extract_param($param, 'comment'); | |
1201 | ||
1202 | eval { | |
1203 | PVE::Notify::lock_config(sub { | |
1204 | my $config = PVE::Notify::read_config(); | |
1205 | ||
1206 | $config->add_filter( | |
1207 | $name, | |
1208 | $min_severity, | |
1209 | $mode, | |
1210 | $invert_match, | |
1211 | $comment, | |
1212 | ); | |
1213 | ||
1214 | PVE::Notify::write_config($config); | |
1215 | }); | |
1216 | }; | |
1217 | ||
1218 | raise_api_error($@) if $@; | |
1219 | return; | |
1220 | } | |
1221 | }); | |
1222 | ||
1223 | __PACKAGE__->register_method ({ | |
1224 | name => 'update_filter', | |
1225 | path => 'filters/{name}', | |
1226 | protected => 1, | |
1227 | method => 'PUT', | |
1228 | description => 'Update existing filter', | |
1229 | permissions => { | |
1230 | check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
1231 | }, | |
1232 | parameters => { | |
1233 | additionalProperties => 0, | |
1234 | properties => { | |
1235 | %{ make_properties_optional($filter_properties) }, | |
1236 | delete => { | |
1237 | type => 'array', | |
1238 | items => { | |
1239 | type => 'string', | |
1240 | format => 'pve-configid', | |
1241 | }, | |
1242 | optional => 1, | |
1243 | description => 'A list of settings you want to delete.', | |
1244 | }, | |
1245 | digest => get_standard_option('pve-config-digest'), | |
1246 | }, | |
1247 | }, | |
1248 | returns => { type => 'null' }, | |
1249 | code => sub { | |
1250 | my ($param) = @_; | |
1251 | ||
1252 | my $name = extract_param($param, 'name'); | |
1253 | my $min_severity = extract_param($param, 'min-severity'); | |
1254 | my $mode = extract_param($param, 'mode'); | |
1255 | my $invert_match = extract_param($param, 'invert-match'); | |
1256 | my $comment = extract_param($param, 'comment'); | |
1257 | my $digest = extract_param($param, 'digest'); | |
1258 | my $delete = extract_param($param, 'delete'); | |
1259 | ||
1260 | eval { | |
1261 | PVE::Notify::lock_config(sub { | |
1262 | my $config = PVE::Notify::read_config(); | |
1263 | ||
1264 | $config->update_filter( | |
1265 | $name, | |
1266 | $min_severity, | |
1267 | $mode, | |
1268 | $invert_match, | |
1269 | $comment, | |
1270 | $delete, | |
1271 | $digest, | |
1272 | ); | |
1273 | ||
1274 | PVE::Notify::write_config($config); | |
1275 | }); | |
1276 | }; | |
1277 | ||
1278 | raise_api_error($@) if $@; | |
1279 | return; | |
1280 | } | |
1281 | }); | |
1282 | ||
1283 | __PACKAGE__->register_method ({ | |
1284 | name => 'delete_filter', | |
1285 | protected => 1, | |
1286 | path => 'filters/{name}', | |
1287 | method => 'DELETE', | |
1288 | description => 'Remove filter', | |
1289 | permissions => { | |
1290 | check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']], | |
1291 | }, | |
1292 | parameters => { | |
1293 | additionalProperties => 0, | |
1294 | properties => { | |
1295 | name => { | |
1296 | type => 'string', | |
1297 | format => 'pve-configid', | |
1298 | }, | |
1299 | } | |
1300 | }, | |
1301 | returns => { type => 'null' }, | |
1302 | code => sub { | |
1303 | my ($param) = @_; | |
1304 | my $name = extract_param($param, 'name'); | |
1305 | ||
1306 | eval { | |
1307 | PVE::Notify::lock_config(sub { | |
1308 | my $config = PVE::Notify::read_config(); | |
1309 | $config->delete_filter($name); | |
1310 | PVE::Notify::write_config($config); | |
1311 | }); | |
1312 | }; | |
1313 | ||
1314 | raise_api_error($@) if $@; | |
1315 | return; | |
1316 | } | |
1317 | }); | |
1318 | ||
b6fa29f3 | 1319 | 1; |