1 package PVE
::API2
::Cluster
::Notifications
;
6 use Storable
qw(dclone);
9 use PVE
::Tools
qw(extract_param);
10 use PVE
::JSONSchema
qw(get_standard_option);
14 use base
qw(PVE::RESTHandler);
16 sub make_properties_optional
{
17 my ($properties) = @_;
18 $properties = dclone
($properties);
20 for my $key (keys %$properties) {
21 $properties->{$key}->{optional
} = 1 if $key ne 'name';
27 sub remove_protected_properties
{
28 my ($properties, $to_remove) = @_;
29 $properties = dclone
($properties);
31 for my $key (keys %$properties) {
32 if (grep /^$key$/, @$to_remove) {
33 delete $properties->{$key};
43 if (!(ref($api_error) eq 'HASH' && $api_error->{message
} && $api_error->{code
})) {
47 my $msg = "$api_error->{message}\n";
48 my $exc = PVE
::Exception-
>new($msg, code
=> $api_error->{code
});
50 my (undef, $filename, $line) = caller;
52 $exc->{filename
} = $filename;
58 sub filter_entities_by_privs
{
59 my ($rpcenv, $entities) = @_;
60 my $authuser = $rpcenv->get_user();
62 my $can_see_mapping_privs = ['Mapping.Modify', 'Mapping.Use', 'Mapping.Audit'];
64 my $filtered = [grep {
67 "/mapping/notification/$_->{name}",
68 $can_see_mapping_privs,
76 __PACKAGE__-
>register_method ({
80 description
=> 'Index for notification-related API endpoints.',
81 permissions
=> { user
=> 'all' },
83 additionalProperties
=> 0,
92 links
=> [ { rel
=> 'child', href
=> '{name}' } ],
96 { name
=> 'endpoints' },
97 { name
=> 'filters' },
105 __PACKAGE__-
>register_method ({
106 name
=> 'endpoints_index',
109 description
=> 'Index for all available endpoint types.',
110 permissions
=> { user
=> 'all' },
112 additionalProperties
=> 0,
121 links
=> [ { rel
=> 'child', href
=> '{name}' } ],
125 { name
=> 'gotify' },
126 { name
=> 'sendmail' },
133 my $group_properties = {
135 description
=> 'Name of the group.',
137 format
=> 'pve-configid',
143 format
=> 'pve-configid',
145 description
=> 'List of included endpoints',
148 description
=> 'Comment',
153 description
=> 'Name of the filter that should be applied.',
155 format
=> 'pve-configid',
160 __PACKAGE__-
>register_method ({
161 name
=> 'get_groups',
164 description
=> 'Returns a list of all groups',
167 description
=> "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
168 . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.",
172 additionalProperties
=> 0,
179 properties
=> $group_properties,
181 links
=> [ { rel
=> 'child', href
=> '{name}' } ],
184 my $config = PVE
::Notify
::read_config
();
185 my $rpcenv = PVE
::RPCEnvironment
::get
();
187 my $entities = eval {
188 $config->get_groups();
190 raise_api_error
($@) if $@;
192 return filter_entities_by_privs
($rpcenv, $entities);
196 __PACKAGE__-
>register_method ({
198 path
=> 'groups/{name}',
200 description
=> 'Return a specific group',
204 ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
205 ['perm', '/mapping/notification/{name}', ['Mapping.Audit']],
209 additionalProperties
=> 0,
213 format
=> 'pve-configid',
221 digest
=> get_standard_option
('pve-config-digest'),
226 my $name = extract_param
($param, 'name');
228 my $config = PVE
::Notify
::read_config
();
231 $config->get_group($name)
234 raise_api_error
($@) if $@;
235 $group->{digest
} = $config->digest();
241 __PACKAGE__-
>register_method ({
242 name
=> 'create_group',
246 description
=> 'Create a new group',
248 check
=> ['perm', '/mapping/notification', ['Mapping.Modify']],
251 additionalProperties
=> 0,
252 properties
=> $group_properties,
254 returns
=> { type
=> 'null' },
258 my $name = extract_param
($param, 'name');
259 my $endpoint = extract_param
($param, 'endpoint');
260 my $comment = extract_param
($param, 'comment');
261 my $filter = extract_param
($param, 'filter');
264 PVE
::Notify
::lock_config
(sub {
265 my $config = PVE
::Notify
::read_config
();
274 PVE
::Notify
::write_config
($config);
278 raise_api_error
($@) if $@;
283 __PACKAGE__-
>register_method ({
284 name
=> 'update_group',
285 path
=> 'groups/{name}',
288 description
=> 'Update existing group',
290 check
=> ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
293 additionalProperties
=> 0,
295 %{ make_properties_optional
($group_properties) },
300 format
=> 'pve-configid',
303 description
=> 'A list of settings you want to delete.',
305 digest
=> get_standard_option
('pve-config-digest'),
308 returns
=> { type
=> 'null' },
312 my $name = extract_param
($param, 'name');
313 my $endpoint = extract_param
($param, 'endpoint');
314 my $comment = extract_param
($param, 'comment');
315 my $filter = extract_param
($param, 'filter');
316 my $digest = extract_param
($param, 'digest');
317 my $delete = extract_param
($param, 'delete');
320 PVE
::Notify
::lock_config
(sub {
321 my $config = PVE
::Notify
::read_config
();
323 $config->update_group(
332 PVE
::Notify
::write_config
($config);
336 raise_api_error
($@) if $@;
341 __PACKAGE__-
>register_method ({
342 name
=> 'delete_group',
344 path
=> 'groups/{name}',
346 description
=> 'Remove group',
348 check
=> ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
351 additionalProperties
=> 0,
355 format
=> 'pve-configid',
359 returns
=> { type
=> 'null' },
362 my $name = extract_param
($param, 'name');
365 PVE
::Notify
::lock_config
(sub {
366 my $config = PVE
::Notify
::read_config
();
367 $config->delete_group($name);
368 PVE
::Notify
::write_config
($config);
372 raise_api_error
($@) if $@;
377 my $sendmail_properties = {
379 description
=> 'The name of the endpoint.',
381 format
=> 'pve-configid',
387 format
=> 'email-or-username',
389 description
=> 'List of email recipients',
396 format
=> 'pve-userid',
398 description
=> 'List of users',
402 description
=> '`From` address for the mail',
407 description
=> 'Author of the mail',
412 description
=> 'Comment',
417 description
=> 'Name of the filter that should be applied.',
419 format
=> 'pve-configid',
424 __PACKAGE__-
>register_method ({
425 name
=> 'get_sendmail_endpoints',
426 path
=> 'endpoints/sendmail',
428 description
=> 'Returns a list of all sendmail endpoints',
430 description
=> "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
431 . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.",
436 additionalProperties
=> 0,
443 properties
=> $sendmail_properties,
445 links
=> [ { rel
=> 'child', href
=> '{name}' } ],
448 my $config = PVE
::Notify
::read_config
();
449 my $rpcenv = PVE
::RPCEnvironment
::get
();
451 my $entities = eval {
452 $config->get_sendmail_endpoints();
454 raise_api_error
($@) if $@;
456 return filter_entities_by_privs
($rpcenv, $entities);
460 __PACKAGE__-
>register_method ({
461 name
=> 'get_sendmail_endpoint',
462 path
=> 'endpoints/sendmail/{name}',
464 description
=> 'Return a specific sendmail endpoint',
467 ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
468 ['perm', '/mapping/notification/{name}', ['Mapping.Audit']],
473 additionalProperties
=> 0,
477 format
=> 'pve-configid',
484 %$sendmail_properties,
485 digest
=> get_standard_option
('pve-config-digest'),
491 my $name = extract_param
($param, 'name');
493 my $config = PVE
::Notify
::read_config
();
494 my $endpoint = eval {
495 $config->get_sendmail_endpoint($name)
498 raise_api_error
($@) if $@;
499 $endpoint->{digest
} = $config->digest();
505 __PACKAGE__-
>register_method ({
506 name
=> 'create_sendmail_endpoint',
507 path
=> 'endpoints/sendmail',
510 description
=> 'Create a new sendmail endpoint',
512 check
=> ['perm', '/mapping/notification', ['Mapping.Modify']],
515 additionalProperties
=> 0,
516 properties
=> $sendmail_properties,
518 returns
=> { type
=> 'null' },
522 my $name = extract_param
($param, 'name');
523 my $mailto = extract_param
($param, 'mailto');
524 my $mailto_user = extract_param
($param, 'mailto-user');
525 my $from_address = extract_param
($param, 'from-address');
526 my $author = extract_param
($param, 'author');
527 my $comment = extract_param
($param, 'comment');
528 my $filter = extract_param
($param, 'filter');
531 PVE
::Notify
::lock_config
(sub {
532 my $config = PVE
::Notify
::read_config
();
534 $config->add_sendmail_endpoint(
544 PVE
::Notify
::write_config
($config);
548 raise_api_error
($@) if $@;
553 __PACKAGE__-
>register_method ({
554 name
=> 'update_sendmail_endpoint',
555 path
=> 'endpoints/sendmail/{name}',
558 description
=> 'Update existing sendmail endpoint',
560 check
=> ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
563 additionalProperties
=> 0,
565 %{ make_properties_optional
($sendmail_properties) },
570 format
=> 'pve-configid',
573 description
=> 'A list of settings you want to delete.',
575 digest
=> get_standard_option
('pve-config-digest'),
579 returns
=> { type
=> 'null' },
583 my $name = extract_param
($param, 'name');
584 my $mailto = extract_param
($param, 'mailto');
585 my $mailto_user = extract_param
($param, 'mailto-user');
586 my $from_address = extract_param
($param, 'from-address');
587 my $author = extract_param
($param, 'author');
588 my $comment = extract_param
($param, 'comment');
589 my $filter = extract_param
($param, 'filter');
591 my $delete = extract_param
($param, 'delete');
592 my $digest = extract_param
($param, 'digest');
595 PVE
::Notify
::lock_config
(sub {
596 my $config = PVE
::Notify
::read_config
();
598 $config->update_sendmail_endpoint(
610 PVE
::Notify
::write_config
($config);
614 raise_api_error
($@) if $@;
619 __PACKAGE__-
>register_method ({
620 name
=> 'delete_sendmail_endpoint',
622 path
=> 'endpoints/sendmail/{name}',
624 description
=> 'Remove sendmail endpoint',
626 check
=> ['perm', '/mapping/notification', ['Mapping.Modify']],
629 additionalProperties
=> 0,
633 format
=> 'pve-configid',
637 returns
=> { type
=> 'null' },
642 PVE
::Notify
::lock_config
(sub {
643 my $config = PVE
::Notify
::read_config
();
644 $config->delete_sendmail_endpoint($param->{name
});
645 PVE
::Notify
::write_config
($config);
649 raise_api_error
($@) if ($@);
654 my $gotify_properties = {
656 description
=> 'The name of the endpoint.',
658 format
=> 'pve-configid',
661 description
=> 'Server URL',
665 description
=> 'Secret token',
669 description
=> 'Comment',
674 description
=> 'Name of the filter that should be applied.',
676 format
=> 'pve-configid',
681 __PACKAGE__-
>register_method ({
682 name
=> 'get_gotify_endpoints',
683 path
=> 'endpoints/gotify',
685 description
=> 'Returns a list of all gotify endpoints',
688 description
=> "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
689 . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.",
693 additionalProperties
=> 0,
700 properties
=> remove_protected_properties
($gotify_properties, ['token']),
702 links
=> [ { rel
=> 'child', href
=> '{name}' } ],
705 my $config = PVE
::Notify
::read_config
();
706 my $rpcenv = PVE
::RPCEnvironment
::get
();
708 my $entities = eval {
709 $config->get_gotify_endpoints();
711 raise_api_error
($@) if $@;
713 return filter_entities_by_privs
($rpcenv, $entities);
717 __PACKAGE__-
>register_method ({
718 name
=> 'get_gotify_endpoint',
719 path
=> 'endpoints/gotify/{name}',
721 description
=> 'Return a specific gotify endpoint',
725 ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
726 ['perm', '/mapping/notification/{name}', ['Mapping.Audit']],
730 additionalProperties
=> 0,
734 format
=> 'pve-configid',
735 description
=> 'Name of the endpoint.'
742 %{ remove_protected_properties
($gotify_properties, ['token']) },
743 digest
=> get_standard_option
('pve-config-digest'),
748 my $name = extract_param
($param, 'name');
750 my $config = PVE
::Notify
::read_config
();
751 my $endpoint = eval {
752 $config->get_gotify_endpoint($name)
755 raise_api_error
($@) if $@;
756 $endpoint->{digest
} = $config->digest();
762 __PACKAGE__-
>register_method ({
763 name
=> 'create_gotify_endpoint',
764 path
=> 'endpoints/gotify',
767 description
=> 'Create a new gotify endpoint',
769 check
=> ['perm', '/mapping/notification', ['Mapping.Modify']],
772 additionalProperties
=> 0,
773 properties
=> $gotify_properties,
775 returns
=> { type
=> 'null' },
779 my $name = extract_param
($param, 'name');
780 my $server = extract_param
($param, 'server');
781 my $token = extract_param
($param, 'token');
782 my $comment = extract_param
($param, 'comment');
783 my $filter = extract_param
($param, 'filter');
786 PVE
::Notify
::lock_config
(sub {
787 my $config = PVE
::Notify
::read_config
();
789 $config->add_gotify_endpoint(
797 PVE
::Notify
::write_config
($config);
801 raise_api_error
($@) if $@;
806 __PACKAGE__-
>register_method ({
807 name
=> 'update_gotify_endpoint',
808 path
=> 'endpoints/gotify/{name}',
811 description
=> 'Update existing gotify endpoint',
813 check
=> ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
816 additionalProperties
=> 0,
818 %{ make_properties_optional
($gotify_properties) },
823 format
=> 'pve-configid',
826 description
=> 'A list of settings you want to delete.',
828 digest
=> get_standard_option
('pve-config-digest'),
831 returns
=> { type
=> 'null' },
835 my $name = extract_param
($param, 'name');
836 my $server = extract_param
($param, 'server');
837 my $token = extract_param
($param, 'token');
838 my $comment = extract_param
($param, 'comment');
839 my $filter = extract_param
($param, 'filter');
841 my $delete = extract_param
($param, 'delete');
842 my $digest = extract_param
($param, 'digest');
845 PVE
::Notify
::lock_config
(sub {
846 my $config = PVE
::Notify
::read_config
();
848 $config->update_gotify_endpoint(
858 PVE
::Notify
::write_config
($config);
862 raise_api_error
($@) if $@;
867 __PACKAGE__-
>register_method ({
868 name
=> 'delete_gotify_endpoint',
870 path
=> 'endpoints/gotify/{name}',
872 description
=> 'Remove gotify endpoint',
874 check
=> ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
877 additionalProperties
=> 0,
881 format
=> 'pve-configid',
885 returns
=> { type
=> 'null' },
888 my $name = extract_param
($param, 'name');
891 PVE
::Notify
::lock_config
(sub {
892 my $config = PVE
::Notify
::read_config
();
893 $config->delete_gotify_endpoint($name);
894 PVE
::Notify
::write_config
($config);
898 raise_api_error
($@) if $@;
903 my $filter_properties = {
905 description
=> 'Name of the endpoint.',
907 format
=> 'pve-configid',
911 description
=> 'Minimum severity to match',
913 enum
=> [qw(info notice warning error)],
917 description
=> "Choose between 'and' and 'or' for when multiple properties are specified",
919 enum
=> [qw(and or)],
924 description
=> 'Invert match of the whole filter',
928 description
=> 'Comment',
934 __PACKAGE__-
>register_method ({
935 name
=> 'get_filters',
938 description
=> 'Returns a list of all filters',
941 description
=> "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
942 . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.",
946 additionalProperties
=> 0,
953 properties
=> $filter_properties,
955 links
=> [ { rel
=> 'child', href
=> '{name}' } ],
958 my $config = PVE
::Notify
::read_config
();
959 my $rpcenv = PVE
::RPCEnvironment
::get
();
961 my $entities = eval {
962 $config->get_filters();
964 raise_api_error
($@) if $@;
966 return filter_entities_by_privs
($rpcenv, $entities);
970 __PACKAGE__-
>register_method ({
971 name
=> 'get_filter',
972 path
=> 'filters/{name}',
974 description
=> 'Return a specific filter',
978 ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
979 ['perm', '/mapping/notification/{name}', ['Mapping.Audit']],
983 additionalProperties
=> 0,
987 format
=> 'pve-configid',
995 digest
=> get_standard_option
('pve-config-digest'),
1000 my $name = extract_param
($param, 'name');
1002 my $config = PVE
::Notify
::read_config
();
1005 $config->get_filter($name)
1008 raise_api_error
($@) if $@;
1009 $filter->{digest
} = $config->digest();
1015 __PACKAGE__-
>register_method ({
1016 name
=> 'create_filter',
1020 description
=> 'Create a new filter',
1023 check
=> ['perm', '/mapping/notification', ['Mapping.Modify']],
1026 additionalProperties
=> 0,
1027 properties
=> $filter_properties,
1029 returns
=> { type
=> 'null' },
1033 my $name = extract_param
($param, 'name');
1034 my $min_severity = extract_param
($param, 'min-severity');
1035 my $mode = extract_param
($param, 'mode');
1036 my $invert_match = extract_param
($param, 'invert-match');
1037 my $comment = extract_param
($param, 'comment');
1040 PVE
::Notify
::lock_config
(sub {
1041 my $config = PVE
::Notify
::read_config
();
1043 $config->add_filter(
1051 PVE
::Notify
::write_config
($config);
1055 raise_api_error
($@) if $@;
1060 __PACKAGE__-
>register_method ({
1061 name
=> 'update_filter',
1062 path
=> 'filters/{name}',
1065 description
=> 'Update existing filter',
1067 check
=> ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
1070 additionalProperties
=> 0,
1072 %{ make_properties_optional
($filter_properties) },
1077 format
=> 'pve-configid',
1080 description
=> 'A list of settings you want to delete.',
1082 digest
=> get_standard_option
('pve-config-digest'),
1085 returns
=> { type
=> 'null' },
1089 my $name = extract_param
($param, 'name');
1090 my $min_severity = extract_param
($param, 'min-severity');
1091 my $mode = extract_param
($param, 'mode');
1092 my $invert_match = extract_param
($param, 'invert-match');
1093 my $comment = extract_param
($param, 'comment');
1094 my $digest = extract_param
($param, 'digest');
1095 my $delete = extract_param
($param, 'delete');
1098 PVE
::Notify
::lock_config
(sub {
1099 my $config = PVE
::Notify
::read_config
();
1101 $config->update_filter(
1111 PVE
::Notify
::write_config
($config);
1115 raise_api_error
($@) if $@;
1120 __PACKAGE__-
>register_method ({
1121 name
=> 'delete_filter',
1123 path
=> 'filters/{name}',
1125 description
=> 'Remove filter',
1127 check
=> ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
1130 additionalProperties
=> 0,
1134 format
=> 'pve-configid',
1138 returns
=> { type
=> 'null' },
1141 my $name = extract_param
($param, 'name');
1144 PVE
::Notify
::lock_config
(sub {
1145 my $config = PVE
::Notify
::read_config
();
1146 $config->delete_filter($name);
1147 PVE
::Notify
::write_config
($config);
1151 raise_api_error
($@) if $@;