]> git.proxmox.com Git - pve-manager.git/blame - PVE/API2/Cluster/Notifications.pm
api: notification: disallow removing targets if they are used
[pve-manager.git] / PVE / API2 / Cluster / Notifications.pm
CommitLineData
b6fa29f3
LW
1package PVE::API2::Cluster::Notifications;
2
3use warnings;
4use strict;
5
6use Storable qw(dclone);
7use JSON;
8
1ba1988d 9use PVE::Exception qw(raise_param_exc);
b6fa29f3
LW
10use PVE::Tools qw(extract_param);
11use PVE::JSONSchema qw(get_standard_option);
12use PVE::RESTHandler;
13use PVE::Notify;
14
15use base qw(PVE::RESTHandler);
16
17sub 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
28sub 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
41sub 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
59sub 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
77sub 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
280my $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
529my $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
812my $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
1066my $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 13191;