]> git.proxmox.com Git - pve-manager.git/blob - PVE/API2/Cluster/Notifications.pm
api: notification: add api routes for sendmail endpoints
[pve-manager.git] / PVE / API2 / Cluster / Notifications.pm
1 package PVE::API2::Cluster::Notifications;
2
3 use warnings;
4 use strict;
5
6 use Storable qw(dclone);
7 use JSON;
8
9 use PVE::Tools qw(extract_param);
10 use PVE::JSONSchema qw(get_standard_option);
11 use PVE::RESTHandler;
12 use PVE::Notify;
13
14 use base qw(PVE::RESTHandler);
15
16 sub make_properties_optional {
17 my ($properties) = @_;
18 $properties = dclone($properties);
19
20 for my $key (keys %$properties) {
21 $properties->{$key}->{optional} = 1 if $key ne 'name';
22 }
23
24 return $properties;
25 }
26
27 sub raise_api_error {
28 my ($api_error) = @_;
29
30 if (!(ref($api_error) eq 'HASH' && $api_error->{message} && $api_error->{code})) {
31 die $api_error;
32 }
33
34 my $msg = "$api_error->{message}\n";
35 my $exc = PVE::Exception->new($msg, code => $api_error->{code});
36
37 my (undef, $filename, $line) = caller;
38
39 $exc->{filename} = $filename;
40 $exc->{line} = $line;
41
42 die $exc;
43 }
44
45 sub filter_entities_by_privs {
46 my ($rpcenv, $entities) = @_;
47 my $authuser = $rpcenv->get_user();
48
49 my $can_see_mapping_privs = ['Mapping.Modify', 'Mapping.Use', 'Mapping.Audit'];
50
51 my $filtered = [grep {
52 $rpcenv->check_any(
53 $authuser,
54 "/mapping/notification/$_->{name}",
55 $can_see_mapping_privs,
56 1
57 )
58 } @$entities];
59
60 return $filtered;
61 }
62
63 __PACKAGE__->register_method ({
64 name => 'index',
65 path => '',
66 method => 'GET',
67 description => 'Index for notification-related API endpoints.',
68 permissions => { user => 'all' },
69 parameters => {
70 additionalProperties => 0,
71 properties => {},
72 },
73 returns => {
74 type => 'array',
75 items => {
76 type => 'object',
77 properties => {},
78 },
79 links => [ { rel => 'child', href => '{name}' } ],
80 },
81 code => sub {
82 my $result = [
83 { name => 'endpoints' },
84 { name => 'groups' },
85 ];
86
87 return $result;
88 }
89 });
90
91 __PACKAGE__->register_method ({
92 name => 'endpoints_index',
93 path => 'endpoints',
94 method => 'GET',
95 description => 'Index for all available endpoint types.',
96 permissions => { user => 'all' },
97 parameters => {
98 additionalProperties => 0,
99 properties => {},
100 },
101 returns => {
102 type => 'array',
103 items => {
104 type => 'object',
105 properties => {},
106 },
107 links => [ { rel => 'child', href => '{name}' } ],
108 },
109 code => sub {
110 my $result = [
111 { name => 'sendmail' },
112 ];
113
114 return $result;
115 }
116 });
117
118 my $group_properties = {
119 name => {
120 description => 'Name of the group.',
121 type => 'string',
122 format => 'pve-configid',
123 },
124 'endpoint' => {
125 type => 'array',
126 items => {
127 type => 'string',
128 format => 'pve-configid',
129 },
130 description => 'List of included endpoints',
131 },
132 'comment' => {
133 description => 'Comment',
134 type => 'string',
135 optional => 1,
136 },
137 filter => {
138 description => 'Name of the filter that should be applied.',
139 type => 'string',
140 format => 'pve-configid',
141 optional => 1,
142 },
143 };
144
145 __PACKAGE__->register_method ({
146 name => 'get_groups',
147 path => 'groups',
148 method => 'GET',
149 description => 'Returns a list of all groups',
150 protected => 1,
151 permissions => {
152 description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
153 . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.",
154 user => 'all',
155 },
156 parameters => {
157 additionalProperties => 0,
158 properties => {},
159 },
160 returns => {
161 type => 'array',
162 items => {
163 type => 'object',
164 properties => $group_properties,
165 },
166 links => [ { rel => 'child', href => '{name}' } ],
167 },
168 code => sub {
169 my $config = PVE::Notify::read_config();
170 my $rpcenv = PVE::RPCEnvironment::get();
171
172 my $entities = eval {
173 $config->get_groups();
174 };
175 raise_api_error($@) if $@;
176
177 return filter_entities_by_privs($rpcenv, $entities);
178 }
179 });
180
181 __PACKAGE__->register_method ({
182 name => 'get_group',
183 path => 'groups/{name}',
184 method => 'GET',
185 description => 'Return a specific group',
186 protected => 1,
187 permissions => {
188 check => ['or',
189 ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
190 ['perm', '/mapping/notification/{name}', ['Mapping.Audit']],
191 ],
192 },
193 parameters => {
194 additionalProperties => 0,
195 properties => {
196 name => {
197 type => 'string',
198 format => 'pve-configid',
199 },
200 }
201 },
202 returns => {
203 type => 'object',
204 properties => {
205 %$group_properties,
206 digest => get_standard_option('pve-config-digest'),
207 },
208 },
209 code => sub {
210 my ($param) = @_;
211 my $name = extract_param($param, 'name');
212
213 my $config = PVE::Notify::read_config();
214
215 my $group = eval {
216 $config->get_group($name)
217 };
218
219 raise_api_error($@) if $@;
220 $group->{digest} = $config->digest();
221
222 return $group;
223 }
224 });
225
226 __PACKAGE__->register_method ({
227 name => 'create_group',
228 path => 'groups',
229 protected => 1,
230 method => 'POST',
231 description => 'Create a new group',
232 permissions => {
233 check => ['perm', '/mapping/notification', ['Mapping.Modify']],
234 },
235 parameters => {
236 additionalProperties => 0,
237 properties => $group_properties,
238 },
239 returns => { type => 'null' },
240 code => sub {
241 my ($param) = @_;
242
243 my $name = extract_param($param, 'name');
244 my $endpoint = extract_param($param, 'endpoint');
245 my $comment = extract_param($param, 'comment');
246 my $filter = extract_param($param, 'filter');
247
248 eval {
249 PVE::Notify::lock_config(sub {
250 my $config = PVE::Notify::read_config();
251
252 $config->add_group(
253 $name,
254 $endpoint,
255 $comment,
256 $filter,
257 );
258
259 PVE::Notify::write_config($config);
260 });
261 };
262
263 raise_api_error($@) if $@;
264 return;
265 }
266 });
267
268 __PACKAGE__->register_method ({
269 name => 'update_group',
270 path => 'groups/{name}',
271 protected => 1,
272 method => 'PUT',
273 description => 'Update existing group',
274 permissions => {
275 check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
276 },
277 parameters => {
278 additionalProperties => 0,
279 properties => {
280 %{ make_properties_optional($group_properties) },
281 delete => {
282 type => 'array',
283 items => {
284 type => 'string',
285 format => 'pve-configid',
286 },
287 optional => 1,
288 description => 'A list of settings you want to delete.',
289 },
290 digest => get_standard_option('pve-config-digest'),
291 },
292 },
293 returns => { type => 'null' },
294 code => sub {
295 my ($param) = @_;
296
297 my $name = extract_param($param, 'name');
298 my $endpoint = extract_param($param, 'endpoint');
299 my $comment = extract_param($param, 'comment');
300 my $filter = extract_param($param, 'filter');
301 my $digest = extract_param($param, 'digest');
302 my $delete = extract_param($param, 'delete');
303
304 eval {
305 PVE::Notify::lock_config(sub {
306 my $config = PVE::Notify::read_config();
307
308 $config->update_group(
309 $name,
310 $endpoint,
311 $comment,
312 $filter,
313 $delete,
314 $digest,
315 );
316
317 PVE::Notify::write_config($config);
318 });
319 };
320
321 raise_api_error($@) if $@;
322 return;
323 }
324 });
325
326 __PACKAGE__->register_method ({
327 name => 'delete_group',
328 protected => 1,
329 path => 'groups/{name}',
330 method => 'DELETE',
331 description => 'Remove group',
332 permissions => {
333 check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
334 },
335 parameters => {
336 additionalProperties => 0,
337 properties => {
338 name => {
339 type => 'string',
340 format => 'pve-configid',
341 },
342 }
343 },
344 returns => { type => 'null' },
345 code => sub {
346 my ($param) = @_;
347 my $name = extract_param($param, 'name');
348
349 eval {
350 PVE::Notify::lock_config(sub {
351 my $config = PVE::Notify::read_config();
352 $config->delete_group($name);
353 PVE::Notify::write_config($config);
354 });
355 };
356
357 raise_api_error($@) if $@;
358 return;
359 }
360 });
361
362 my $sendmail_properties = {
363 name => {
364 description => 'The name of the endpoint.',
365 type => 'string',
366 format => 'pve-configid',
367 },
368 mailto => {
369 type => 'array',
370 items => {
371 type => 'string',
372 format => 'email-or-username',
373 },
374 description => 'List of email recipients',
375 optional => 1,
376 },
377 'mailto-user' => {
378 type => 'array',
379 items => {
380 type => 'string',
381 format => 'pve-userid',
382 },
383 description => 'List of users',
384 optional => 1,
385 },
386 'from-address' => {
387 description => '`From` address for the mail',
388 type => 'string',
389 optional => 1,
390 },
391 author => {
392 description => 'Author of the mail',
393 type => 'string',
394 optional => 1,
395 },
396 'comment' => {
397 description => 'Comment',
398 type => 'string',
399 optional => 1,
400 },
401 filter => {
402 description => 'Name of the filter that should be applied.',
403 type => 'string',
404 format => 'pve-configid',
405 optional => 1,
406 },
407 };
408
409 __PACKAGE__->register_method ({
410 name => 'get_sendmail_endpoints',
411 path => 'endpoints/sendmail',
412 method => 'GET',
413 description => 'Returns a list of all sendmail endpoints',
414 permissions => {
415 description => "Only lists entries where you have 'Mapping.Modify', 'Mapping.Use' or"
416 . " 'Mapping.Audit' permissions on '/mapping/notification/<name>'.",
417 user => 'all',
418 },
419 protected => 1,
420 parameters => {
421 additionalProperties => 0,
422 properties => {},
423 },
424 returns => {
425 type => 'array',
426 items => {
427 type => 'object',
428 properties => $sendmail_properties,
429 },
430 links => [ { rel => 'child', href => '{name}' } ],
431 },
432 code => sub {
433 my $config = PVE::Notify::read_config();
434 my $rpcenv = PVE::RPCEnvironment::get();
435
436 my $entities = eval {
437 $config->get_sendmail_endpoints();
438 };
439 raise_api_error($@) if $@;
440
441 return filter_entities_by_privs($rpcenv, $entities);
442 }
443 });
444
445 __PACKAGE__->register_method ({
446 name => 'get_sendmail_endpoint',
447 path => 'endpoints/sendmail/{name}',
448 method => 'GET',
449 description => 'Return a specific sendmail endpoint',
450 permissions => {
451 check => ['or',
452 ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
453 ['perm', '/mapping/notification/{name}', ['Mapping.Audit']],
454 ],
455 },
456 protected => 1,
457 parameters => {
458 additionalProperties => 0,
459 properties => {
460 name => {
461 type => 'string',
462 format => 'pve-configid',
463 },
464 }
465 },
466 returns => {
467 type => 'object',
468 properties => {
469 %$sendmail_properties,
470 digest => get_standard_option('pve-config-digest'),
471 }
472
473 },
474 code => sub {
475 my ($param) = @_;
476 my $name = extract_param($param, 'name');
477
478 my $config = PVE::Notify::read_config();
479 my $endpoint = eval {
480 $config->get_sendmail_endpoint($name)
481 };
482
483 raise_api_error($@) if $@;
484 $endpoint->{digest} = $config->digest();
485
486 return $endpoint;
487 }
488 });
489
490 __PACKAGE__->register_method ({
491 name => 'create_sendmail_endpoint',
492 path => 'endpoints/sendmail',
493 protected => 1,
494 method => 'POST',
495 description => 'Create a new sendmail endpoint',
496 permissions => {
497 check => ['perm', '/mapping/notification', ['Mapping.Modify']],
498 },
499 parameters => {
500 additionalProperties => 0,
501 properties => $sendmail_properties,
502 },
503 returns => { type => 'null' },
504 code => sub {
505 my ($param) = @_;
506
507 my $name = extract_param($param, 'name');
508 my $mailto = extract_param($param, 'mailto');
509 my $mailto_user = extract_param($param, 'mailto-user');
510 my $from_address = extract_param($param, 'from-address');
511 my $author = extract_param($param, 'author');
512 my $comment = extract_param($param, 'comment');
513 my $filter = extract_param($param, 'filter');
514
515 eval {
516 PVE::Notify::lock_config(sub {
517 my $config = PVE::Notify::read_config();
518
519 $config->add_sendmail_endpoint(
520 $name,
521 $mailto,
522 $mailto_user,
523 $from_address,
524 $author,
525 $comment,
526 $filter
527 );
528
529 PVE::Notify::write_config($config);
530 });
531 };
532
533 raise_api_error($@) if $@;
534 return;
535 }
536 });
537
538 __PACKAGE__->register_method ({
539 name => 'update_sendmail_endpoint',
540 path => 'endpoints/sendmail/{name}',
541 protected => 1,
542 method => 'PUT',
543 description => 'Update existing sendmail endpoint',
544 permissions => {
545 check => ['perm', '/mapping/notification/{name}', ['Mapping.Modify']],
546 },
547 parameters => {
548 additionalProperties => 0,
549 properties => {
550 %{ make_properties_optional($sendmail_properties) },
551 delete => {
552 type => 'array',
553 items => {
554 type => 'string',
555 format => 'pve-configid',
556 },
557 optional => 1,
558 description => 'A list of settings you want to delete.',
559 },
560 digest => get_standard_option('pve-config-digest'),
561
562 }
563 },
564 returns => { type => 'null' },
565 code => sub {
566 my ($param) = @_;
567
568 my $name = extract_param($param, 'name');
569 my $mailto = extract_param($param, 'mailto');
570 my $mailto_user = extract_param($param, 'mailto-user');
571 my $from_address = extract_param($param, 'from-address');
572 my $author = extract_param($param, 'author');
573 my $comment = extract_param($param, 'comment');
574 my $filter = extract_param($param, 'filter');
575
576 my $delete = extract_param($param, 'delete');
577 my $digest = extract_param($param, 'digest');
578
579 eval {
580 PVE::Notify::lock_config(sub {
581 my $config = PVE::Notify::read_config();
582
583 $config->update_sendmail_endpoint(
584 $name,
585 $mailto,
586 $mailto_user,
587 $from_address,
588 $author,
589 $comment,
590 $filter,
591 $delete,
592 $digest,
593 );
594
595 PVE::Notify::write_config($config);
596 });
597 };
598
599 raise_api_error($@) if $@;
600 return;
601 }
602 });
603
604 __PACKAGE__->register_method ({
605 name => 'delete_sendmail_endpoint',
606 protected => 1,
607 path => 'endpoints/sendmail/{name}',
608 method => 'DELETE',
609 description => 'Remove sendmail endpoint',
610 permissions => {
611 check => ['perm', '/mapping/notification', ['Mapping.Modify']],
612 },
613 parameters => {
614 additionalProperties => 0,
615 properties => {
616 name => {
617 type => 'string',
618 format => 'pve-configid',
619 },
620 }
621 },
622 returns => { type => 'null' },
623 code => sub {
624 my ($param) = @_;
625
626 eval {
627 PVE::Notify::lock_config(sub {
628 my $config = PVE::Notify::read_config();
629 $config->delete_sendmail_endpoint($param->{name});
630 PVE::Notify::write_config($config);
631 });
632 };
633
634 raise_api_error($@) if ($@);
635 return;
636 }
637 });
638
639 1;