From 95c2dc1bc9fd78cf9c508e7eb1ec1b097b54d7b2 Mon Sep 17 00:00:00 2001 From: Lukas Wagner Date: Thu, 3 Aug 2023 14:16:57 +0200 Subject: [PATCH] api: notification: add api routes for groups The Perl part of the API methods primarily defines the API schema, checks for any needed priviledges and then calls the actual Rust implementation exposed via perlmod. Any errors returned by the Rust code are translated into PVE::Exception, so that the API call fails with the correct HTTP error code. Signed-off-by: Lukas Wagner --- PVE/API2/Cluster/Notifications.pm | 263 ++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) diff --git a/PVE/API2/Cluster/Notifications.pm b/PVE/API2/Cluster/Notifications.pm index 1efebbc1..55dd650d 100644 --- a/PVE/API2/Cluster/Notifications.pm +++ b/PVE/API2/Cluster/Notifications.pm @@ -42,6 +42,24 @@ sub raise_api_error { 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 + ) + } @$entities]; + + return $filtered; +} + __PACKAGE__->register_method ({ name => 'index', path => '', @@ -62,10 +80,255 @@ __PACKAGE__->register_method ({ }, code => sub { my $result = [ + { name => 'groups' }, ]; return $result; } }); +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/'.", + 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'); + + 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; + } +}); + 1;