pve-manager/PVE/API2/Cluster/Notifications.pm
Lukas Wagner 4c40d7cbed api: notification: make the 'mail-to-root' target visible to any user
Since the target does not require Mapping.Use, it should also be
visible and testable by all users.

Short explanation why the 'mail-to-root' is exempt from priv checks:

To ensure backwards compatibility, the 'mail-to-root' target does not
require the `Mapping.Use` privs. This is needed due to the fact that
this target is used as a fallback in case no other target is
configured for an event. For instance, the /node/<name>/apt/update API
call only requires Sys.Modify for the node, but it can also send a
notification. If we were to require Mapping.Use, we could break the
apt/update API compat in the case that a notification shall be sent,
but without any configured notification target (which will then
default to 'mail-to-root').

Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
2023-08-16 11:11:24 +02:00

1333 lines
29 KiB
Perl

package PVE::API2::Cluster::Notifications;
use warnings;
use strict;
use Storable qw(dclone);
use JSON;
use PVE::Exception qw(raise_param_exc);
use PVE::Tools qw(extract_param);
use PVE::JSONSchema qw(get_standard_option);
use PVE::RESTHandler;
use PVE::Notify;
use base qw(PVE::RESTHandler);
sub make_properties_optional {
my ($properties) = @_;
$properties = dclone($properties);
for my $key (keys %$properties) {
$properties->{$key}->{optional} = 1 if $key ne 'name';
}
return $properties;
}
sub remove_protected_properties {
my ($properties, $to_remove) = @_;
$properties = dclone($properties);
for my $key (keys %$properties) {
if (grep /^$key$/, @$to_remove) {
delete $properties->{$key};
}
}
return $properties;
}
sub raise_api_error {
my ($api_error) = @_;
if (!(ref($api_error) eq 'HASH' && $api_error->{message} && $api_error->{code})) {
die $api_error;
}
my $msg = "$api_error->{message}\n";
my $exc = PVE::Exception->new($msg, code => $api_error->{code});
my (undef, $filename, $line) = caller;
$exc->{filename} = $filename;
$exc->{line} = $line;
die $exc;
}
sub filter_entities_by_privs {
my ($rpcenv, $entities) = @_;
my $authuser = $rpcenv->get_user();
my $can_see_mapping_privs = ['Mapping.Modify', 'Mapping.Use', 'Mapping.Audit'];
my $filtered = [grep {
$rpcenv->check_any(
$authuser,
"/mapping/notification/$_->{name}",
$can_see_mapping_privs,
1
) || $_->{name} eq PVE::Notify::default_target();
} @$entities];
return $filtered;
}
sub target_used_by {
my ($target) = @_;
my $used_by = [];
# Check keys in datacenter.cfg
my $dc_conf = PVE::Cluster::cfs_read_file('datacenter.cfg');
for my $key (qw(target-package-updates target-replication target-fencing)) {
if ($dc_conf->{notify} && $dc_conf->{notify}->{$key} eq $target) {
push @$used_by, $key;
}
}
# Check backup jobs
my $jobs_conf = PVE::Cluster::cfs_read_file('jobs.cfg');
for my $key (keys %{$jobs_conf->{ids}}) {
my $job = $jobs_conf->{ids}->{$key};
if ($job->{'notification-target'} eq $target) {
push @$used_by, $key;
}
}
return join(', ', @$used_by);
}
__PACKAGE__->register_method ({
name => 'index',
path => '',
method => 'GET',
description => 'Index for notification-related API endpoints.',
permissions => { user => 'all' },
parameters => {
additionalProperties => 0,
properties => {},
},
returns => {
type => 'array',
items => {
type => 'object',
properties => {},
},
links => [ { rel => 'child', href => '{name}' } ],
},
code => sub {
my $result = [
{ name => 'endpoints' },
{ name => 'filters' },
{ name => 'groups' },
{ name => 'targets' },
];
return $result;
}
});
__PACKAGE__->register_method ({
name => 'endpoints_index',
path => 'endpoints',
method => 'GET',
description => 'Index for all available endpoint types.',
permissions => { user => 'all' },
parameters => {
additionalProperties => 0,
properties => {},
},
returns => {
type => 'array',
items => {
type => 'object',
properties => {},
},
links => [ { rel => 'child', href => '{name}' } ],
},
code => sub {
my $result = [
{ name => 'gotify' },
{ name => 'sendmail' },
];
return $result;
}
});
__PACKAGE__->register_method ({
name => 'get_all_targets',
path => 'targets',
method => 'GET',
description => 'Returns a list of all entities that can be used as notification targets' .
' (endpoints and groups).',
permissions => {
description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
. " 'Mapping.Audit' permissions on '/mapping/notification/<name>'."
. " The special 'mail-to-root' target is available to all users.",
user => 'all',
},
protected => 1,
parameters => {
additionalProperties => 0,
properties => {},
},
returns => {
type => 'array',
items => {
type => 'object',
properties => {
name => {
description => 'Name of the endpoint/group.',
type => 'string',
format => 'pve-configid',
},
'type' => {
description => 'Type of the endpoint or group.',
type => 'string',
enum => [qw(sendmail gotify group)],
},
'comment' => {
description => 'Comment',
type => 'string',
optional => 1,
},
},
},
links => [ { rel => 'child', href => '{name}' } ],
},
code => sub {
my $config = PVE::Notify::read_config();
my $rpcenv = PVE::RPCEnvironment::get();
my $targets = eval {
my $result = [];
for my $target (@{$config->get_sendmail_endpoints()}) {
push @$result, {
name => $target->{name},
comment => $target->{comment},
type => 'sendmail',
};
}
for my $target (@{$config->get_gotify_endpoints()}) {
push @$result, {
name => $target->{name},
comment => $target->{comment},
type => 'gotify',
};
}
for my $target (@{$config->get_groups()}) {
push @$result, {
name => $target->{name},
comment => $target->{comment},
type => 'group',
};
}
$result
};
raise_api_error($@) if $@;
return filter_entities_by_privs($rpcenv, $targets);
}
});
__PACKAGE__->register_method ({
name => 'test_target',
path => 'targets/{name}/test',
protected => 1,
method => 'POST',
description => 'Send a test notification to a provided target.',
permissions => {
description => "The user requires 'Mapping.Modify', 'Mapping.Use' or"
. " 'Mapping.Audit' permissions on '/mapping/notification/<name>'."
. " The special 'mail-to-root' target can be accessed by all users.",
user => 'all',
},
parameters => {
additionalProperties => 0,
properties => {
name => {
description => 'Name of the target.',
type => 'string',
format => 'pve-configid'
},
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $rpcenv = PVE::RPCEnvironment::get();
my $authuser = $rpcenv->get_user();
my $privs = ['Mapping.Modify', 'Mapping.Use', 'Mapping.Audit'];
if ($name ne PVE::Notify::default_target()) {
# Due to backwards compatibility reasons the 'mail-to-root'
# target must be accessible for any user
$rpcenv->check_any(
$authuser,
"/mapping/notification/$name",
$privs,
);
}
eval {
my $config = PVE::Notify::read_config();
$config->test_target($name);
};
raise_api_error($@) if $@;
return;
}
});
my $group_properties = {
name => {
description => 'Name of the group.',
type => 'string',
format => 'pve-configid',
},
'endpoint' => {
type => 'array',
items => {
type => 'string',
format => 'pve-configid',
},
description => 'List of included endpoints',
},
'comment' => {
description => 'Comment',
type => 'string',
optional => 1,
},
filter => {
description => 'Name of the filter that should be applied.',
type => 'string',
format => 'pve-configid',
optional => 1,
},
};
__PACKAGE__->register_method ({
name => 'get_groups',
path => 'groups',
method => 'GET',
description => 'Returns a list of all groups',
protected => 1,
permissions => {
description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
. " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.",
user => 'all',
},
parameters => {
additionalProperties => 0,
properties => {},
},
returns => {
type => 'array',
items => {
type => 'object',
properties => $group_properties,
},
links => [ { rel => 'child', href => '{name}' } ],
},
code => sub {
my $config = PVE::Notify::read_config();
my $rpcenv = PVE::RPCEnvironment::get();
my $entities = eval {
$config->get_groups();
};
raise_api_error($@) if $@;
return filter_entities_by_privs($rpcenv, $entities);
}
});
__PACKAGE__->register_method ({
name => 'get_group',
path => 'groups/{name}',
method => 'GET',
description => 'Return a specific group',
protected => 1,
permissions => {
check => ['or',
['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
['perm', '/mapping/notification/{name}', ['Mapping.Audit']],
],
},
parameters => {
additionalProperties => 0,
properties => {
name => {
type => 'string',
format => 'pve-configid',
},
}
},
returns => {
type => 'object',
properties => {
%$group_properties,
digest => get_standard_option('pve-config-digest'),
},
},
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $config = PVE::Notify::read_config();
my $group = eval {
$config->get_group($name)
};
raise_api_error($@) if $@;
$group->{digest} = $config->digest();
return $group;
}
});
__PACKAGE__->register_method ({
name => 'create_group',
path => 'groups',
protected => 1,
method => 'POST',
description => 'Create a new group',
permissions => {
check => ['perm', '/mapping/notification', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => $group_properties,
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $endpoint = extract_param($param, 'endpoint');
my $comment = extract_param($param, 'comment');
my $filter = extract_param($param, 'filter');
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->add_group(
$name,
$endpoint,
$comment,
$filter,
);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
__PACKAGE__->register_method ({
name => 'update_group',
path => 'groups/{name}',
protected => 1,
method => 'PUT',
description => 'Update existing group',
permissions => {
check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => {
%{ make_properties_optional($group_properties) },
delete => {
type => 'array',
items => {
type => 'string',
format => 'pve-configid',
},
optional => 1,
description => 'A list of settings you want to delete.',
},
digest => get_standard_option('pve-config-digest'),
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $endpoint = extract_param($param, 'endpoint');
my $comment = extract_param($param, 'comment');
my $filter = extract_param($param, 'filter');
my $digest = extract_param($param, 'digest');
my $delete = extract_param($param, 'delete');
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->update_group(
$name,
$endpoint,
$comment,
$filter,
$delete,
$digest,
);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
__PACKAGE__->register_method ({
name => 'delete_group',
protected => 1,
path => 'groups/{name}',
method => 'DELETE',
description => 'Remove group',
permissions => {
check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => {
name => {
type => 'string',
format => 'pve-configid',
},
}
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $used_by = target_used_by($name);
if ($used_by) {
raise_param_exc({'name' => "Cannot remove $name, used by: $used_by"});
}
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->delete_group($name);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
my $sendmail_properties = {
name => {
description => 'The name of the endpoint.',
type => 'string',
format => 'pve-configid',
},
mailto => {
type => 'array',
items => {
type => 'string',
format => 'email-or-username',
},
description => 'List of email recipients',
optional => 1,
},
'mailto-user' => {
type => 'array',
items => {
type => 'string',
format => 'pve-userid',
},
description => 'List of users',
optional => 1,
},
'from-address' => {
description => '`From` address for the mail',
type => 'string',
optional => 1,
},
author => {
description => 'Author of the mail',
type => 'string',
optional => 1,
},
'comment' => {
description => 'Comment',
type => 'string',
optional => 1,
},
filter => {
description => 'Name of the filter that should be applied.',
type => 'string',
format => 'pve-configid',
optional => 1,
},
};
__PACKAGE__->register_method ({
name => 'get_sendmail_endpoints',
path => 'endpoints/sendmail',
method => 'GET',
description => 'Returns a list of all sendmail endpoints',
permissions => {
description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
. " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.",
user => 'all',
},
protected => 1,
parameters => {
additionalProperties => 0,
properties => {},
},
returns => {
type => 'array',
items => {
type => 'object',
properties => $sendmail_properties,
},
links => [ { rel => 'child', href => '{name}' } ],
},
code => sub {
my $config = PVE::Notify::read_config();
my $rpcenv = PVE::RPCEnvironment::get();
my $entities = eval {
$config->get_sendmail_endpoints();
};
raise_api_error($@) if $@;
return filter_entities_by_privs($rpcenv, $entities);
}
});
__PACKAGE__->register_method ({
name => 'get_sendmail_endpoint',
path => 'endpoints/sendmail/{name}',
method => 'GET',
description => 'Return a specific sendmail endpoint',
permissions => {
check => ['or',
['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
['perm', '/mapping/notification/{name}', ['Mapping.Audit']],
],
},
protected => 1,
parameters => {
additionalProperties => 0,
properties => {
name => {
type => 'string',
format => 'pve-configid',
},
}
},
returns => {
type => 'object',
properties => {
%$sendmail_properties,
digest => get_standard_option('pve-config-digest'),
}
},
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $config = PVE::Notify::read_config();
my $endpoint = eval {
$config->get_sendmail_endpoint($name)
};
raise_api_error($@) if $@;
$endpoint->{digest} = $config->digest();
return $endpoint;
}
});
__PACKAGE__->register_method ({
name => 'create_sendmail_endpoint',
path => 'endpoints/sendmail',
protected => 1,
method => 'POST',
description => 'Create a new sendmail endpoint',
permissions => {
check => ['perm', '/mapping/notification', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => $sendmail_properties,
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $mailto = extract_param($param, 'mailto');
my $mailto_user = extract_param($param, 'mailto-user');
my $from_address = extract_param($param, 'from-address');
my $author = extract_param($param, 'author');
my $comment = extract_param($param, 'comment');
my $filter = extract_param($param, 'filter');
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->add_sendmail_endpoint(
$name,
$mailto,
$mailto_user,
$from_address,
$author,
$comment,
$filter
);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
__PACKAGE__->register_method ({
name => 'update_sendmail_endpoint',
path => 'endpoints/sendmail/{name}',
protected => 1,
method => 'PUT',
description => 'Update existing sendmail endpoint',
permissions => {
check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => {
%{ make_properties_optional($sendmail_properties) },
delete => {
type => 'array',
items => {
type => 'string',
format => 'pve-configid',
},
optional => 1,
description => 'A list of settings you want to delete.',
},
digest => get_standard_option('pve-config-digest'),
}
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $mailto = extract_param($param, 'mailto');
my $mailto_user = extract_param($param, 'mailto-user');
my $from_address = extract_param($param, 'from-address');
my $author = extract_param($param, 'author');
my $comment = extract_param($param, 'comment');
my $filter = extract_param($param, 'filter');
my $delete = extract_param($param, 'delete');
my $digest = extract_param($param, 'digest');
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->update_sendmail_endpoint(
$name,
$mailto,
$mailto_user,
$from_address,
$author,
$comment,
$filter,
$delete,
$digest,
);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
__PACKAGE__->register_method ({
name => 'delete_sendmail_endpoint',
protected => 1,
path => 'endpoints/sendmail/{name}',
method => 'DELETE',
description => 'Remove sendmail endpoint',
permissions => {
check => ['perm', '/mapping/notification', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => {
name => {
type => 'string',
format => 'pve-configid',
},
}
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $used_by = target_used_by($name);
if ($used_by) {
raise_param_exc({'name' => "Cannot remove $name, used by: $used_by"});
}
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->delete_sendmail_endpoint($name);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if ($@);
return;
}
});
my $gotify_properties = {
name => {
description => 'The name of the endpoint.',
type => 'string',
format => 'pve-configid',
},
'server' => {
description => 'Server URL',
type => 'string',
},
'token' => {
description => 'Secret token',
type => 'string',
},
'comment' => {
description => 'Comment',
type => 'string',
optional => 1,
},
'filter' => {
description => 'Name of the filter that should be applied.',
type => 'string',
format => 'pve-configid',
optional => 1,
}
};
__PACKAGE__->register_method ({
name => 'get_gotify_endpoints',
path => 'endpoints/gotify',
method => 'GET',
description => 'Returns a list of all gotify endpoints',
protected => 1,
permissions => {
description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
. " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.",
user => 'all',
},
parameters => {
additionalProperties => 0,
properties => {},
},
returns => {
type => 'array',
items => {
type => 'object',
properties => remove_protected_properties($gotify_properties, ['token']),
},
links => [ { rel => 'child', href => '{name}' } ],
},
code => sub {
my $config = PVE::Notify::read_config();
my $rpcenv = PVE::RPCEnvironment::get();
my $entities = eval {
$config->get_gotify_endpoints();
};
raise_api_error($@) if $@;
return filter_entities_by_privs($rpcenv, $entities);
}
});
__PACKAGE__->register_method ({
name => 'get_gotify_endpoint',
path => 'endpoints/gotify/{name}',
method => 'GET',
description => 'Return a specific gotify endpoint',
protected => 1,
permissions => {
check => ['or',
['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
['perm', '/mapping/notification/{name}', ['Mapping.Audit']],
],
},
parameters => {
additionalProperties => 0,
properties => {
name => {
type => 'string',
format => 'pve-configid',
description => 'Name of the endpoint.'
},
}
},
returns => {
type => 'object',
properties => {
%{ remove_protected_properties($gotify_properties, ['token']) },
digest => get_standard_option('pve-config-digest'),
}
},
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $config = PVE::Notify::read_config();
my $endpoint = eval {
$config->get_gotify_endpoint($name)
};
raise_api_error($@) if $@;
$endpoint->{digest} = $config->digest();
return $endpoint;
}
});
__PACKAGE__->register_method ({
name => 'create_gotify_endpoint',
path => 'endpoints/gotify',
protected => 1,
method => 'POST',
description => 'Create a new gotify endpoint',
permissions => {
check => ['perm', '/mapping/notification', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => $gotify_properties,
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $server = extract_param($param, 'server');
my $token = extract_param($param, 'token');
my $comment = extract_param($param, 'comment');
my $filter = extract_param($param, 'filter');
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->add_gotify_endpoint(
$name,
$server,
$token,
$comment,
$filter
);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
__PACKAGE__->register_method ({
name => 'update_gotify_endpoint',
path => 'endpoints/gotify/{name}',
protected => 1,
method => 'PUT',
description => 'Update existing gotify endpoint',
permissions => {
check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => {
%{ make_properties_optional($gotify_properties) },
delete => {
type => 'array',
items => {
type => 'string',
format => 'pve-configid',
},
optional => 1,
description => 'A list of settings you want to delete.',
},
digest => get_standard_option('pve-config-digest'),
}
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $server = extract_param($param, 'server');
my $token = extract_param($param, 'token');
my $comment = extract_param($param, 'comment');
my $filter = extract_param($param, 'filter');
my $delete = extract_param($param, 'delete');
my $digest = extract_param($param, 'digest');
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->update_gotify_endpoint(
$name,
$server,
$token,
$comment,
$filter,
$delete,
$digest,
);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
__PACKAGE__->register_method ({
name => 'delete_gotify_endpoint',
protected => 1,
path => 'endpoints/gotify/{name}',
method => 'DELETE',
description => 'Remove gotify endpoint',
permissions => {
check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => {
name => {
type => 'string',
format => 'pve-configid',
},
}
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $used_by = target_used_by($name);
if ($used_by) {
raise_param_exc({'name' => "Cannot remove $name, used by: $used_by"});
}
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->delete_gotify_endpoint($name);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
my $filter_properties = {
name => {
description => 'Name of the endpoint.',
type => 'string',
format => 'pve-configid',
},
'min-severity' => {
type => 'string',
description => 'Minimum severity to match',
optional => 1,
enum => [qw(info notice warning error)],
},
mode => {
type => 'string',
description => "Choose between 'and' and 'or' for when multiple properties are specified",
optional => 1,
enum => [qw(and or)],
default => 'and',
},
'invert-match' => {
type => 'boolean',
description => 'Invert match of the whole filter',
optional => 1,
},
'comment' => {
description => 'Comment',
type => 'string',
optional => 1,
},
};
__PACKAGE__->register_method ({
name => 'get_filters',
path => 'filters',
method => 'GET',
description => 'Returns a list of all filters',
protected => 1,
permissions => {
description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
. " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.",
user => 'all',
},
parameters => {
additionalProperties => 0,
properties => {},
},
returns => {
type => 'array',
items => {
type => 'object',
properties => $filter_properties,
},
links => [ { rel => 'child', href => '{name}' } ],
},
code => sub {
my $config = PVE::Notify::read_config();
my $rpcenv = PVE::RPCEnvironment::get();
my $entities = eval {
$config->get_filters();
};
raise_api_error($@) if $@;
return filter_entities_by_privs($rpcenv, $entities);
}
});
__PACKAGE__->register_method ({
name => 'get_filter',
path => 'filters/{name}',
method => 'GET',
description => 'Return a specific filter',
protected => 1,
permissions => {
check => ['or',
['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
['perm', '/mapping/notification/{name}', ['Mapping.Audit']],
],
},
parameters => {
additionalProperties => 0,
properties => {
name => {
type => 'string',
format => 'pve-configid',
},
}
},
returns => {
type => 'object',
properties => {
%$filter_properties,
digest => get_standard_option('pve-config-digest'),
},
},
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $config = PVE::Notify::read_config();
my $filter = eval {
$config->get_filter($name)
};
raise_api_error($@) if $@;
$filter->{digest} = $config->digest();
return $filter;
}
});
__PACKAGE__->register_method ({
name => 'create_filter',
path => 'filters',
protected => 1,
method => 'POST',
description => 'Create a new filter',
protected => 1,
permissions => {
check => ['perm', '/mapping/notification', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => $filter_properties,
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $min_severity = extract_param($param, 'min-severity');
my $mode = extract_param($param, 'mode');
my $invert_match = extract_param($param, 'invert-match');
my $comment = extract_param($param, 'comment');
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->add_filter(
$name,
$min_severity,
$mode,
$invert_match,
$comment,
);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
__PACKAGE__->register_method ({
name => 'update_filter',
path => 'filters/{name}',
protected => 1,
method => 'PUT',
description => 'Update existing filter',
permissions => {
check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => {
%{ make_properties_optional($filter_properties) },
delete => {
type => 'array',
items => {
type => 'string',
format => 'pve-configid',
},
optional => 1,
description => 'A list of settings you want to delete.',
},
digest => get_standard_option('pve-config-digest'),
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
my $min_severity = extract_param($param, 'min-severity');
my $mode = extract_param($param, 'mode');
my $invert_match = extract_param($param, 'invert-match');
my $comment = extract_param($param, 'comment');
my $digest = extract_param($param, 'digest');
my $delete = extract_param($param, 'delete');
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->update_filter(
$name,
$min_severity,
$mode,
$invert_match,
$comment,
$delete,
$digest,
);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
__PACKAGE__->register_method ({
name => 'delete_filter',
protected => 1,
path => 'filters/{name}',
method => 'DELETE',
description => 'Remove filter',
permissions => {
check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
},
parameters => {
additionalProperties => 0,
properties => {
name => {
type => 'string',
format => 'pve-configid',
},
}
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
my $name = extract_param($param, 'name');
eval {
PVE::Notify::lock_config(sub {
my $config = PVE::Notify::read_config();
$config->delete_filter($name);
PVE::Notify::write_config($config);
});
};
raise_api_error($@) if $@;
return;
}
});
1;