]>
Commit | Line | Data |
---|---|---|
5de9374c DM |
1 | package PMG::API2::Statistics; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use Data::Dumper; | |
15a1e62c | 6 | use JSON; |
0f6b8ccb | 7 | use Time::Local; |
5de9374c DM |
8 | |
9 | use PVE::Tools; | |
10 | use PVE::SafeSyslog; | |
11 | use PVE::INotify; | |
12 | use PVE::Exception qw(raise_param_exc); | |
13 | use PVE::RESTHandler; | |
14 | use PMG::RESTEnvironment; | |
15 | use PVE::JSONSchema qw(get_standard_option); | |
16 | ||
17 | use PMG::Utils; | |
44017d49 | 18 | use PMG::Config; |
5de9374c DM |
19 | use PMG::RuleDB; |
20 | use PMG::Statistic; | |
21 | ||
22 | use base qw(PVE::RESTHandler); | |
23 | ||
24 | __PACKAGE__->register_method ({ | |
25 | name => 'index', | |
26 | path => '', | |
27 | method => 'GET', | |
28 | description => "Directory index.", | |
29 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
30 | parameters => { | |
31 | additionalProperties => 0, | |
d67b777f | 32 | properties => {}, |
5de9374c DM |
33 | }, |
34 | returns => { | |
35 | type => 'array', | |
36 | items => { | |
37 | type => "object", | |
38 | properties => {}, | |
39 | }, | |
40 | links => [ { rel => 'child', href => "{name}" } ], | |
41 | }, | |
42 | code => sub { | |
43 | my ($param) = @_; | |
44 | ||
45 | return [ | |
bcf493af | 46 | { name => "contact" }, |
e89b61c5 | 47 | { name => "detail" }, |
d19c40e0 | 48 | { name => "domains" }, |
5de9374c | 49 | { name => "mail" }, |
6156e4b6 | 50 | { name => "mailcount" }, |
fea9d463 | 51 | { name => "recent" }, |
56e1cb1b | 52 | { name => "recentreceivers" }, |
89891fa2 | 53 | { name => "maildistribution" }, |
67832798 | 54 | { name => "spamscores" }, |
15a1e62c | 55 | { name => "sender" }, |
2719ef94 | 56 | { name => "rblcount" }, |
0ab6dc2a | 57 | { name => "receiver" }, |
d67b777f | 58 | { name => "virus" }, |
5de9374c DM |
59 | ]; |
60 | }}); | |
61 | ||
15a1e62c DM |
62 | my $decode_orderby = sub { |
63 | my ($orderby, $allowed_props) = @_; | |
64 | ||
65 | my $sorters; | |
66 | ||
67 | eval { $sorters = decode_json($orderby); }; | |
68 | if (my $err = $@) { | |
69 | raise_param_exc({ orderby => 'invalid JSON'}); | |
70 | } | |
71 | ||
72 | my $schema = { | |
73 | type => 'array', | |
74 | items => { | |
75 | type => "object", | |
76 | properties => { | |
77 | property => { | |
78 | type => 'string', | |
79 | enum => $allowed_props, | |
80 | }, | |
81 | direction => { | |
82 | type => 'string', | |
83 | enum => ['ASC', 'DESC'], | |
84 | }, | |
85 | }, | |
86 | }, | |
87 | }; | |
88 | ||
89 | PVE::JSONSchema::validate($sorters, $schema, "Parameter 'orderby' verification failed\n"); | |
90 | ||
91 | return $sorters; | |
92 | }; | |
93 | ||
f194ac27 DM |
94 | my $api_properties = { |
95 | orderby => { | |
96 | description => "Remote sorting configuration(JSON, ExtJS compatible).", | |
97 | type => 'string', | |
98 | optional => 1, | |
99 | maxLength => 4096, | |
100 | }, | |
15a1e62c DM |
101 | }; |
102 | ||
f194ac27 DM |
103 | my $default_properties = sub { |
104 | my ($prop) = @_; | |
105 | ||
106 | $prop //= {}; | |
107 | ||
108 | $prop->{starttime} = get_standard_option('pmg-starttime'); | |
109 | $prop->{endtime} = get_standard_option('pmg-endtime'); | |
110 | ||
0f6b8ccb DM |
111 | $prop->{year} = { |
112 | description => "Year. Defaults to current year. You will get statistics for the whole year if you do not specify a month or day.", | |
113 | type => 'integer', | |
114 | minimum => 1900, | |
115 | maximum => 3000, | |
116 | optional => 1, | |
117 | }; | |
118 | ||
119 | $prop->{month} = { | |
120 | description => "Month. You will get statistics for the whole month if you do not specify a day.", | |
121 | type => 'integer', | |
122 | minimum => 1, | |
123 | maximum => 12, | |
124 | optional => 1, | |
125 | }; | |
126 | ||
127 | $prop->{day} = { | |
128 | description => "Day of month. Get statistics for a single day.", | |
129 | type => 'integer', | |
130 | minimum => 1, | |
131 | maximum => 31, | |
132 | optional => 1, | |
133 | }; | |
134 | ||
f194ac27 DM |
135 | return $prop; |
136 | }; | |
137 | ||
138 | my $extract_start_end = sub { | |
139 | my ($param) = @_; | |
140 | ||
0f6b8ccb DM |
141 | my $has_ymd; |
142 | foreach my $k (qw(year month day)) { | |
143 | if (defined($param->{$k})) { | |
144 | $has_ymd = $k; | |
145 | last; | |
146 | } | |
147 | } | |
148 | my $has_se; | |
149 | foreach my $k (qw(starttime endtime)) { | |
150 | if (defined($param->{$k})) { | |
151 | $has_se = $k; | |
152 | last; | |
153 | } | |
154 | } | |
155 | ||
156 | raise_param_exc({ $has_se => "parameter conflicts with parameter '$has_ymd'"}) | |
157 | if $has_se && $has_ymd; | |
158 | ||
159 | my $start; | |
160 | my $end; | |
161 | ||
162 | if ($has_ymd) { | |
163 | my (undef, undef, undef, undef, $month, $year) = localtime(time()); | |
164 | $month += 1; | |
165 | $year = $param->{year} if defined($param->{year}); | |
166 | if (defined($param->{day})) { | |
9bb1fcf1 | 167 | my $day = $param->{day}; |
0f6b8ccb | 168 | $month = $param->{month} if defined($param->{month}); |
9bb1fcf1 DC |
169 | $start = timelocal(0, 0, 0, $day, $month - 1, $year); |
170 | $end = timelocal(59, 59, 23, $day, $month - 1, $year); | |
0f6b8ccb DM |
171 | } elsif (defined($param->{month})) { |
172 | my $month = $param->{month}; | |
173 | if ($month < 12) { | |
174 | $start = timelocal(0, 0, 0, 1, $month - 1, $year); | |
175 | $end = timelocal(0, 0, 0, 1, $month, $year); | |
176 | } else { | |
177 | $start = timelocal(0, 0, 0, 1, 11, $year); | |
178 | $end = timelocal(0, 0, 0, 1, 0, $year + 1); | |
179 | } | |
180 | } else { | |
181 | $start = timelocal(0, 0, 0, 1, 0, $year); | |
182 | $end = timelocal(0, 0, 0, 1, 0, $year + 1); | |
183 | } | |
184 | } else { | |
185 | $start = $param->{starttime} // (time - 86400); | |
186 | $end = $param->{endtime} // ($start + 86400); | |
187 | } | |
f194ac27 DM |
188 | |
189 | return ($start, $end); | |
190 | }; | |
15a1e62c | 191 | |
f194ac27 | 192 | my $userstat_limit = 2000; # hardcoded limit |
bcf493af DM |
193 | |
194 | __PACKAGE__->register_method ({ | |
195 | name => 'contact', | |
196 | path => 'contact', | |
197 | method => 'GET', | |
198 | description => "Contact Address Statistics.", | |
199 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
200 | parameters => { | |
201 | additionalProperties => 0, | |
f194ac27 | 202 | properties => $default_properties->({ |
bcf493af DM |
203 | filter => { |
204 | description => "Contact address filter.", | |
205 | type => 'string', | |
206 | maxLength => 512, | |
207 | optional => 1, | |
208 | }, | |
f194ac27 DM |
209 | orderby => $api_properties->{orderby}, |
210 | }), | |
bcf493af DM |
211 | }, |
212 | returns => { | |
213 | type => 'array', | |
214 | items => { | |
215 | type => "object", | |
216 | properties => { | |
217 | contact => { | |
218 | description => "Contact email.", | |
219 | type => 'string', | |
220 | }, | |
221 | count => { | |
222 | description => "Mail count.", | |
223 | type => 'number', | |
224 | optional => 1, | |
225 | }, | |
226 | bytes => { | |
227 | description => "Mail traffic (Bytes).", | |
228 | type => 'number', | |
229 | }, | |
230 | viruscount => { | |
231 | description => "Number of sent virus mails.", | |
232 | type => 'number', | |
233 | optional => 1, | |
234 | }, | |
235 | }, | |
236 | }, | |
237 | links => [ { rel => 'child', href => "{contact}" } ], | |
238 | }, | |
239 | code => sub { | |
240 | my ($param) = @_; | |
241 | ||
f194ac27 | 242 | my ($start, $end) = $extract_start_end->($param); |
bcf493af | 243 | |
44017d49 DM |
244 | my $cfg = PMG::Config->new(); |
245 | my $advfilter = $cfg->get('admin', 'advfilter'); | |
246 | ||
bcf493af DM |
247 | my $stat = PMG::Statistic->new($start, $end); |
248 | my $rdb = PMG::RuleDB->new(); | |
249 | ||
250 | my $sorters = []; | |
251 | if ($param->{orderby}) { | |
252 | my $props = ['contact', 'count', 'bytes', 'viruscount']; | |
253 | $sorters = $decode_orderby->($param->{orderby}, $props); | |
254 | } | |
255 | ||
44017d49 | 256 | my $res = $stat->user_stat_contact($rdb, $userstat_limit, $sorters, $param->{filter}, $advfilter); |
bcf493af DM |
257 | |
258 | return $res; | |
259 | }}); | |
260 | ||
5522af5f SI |
261 | my $detail_return_properties = sub { |
262 | my ($prop) = @_; | |
263 | ||
264 | $prop //= {}; | |
265 | ||
266 | $prop->{time} = { | |
267 | description => "Receive time stamp", | |
268 | type => 'integer', | |
269 | }; | |
270 | ||
271 | $prop->{bytes} = { | |
272 | description => "Mail traffic (Bytes).", | |
273 | type => 'number', | |
274 | }; | |
275 | ||
276 | $prop->{blocked} = { | |
277 | description => "Mail was blocked.", | |
278 | type => 'boolean', | |
279 | }; | |
280 | ||
281 | $prop->{spamlevel} = { | |
282 | description => "Spam score.", | |
283 | type => 'number', | |
284 | }; | |
285 | ||
286 | $prop->{virusinfo} = { | |
287 | description => "Virus name.", | |
288 | type => 'string', | |
289 | optional => 1, | |
290 | }; | |
291 | ||
292 | return $prop; | |
293 | }; | |
294 | ||
d865dfba | 295 | sub get_detail_statistics { |
6500e09b | 296 | my ($type, $param) = @_; |
d865dfba SI |
297 | |
298 | my ($start, $end) = $extract_start_end->($param); | |
d865dfba SI |
299 | my $sorters = []; |
300 | if ($param->{orderby}) { | |
301 | my $props = ['time', 'sender', 'bytes', 'blocked', 'spamlevel', 'virusinfo']; | |
302 | $props->[1] = 'receiver' if $type eq 'sender'; | |
303 | $sorters = $decode_orderby->($param->{orderby}, $props); | |
304 | } | |
6500e09b TL |
305 | my $address = $param->{address} // $param->{$type}; |
306 | my $rdb = PMG::RuleDB->new(); | |
307 | ||
308 | my @args = ($rdb, $address, $userstat_limit, $sorters, $param->{filter}); | |
d865dfba | 309 | |
6500e09b | 310 | my $stat = PMG::Statistic->new($start, $end); |
d865dfba | 311 | if ($type eq 'contact') { |
6500e09b | 312 | return $stat->user_stat_contact_details(@args); |
d865dfba | 313 | } elsif ($type eq 'sender') { |
6500e09b | 314 | return $stat->user_stat_sender_details(@args); |
d865dfba | 315 | } elsif ($type eq 'receiver') { |
6500e09b | 316 | return $stat->user_stat_receiver_details(@args); |
d865dfba SI |
317 | } else { |
318 | die "invalid type provided (not 'contact', 'sender', 'receiver')\n"; | |
319 | } | |
d865dfba SI |
320 | } |
321 | ||
e89b61c5 SI |
322 | __PACKAGE__->register_method ({ |
323 | name => 'detailstats', | |
324 | path => 'detail', | |
325 | method => 'GET', | |
326 | description => "Detailed Statistics.", | |
327 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
328 | parameters => { | |
329 | additionalProperties => 0, | |
330 | properties => $default_properties->({ | |
331 | type => { | |
332 | description => "Type of statistics", | |
333 | type => 'string', | |
334 | enum => [ 'contact', 'sender', 'receiver' ], | |
335 | }, | |
336 | address => get_standard_option('pmg-email-address', { | |
337 | description => "Email address.", | |
338 | }), | |
339 | filter => { | |
340 | description => "Address filter.", | |
341 | type => 'string', | |
342 | maxLength => 512, | |
343 | optional => 1, | |
344 | }, | |
345 | orderby => $api_properties->{orderby}, | |
346 | }), | |
347 | }, | |
348 | returns => { | |
349 | type => 'array', | |
350 | items => { | |
351 | type => "object", | |
352 | properties => $detail_return_properties->({ | |
353 | sender => { | |
354 | description => "Sender email. (for contact and receiver statistics)", | |
355 | type => 'string', | |
356 | optional => 1, | |
357 | }, | |
358 | receiver => { | |
359 | description => "Receiver email. (for sender statistics)", | |
360 | type => 'string', | |
361 | optional => 1, | |
362 | }, | |
363 | }), | |
364 | }, | |
365 | }, | |
366 | code => sub { | |
367 | my ($param) = @_; | |
368 | ||
e89b61c5 SI |
369 | return get_detail_statistics($param->{type}, $param); |
370 | }}); | |
371 | ||
372 | # FIXME: remove for PMG 7.0 - handled by 'details' API call which allows addresses containing '/' | |
bcf493af DM |
373 | __PACKAGE__->register_method ({ |
374 | name => 'contactdetails', | |
375 | path => 'contact/{contact}', | |
376 | method => 'GET', | |
377 | description => "Detailed Contact Statistics.", | |
378 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
379 | parameters => { | |
380 | additionalProperties => 0, | |
f194ac27 | 381 | properties => $default_properties->({ |
bcf493af DM |
382 | contact => get_standard_option('pmg-email-address', { |
383 | description => "Contact email address.", | |
384 | }), | |
385 | filter => { | |
386 | description => "Sender address filter.", | |
387 | type => 'string', | |
388 | maxLength => 512, | |
389 | optional => 1, | |
390 | }, | |
f194ac27 DM |
391 | orderby => $api_properties->{orderby}, |
392 | }), | |
bcf493af DM |
393 | }, |
394 | returns => { | |
395 | type => 'array', | |
396 | items => { | |
397 | type => "object", | |
5522af5f | 398 | properties => $detail_return_properties->({ |
bcf493af DM |
399 | sender => { |
400 | description => "Sender email.", | |
401 | type => 'string', | |
402 | }, | |
5522af5f | 403 | }), |
bcf493af DM |
404 | }, |
405 | }, | |
406 | code => sub { | |
407 | my ($param) = @_; | |
408 | ||
d865dfba | 409 | return get_detail_statistics('contact', $param); |
bcf493af DM |
410 | }}); |
411 | ||
15a1e62c DM |
412 | __PACKAGE__->register_method ({ |
413 | name => 'sender', | |
414 | path => 'sender', | |
415 | method => 'GET', | |
416 | description => "Sender Address Statistics.", | |
417 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
418 | parameters => { | |
419 | additionalProperties => 0, | |
f194ac27 | 420 | properties => $default_properties->({ |
15a1e62c DM |
421 | filter => { |
422 | description => "Sender address filter.", | |
423 | type => 'string', | |
424 | maxLength => 512, | |
425 | optional => 1, | |
426 | }, | |
f194ac27 DM |
427 | orderby => $api_properties->{orderby}, |
428 | }), | |
15a1e62c DM |
429 | }, |
430 | returns => { | |
431 | type => 'array', | |
432 | items => { | |
433 | type => "object", | |
434 | properties => { | |
435 | sender => { | |
436 | description => "Sender email.", | |
437 | type => 'string', | |
438 | }, | |
439 | count => { | |
440 | description => "Mail count.", | |
441 | type => 'number', | |
442 | optional => 1, | |
443 | }, | |
444 | bytes => { | |
445 | description => "Mail traffic (Bytes).", | |
446 | type => 'number', | |
447 | }, | |
448 | viruscount => { | |
449 | description => "Number of sent virus mails.", | |
450 | type => 'number', | |
451 | optional => 1, | |
452 | }, | |
453 | }, | |
454 | }, | |
455 | links => [ { rel => 'child', href => "{sender}" } ], | |
456 | }, | |
457 | code => sub { | |
458 | my ($param) = @_; | |
459 | ||
f194ac27 | 460 | my ($start, $end) = $extract_start_end->($param); |
15a1e62c DM |
461 | |
462 | my $stat = PMG::Statistic->new($start, $end); | |
463 | my $rdb = PMG::RuleDB->new(); | |
464 | ||
465 | my $sorters = []; | |
466 | if ($param->{orderby}) { | |
467 | my $props = ['sender', 'count', 'bytes', 'viruscount']; | |
468 | $sorters = $decode_orderby->($param->{orderby}, $props); | |
469 | } | |
470 | ||
471 | my $res = $stat->user_stat_sender($rdb, $userstat_limit, $sorters, $param->{filter}); | |
472 | ||
473 | return $res; | |
474 | }}); | |
475 | ||
e89b61c5 | 476 | # FIXME: remove for PMG 7.0 - handled by 'details' API call which allows addresses containing '/' |
15a1e62c DM |
477 | __PACKAGE__->register_method ({ |
478 | name => 'senderdetails', | |
479 | path => 'sender/{sender}', | |
480 | method => 'GET', | |
481 | description => "Detailed Sender Statistics.", | |
482 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
483 | parameters => { | |
484 | additionalProperties => 0, | |
f194ac27 | 485 | properties => $default_properties->({ |
15a1e62c DM |
486 | sender => get_standard_option('pmg-email-address', { |
487 | description => "Sender email address.", | |
488 | }), | |
489 | filter => { | |
490 | description => "Receiver address filter.", | |
491 | type => 'string', | |
492 | maxLength => 512, | |
493 | optional => 1, | |
494 | }, | |
f194ac27 DM |
495 | orderby => $api_properties->{orderby}, |
496 | }), | |
15a1e62c DM |
497 | }, |
498 | returns => { | |
499 | type => 'array', | |
500 | items => { | |
501 | type => "object", | |
5522af5f | 502 | properties => $detail_return_properties->({ |
15a1e62c DM |
503 | receiver => { |
504 | description => "Receiver email.", | |
505 | type => 'string', | |
506 | }, | |
5522af5f | 507 | }), |
15a1e62c DM |
508 | }, |
509 | }, | |
510 | code => sub { | |
511 | my ($param) = @_; | |
512 | ||
d865dfba | 513 | return get_detail_statistics('sender', $param); |
0ab6dc2a DM |
514 | }}); |
515 | ||
516 | __PACKAGE__->register_method ({ | |
517 | name => 'receiver', | |
518 | path => 'receiver', | |
519 | method => 'GET', | |
520 | description => "Receiver Address Statistics.", | |
521 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
522 | parameters => { | |
523 | additionalProperties => 0, | |
f194ac27 | 524 | properties => $default_properties->({ |
0ab6dc2a DM |
525 | filter => { |
526 | description => "Receiver address filter.", | |
527 | type => 'string', | |
528 | maxLength => 512, | |
529 | optional => 1, | |
530 | }, | |
f194ac27 DM |
531 | orderby => $api_properties->{orderby}, |
532 | }), | |
0ab6dc2a DM |
533 | }, |
534 | returns => { | |
535 | type => 'array', | |
536 | items => { | |
537 | type => "object", | |
538 | properties => { | |
539 | receiver => { | |
540 | description => "Sender email.", | |
541 | type => 'string', | |
542 | }, | |
543 | count => { | |
544 | description => "Mail count.", | |
545 | type => 'number', | |
546 | optional => 1, | |
547 | }, | |
548 | bytes => { | |
549 | description => "Mail traffic (Bytes).", | |
550 | type => 'number', | |
551 | }, | |
552 | spamcount => { | |
553 | description => "Number of sent spam mails.", | |
554 | type => 'number', | |
555 | optional => 1, | |
556 | }, | |
557 | viruscount => { | |
558 | description => "Number of sent virus mails.", | |
559 | type => 'number', | |
560 | optional => 1, | |
561 | }, | |
562 | }, | |
563 | }, | |
564 | links => [ { rel => 'child', href => "{receiver}" } ], | |
565 | }, | |
566 | code => sub { | |
567 | my ($param) = @_; | |
568 | ||
f194ac27 | 569 | my ($start, $end) = $extract_start_end->($param); |
0ab6dc2a | 570 | |
44017d49 DM |
571 | my $cfg = PMG::Config->new(); |
572 | my $advfilter = $cfg->get('admin', 'advfilter'); | |
573 | ||
0ab6dc2a DM |
574 | my $stat = PMG::Statistic->new($start, $end); |
575 | my $rdb = PMG::RuleDB->new(); | |
576 | ||
577 | my $sorters = []; | |
578 | if ($param->{orderby}) { | |
579 | my $props = ['receiver', 'count', 'bytes', 'spamcount', 'viruscount']; | |
580 | $sorters = $decode_orderby->($param->{orderby}, $props); | |
581 | } | |
582 | ||
44017d49 | 583 | my $res = $stat->user_stat_receiver($rdb, $userstat_limit, $sorters, $param->{filter}, $advfilter); |
0ab6dc2a DM |
584 | |
585 | return $res; | |
586 | }}); | |
587 | ||
e89b61c5 | 588 | # FIXME: remove for PMG 7.0 - handled by 'details' API call which allows addresses containing '/' |
0ab6dc2a DM |
589 | __PACKAGE__->register_method ({ |
590 | name => 'receiverdetails', | |
591 | path => 'receiver/{receiver}', | |
592 | method => 'GET', | |
593 | description => "Detailed Receiver Statistics.", | |
594 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
595 | parameters => { | |
596 | additionalProperties => 0, | |
f194ac27 | 597 | properties => $default_properties->({ |
0ab6dc2a DM |
598 | receiver => get_standard_option('pmg-email-address', { |
599 | description => "Receiver email address.", | |
600 | }), | |
601 | filter => { | |
602 | description => "Sender address filter.", | |
603 | type => 'string', | |
604 | maxLength => 512, | |
605 | optional => 1, | |
606 | }, | |
f194ac27 DM |
607 | orderby => $api_properties->{orderby}, |
608 | }), | |
0ab6dc2a DM |
609 | }, |
610 | returns => { | |
611 | type => 'array', | |
612 | items => { | |
613 | type => "object", | |
5522af5f | 614 | properties => $detail_return_properties->({ |
0ab6dc2a DM |
615 | sender => { |
616 | description => "Sender email.", | |
617 | type => 'string', | |
618 | }, | |
5522af5f | 619 | }), |
0ab6dc2a DM |
620 | }, |
621 | }, | |
622 | code => sub { | |
623 | my ($param) = @_; | |
624 | ||
d865dfba | 625 | return get_detail_statistics('receiver', $param); |
15a1e62c DM |
626 | }}); |
627 | ||
d19c40e0 DM |
628 | __PACKAGE__->register_method ({ |
629 | name => 'domains', | |
630 | path => 'domains', | |
631 | method => 'GET', | |
632 | description => "Mail Domains Statistics.", | |
633 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
634 | parameters => { | |
635 | additionalProperties => 0, | |
f194ac27 | 636 | properties => $default_properties->(), |
d19c40e0 DM |
637 | }, |
638 | returns => { | |
639 | type => 'array', | |
640 | items => { | |
641 | type => "object", | |
642 | properties => { | |
643 | domain => { | |
644 | description => "Domain name.", | |
645 | type => 'string', | |
646 | }, | |
647 | count_in => { | |
648 | description => "Incoming mail count.", | |
649 | type => 'number', | |
650 | }, | |
651 | count_out => { | |
652 | description => "Outgoing mail count.", | |
653 | type => 'number', | |
654 | }, | |
655 | spamcount_in => { | |
656 | description => "Incoming spam mails.", | |
657 | type => 'number', | |
658 | }, | |
659 | spamcount_out => { | |
660 | description => "Outgoing spam mails.", | |
661 | type => 'number', | |
662 | }, | |
6bc396fc DM |
663 | bytes_in => { |
664 | description => "Incoming mail traffic (Bytes).", | |
d19c40e0 DM |
665 | type => 'number', |
666 | }, | |
6bc396fc DM |
667 | bytes_out => { |
668 | description => "Outgoing mail traffic (Bytes).", | |
d19c40e0 DM |
669 | type => 'number', |
670 | }, | |
671 | viruscount_in => { | |
672 | description => "Number of incoming virus mails.", | |
673 | type => 'number', | |
674 | }, | |
675 | viruscount_out => { | |
676 | description => "Number of outgoing virus mails.", | |
677 | type => 'number', | |
678 | }, | |
679 | }, | |
680 | }, | |
681 | }, | |
682 | code => sub { | |
683 | my ($param) = @_; | |
684 | ||
f194ac27 | 685 | my ($start, $end) = $extract_start_end->($param); |
d19c40e0 DM |
686 | |
687 | my $stat = PMG::Statistic->new($start, $end); | |
688 | my $rdb = PMG::RuleDB->new(); | |
689 | ||
690 | #PMG::Statistic::update_stats_domainstat_in($rdb->{dbh}, $cinfo); | |
691 | #PMG::Statistic::update_stats_domainstat_out($rdb->{dbh}, $cinfo); | |
692 | ||
693 | my $res = $stat->total_domain_stat($rdb); | |
694 | ||
15a1e62c | 695 | |
d19c40e0 DM |
696 | return $res; |
697 | }}); | |
698 | ||
5de9374c DM |
699 | __PACKAGE__->register_method ({ |
700 | name => 'mail', | |
701 | path => 'mail', | |
702 | method => 'GET', | |
703 | description => "General Mail Statistics.", | |
704 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
5de9374c DM |
705 | parameters => { |
706 | additionalProperties => 0, | |
f194ac27 | 707 | properties => $default_properties->(), |
5de9374c DM |
708 | }, |
709 | returns => { | |
710 | type => "object", | |
26e55ddd DM |
711 | properties => { |
712 | avptime => { | |
713 | description => "Average mail processing time in seconds.", | |
714 | type => 'number', | |
d3550ac9 DM |
715 | }, |
716 | bounces_in => { | |
717 | description => "Incoming bounce mail count (sender = <>).", | |
718 | type => 'number', | |
719 | }, | |
720 | bounces_out => { | |
721 | description => "Outgoing bounce mail count (sender = <>).", | |
722 | type => 'number', | |
723 | }, | |
724 | count => { | |
725 | description => "Overall mail count (in and out).", | |
726 | type => 'number', | |
727 | }, | |
728 | count_in => { | |
729 | description => "Incoming mail count.", | |
730 | type => 'number', | |
731 | }, | |
732 | count_out => { | |
733 | description => "Outgoing mail count.", | |
734 | type => 'number', | |
735 | }, | |
736 | glcount => { | |
737 | description => "Number of greylisted mails.", | |
738 | type => 'number', | |
739 | }, | |
4681645a DM |
740 | rbl_rejects => { |
741 | description => "Number of RBL rejects.", | |
742 | type => 'integer', | |
743 | }, | |
744 | pregreet_rejects => { | |
745 | description => "PREGREET recject count.", | |
746 | type => 'integer', | |
747 | }, | |
d3550ac9 | 748 | junk_in => { |
4681645a | 749 | description => "Incoming junk mail count (viruscount_in + spamcount_in + glcount + spfcount + rbl_rejects + pregreet_rejects).", |
d3550ac9 DM |
750 | type => 'number', |
751 | }, | |
752 | junk_out => { | |
753 | description => "Outgoing junk mail count (viruscount_out + spamcount_out).", | |
754 | type => 'number', | |
755 | }, | |
756 | spamcount_in => { | |
757 | description => "Incoming spam mails.", | |
758 | type => 'number', | |
759 | }, | |
760 | spamcount_out => { | |
761 | description => "Outgoing spam mails.", | |
762 | type => 'number', | |
763 | }, | |
764 | spfcount => { | |
765 | description => "Mails rejected by SPF.", | |
766 | type => 'number', | |
767 | }, | |
d19c40e0 | 768 | bytes_in => { |
d3550ac9 DM |
769 | description => "Incoming mail traffic (bytes).", |
770 | type => 'number', | |
771 | }, | |
d19c40e0 | 772 | bytes_out => { |
d3550ac9 DM |
773 | description => "Outgoing mail traffic (bytes).", |
774 | type => 'number', | |
775 | }, | |
776 | viruscount_in => { | |
777 | description => "Number of incoming virus mails.", | |
778 | type => 'number', | |
779 | }, | |
780 | viruscount_out => { | |
781 | description => "Number of outgoing virus mails.", | |
782 | type => 'number', | |
783 | }, | |
26e55ddd | 784 | }, |
5de9374c DM |
785 | }, |
786 | code => sub { | |
787 | my ($param) = @_; | |
91bc7652 | 788 | |
f194ac27 | 789 | my ($start, $end) = $extract_start_end->($param); |
91bc7652 | 790 | |
5de9374c DM |
791 | my $stat = PMG::Statistic->new($start, $end); |
792 | my $rdb = PMG::RuleDB->new(); | |
91bc7652 | 793 | |
5de9374c DM |
794 | my $res = $stat->total_mail_stat($rdb); |
795 | ||
4681645a DM |
796 | my $rejects = $stat->postscreen_stat($rdb); |
797 | ||
798 | $res->{rbl_rejects} //= 0; | |
799 | if (defined(my $rbl_rejects = $rejects->{rbl_rejects})) { | |
800 | foreach my $k (qw(rbl_rejects junk_in count_in count)) { | |
801 | $res->{$k} += $rbl_rejects; | |
802 | } | |
803 | } | |
804 | ||
805 | $res->{pregreet_rejects} //= 0; | |
806 | if (defined(my $pregreet_rejects = $rejects->{pregreet_rejects})) { | |
807 | foreach my $k (qw(pregreet_rejects junk_in count_in count)) { | |
808 | $res->{$k} += $pregreet_rejects; | |
809 | } | |
810 | } | |
811 | ||
5de9374c DM |
812 | return $res; |
813 | }}); | |
814 | ||
fea9d463 DC |
815 | __PACKAGE__->register_method ({ |
816 | name => 'recent', | |
817 | path => 'recent', | |
818 | method => 'GET', | |
819 | description => "Mail Count Statistics.", | |
820 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
821 | parameters => { | |
822 | additionalProperties => 0, | |
823 | properties => { | |
824 | hours => { | |
825 | description => "How many hours you want to get", | |
826 | type => 'integer', | |
827 | minimum => 1, | |
828 | maximum => 24, | |
829 | optional => 1, | |
830 | default => 12, | |
831 | }, | |
832 | timespan => { | |
833 | description => "The Timespan for one datapoint (in seconds)", | |
834 | type => 'integer', | |
835 | minimum => 1, | |
836 | maximum => 1800, | |
837 | optional => 1, | |
838 | default => 1800, | |
839 | }, | |
840 | }, | |
841 | }, | |
842 | returns => { | |
843 | type => 'array', | |
844 | items => { | |
845 | type => "object", | |
846 | properties => { | |
847 | index => { | |
848 | description => "Time index.", | |
849 | type => 'integer', | |
850 | }, | |
851 | time => { | |
852 | description => "Time (Unix epoch).", | |
853 | type => 'integer', | |
854 | }, | |
855 | count => { | |
856 | description => "Overall mail count (in and out).", | |
857 | type => 'number', | |
858 | }, | |
859 | count_in => { | |
860 | description => "Incoming mail count.", | |
861 | type => 'number', | |
862 | }, | |
863 | count_out => { | |
864 | description => "Outgoing mail count.", | |
865 | type => 'number', | |
866 | }, | |
867 | spam => { | |
868 | description => "Overall spam mail count (in and out).", | |
869 | type => 'number', | |
870 | }, | |
871 | spam_in => { | |
872 | description => "Incoming spam mails (spamcount_in + glcount + spfcount).", | |
873 | type => 'number', | |
874 | }, | |
875 | spam_out => { | |
876 | description => "Outgoing spam mails.", | |
877 | type => 'number', | |
878 | }, | |
879 | bytes_in => { | |
880 | description => "Number of incoming bytes mails.", | |
881 | type => 'number', | |
882 | }, | |
883 | bytes_out => { | |
884 | description => "Number of outgoing bytes mails.", | |
885 | type => 'number', | |
886 | }, | |
887 | virus_in => { | |
888 | description => "Number of incoming virus mails.", | |
889 | type => 'number', | |
890 | }, | |
891 | virus_out => { | |
892 | description => "Number of outgoing virus mails.", | |
893 | type => 'number', | |
894 | }, | |
895 | timespan => { | |
896 | description => "Timespan in seconds for one data point", | |
897 | type => 'number', | |
898 | } | |
899 | }, | |
900 | }, | |
901 | }, | |
902 | code => sub { | |
903 | my ($param) = @_; | |
904 | ||
fea9d463 DC |
905 | my $hours = $param->{hours} // 12; |
906 | my $span = $param->{timespan} // 1800; | |
907 | ||
908 | my $end = time(); | |
909 | my $start = $end - 3600*$hours; | |
910 | ||
911 | my $stat = PMG::Statistic->new($start, $end); | |
912 | my $rdb = PMG::RuleDB->new(); | |
913 | ||
914 | my $res = $stat->recent_mailcount($rdb, $span); | |
915 | ||
916 | return $res; | |
917 | }}); | |
918 | ||
56e1cb1b DC |
919 | __PACKAGE__->register_method ({ |
920 | name => 'recentreceivers', | |
921 | path => 'recentreceivers', | |
922 | method => 'GET', | |
923 | description => "Top recent Mail Receivers (including spam)", | |
924 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
925 | parameters => { | |
926 | additionalProperties => 0, | |
927 | properties => { | |
928 | hours => { | |
929 | description => "How many hours you want to get", | |
930 | type => 'integer', | |
931 | minimum => 1, | |
932 | maximum => 24, | |
933 | optional => 1, | |
934 | default => 12, | |
935 | }, | |
936 | limit => { | |
937 | description => "The maximum number of receivers to return.", | |
938 | type => 'integer', | |
939 | minimum => 1, | |
940 | maximum => 50, | |
941 | optional => 1, | |
942 | default => 5, | |
943 | }, | |
944 | }, | |
945 | }, | |
946 | returns => { | |
947 | type => 'array', | |
948 | items => { | |
949 | type => "object", | |
950 | properties => { | |
951 | count => { | |
952 | description => "The count of incoming not blocked E-Mails", | |
953 | type => 'integer', | |
954 | }, | |
955 | receiver => { | |
956 | description => "The receiver", | |
957 | type => 'string', | |
958 | }, | |
959 | }, | |
960 | }, | |
961 | }, | |
962 | code => sub { | |
963 | my ($param) = @_; | |
964 | ||
56e1cb1b DC |
965 | my $hours = $param->{hours} // 12; |
966 | ||
967 | my $limit = $param->{limit} // 5; | |
968 | ||
969 | my $end = time(); | |
970 | my $start = $end - 3600*$hours; | |
971 | ||
972 | my $stat = PMG::Statistic->new($start, $end); | |
973 | my $rdb = PMG::RuleDB->new(); | |
974 | ||
975 | my $res = $stat->recent_receivers($rdb, $limit); | |
976 | ||
977 | return $res; | |
978 | }}); | |
979 | ||
6156e4b6 DM |
980 | __PACKAGE__->register_method ({ |
981 | name => 'mailcount', | |
982 | path => 'mailcount', | |
983 | method => 'GET', | |
984 | description => "Mail Count Statistics.", | |
985 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
986 | parameters => { | |
987 | additionalProperties => 0, | |
f194ac27 | 988 | properties => $default_properties->({ |
6156e4b6 | 989 | timespan => { |
f194ac27 | 990 | description => "Return Mails/<timespan>, where <timespan> is specified in seconds.", |
6156e4b6 DM |
991 | type => 'integer', |
992 | minimum => 3600, | |
993 | maximum => 366*86400, | |
994 | optional => 1, | |
995 | default => 3600, | |
f194ac27 DM |
996 | }, |
997 | }), | |
6156e4b6 DM |
998 | }, |
999 | returns => { | |
1000 | type => 'array', | |
1001 | items => { | |
1002 | type => "object", | |
1003 | properties => { | |
1004 | index => { | |
1005 | description => "Time index.", | |
1006 | type => 'integer', | |
1007 | }, | |
1008 | time => { | |
1009 | description => "Time (Unix epoch).", | |
1010 | type => 'integer', | |
1011 | }, | |
1012 | count => { | |
1013 | description => "Overall mail count (in and out).", | |
1014 | type => 'number', | |
1015 | }, | |
1016 | count_in => { | |
1017 | description => "Incoming mail count.", | |
1018 | type => 'number', | |
1019 | }, | |
1020 | count_out => { | |
1021 | description => "Outgoing mail count.", | |
1022 | type => 'number', | |
1023 | }, | |
1024 | spamcount_in => { | |
4681645a | 1025 | description => "Incoming spam mails (spamcount_in + glcount + spfcount + rbl_rejects + pregreet_rejects).", |
6156e4b6 DM |
1026 | type => 'number', |
1027 | }, | |
1028 | spamcount_out => { | |
1029 | description => "Outgoing spam mails.", | |
1030 | type => 'number', | |
1031 | }, | |
1032 | viruscount_in => { | |
1033 | description => "Number of incoming virus mails.", | |
1034 | type => 'number', | |
1035 | }, | |
1036 | viruscount_out => { | |
1037 | description => "Number of outgoing virus mails.", | |
1038 | type => 'number', | |
1039 | }, | |
4681645a DM |
1040 | rbl_rejects => { |
1041 | description => "Number of RBL rejects.", | |
1042 | type => 'integer', | |
1043 | }, | |
1044 | pregreet_rejects => { | |
1045 | description => "PREGREET recject count.", | |
1046 | type => 'integer', | |
1047 | }, | |
6156e4b6 DM |
1048 | bounces_in => { |
1049 | description => "Incoming bounce mail count (sender = <>).", | |
1050 | type => 'number', | |
1051 | }, | |
1052 | bounces_out => { | |
1053 | description => "Outgoing bounce mail count (sender = <>).", | |
1054 | type => 'number', | |
1055 | }, | |
1056 | }, | |
1057 | }, | |
1058 | }, | |
1059 | code => sub { | |
1060 | my ($param) = @_; | |
1061 | ||
f194ac27 | 1062 | my ($start, $end) = $extract_start_end->($param); |
6156e4b6 DM |
1063 | |
1064 | my $span = $param->{timespan} // 3600; | |
1065 | ||
1066 | my $count = ($end - $start)/$span; | |
1067 | ||
1068 | die "too many entries - try to increase parameter 'span'\n" if $count > 5000; | |
1069 | ||
1070 | my $stat = PMG::Statistic->new($start, $end); | |
1071 | my $rdb = PMG::RuleDB->new(); | |
1072 | ||
1073 | #PMG::Statistic::update_stats_dailystat($rdb->{dbh}, $cinfo); | |
1074 | ||
4681645a DM |
1075 | my $rejects = $stat->postscreen_stat_graph($rdb, $span); |
1076 | ||
6156e4b6 DM |
1077 | my $res = $stat->traffic_stat_graph ($rdb, $span); |
1078 | ||
4681645a DM |
1079 | my $element_count = scalar(@$res); |
1080 | ||
1081 | for (my $i = 0; $i < $element_count; $i++) { | |
1082 | my $el = $rejects->[$i]; | |
1083 | next if !$el; | |
1084 | my $d = $res->[$i]; | |
1085 | foreach my $k ('rbl_rejects', 'pregreet_rejects') { | |
1086 | my $count = $el->{$k} // 0; | |
1087 | $d->{$k} = $count; | |
1088 | foreach my $k (qw(count count_in spamcount_in)) { | |
1089 | $d->{$k} += $count; | |
1090 | } | |
1091 | } | |
1092 | } | |
1093 | ||
6156e4b6 DM |
1094 | return $res; |
1095 | }}); | |
1096 | ||
91bc7652 DM |
1097 | __PACKAGE__->register_method ({ |
1098 | name => 'virus', | |
1099 | path => 'virus', | |
1100 | method => 'GET', | |
1101 | description => "Get Statistics about detected Viruses.", | |
1102 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
91bc7652 DM |
1103 | parameters => { |
1104 | additionalProperties => 0, | |
f194ac27 | 1105 | properties => $default_properties->(), |
91bc7652 DM |
1106 | }, |
1107 | returns => { | |
1108 | type => 'array', | |
1109 | items => { | |
1110 | type => "object", | |
1111 | properties => { | |
1112 | name => { | |
1113 | description => 'Virus name.', | |
1114 | type => 'string', | |
1115 | }, | |
1116 | count => { | |
1117 | description => 'Detection count.', | |
1118 | type => 'integer', | |
1119 | }, | |
1120 | }, | |
1121 | } | |
1122 | }, | |
1123 | code => sub { | |
1124 | my ($param) = @_; | |
1125 | ||
f194ac27 | 1126 | my ($start, $end) = $extract_start_end->($param); |
91bc7652 DM |
1127 | |
1128 | my $stat = PMG::Statistic->new($start, $end); | |
1129 | my $rdb = PMG::RuleDB->new(); | |
1130 | ||
1131 | my $res = $stat->total_virus_stat($rdb); | |
1132 | ||
1133 | return $res; | |
1134 | }}); | |
1135 | ||
1136 | __PACKAGE__->register_method ({ | |
67832798 DM |
1137 | name => 'spamscores', |
1138 | path => 'spamscores', | |
91bc7652 | 1139 | method => 'GET', |
67832798 DM |
1140 | description => "Get the count of spam mails grouped by spam score. " . |
1141 | "Count for score 10 includes mails with spam score > 10.", | |
91bc7652 | 1142 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, |
91bc7652 DM |
1143 | parameters => { |
1144 | additionalProperties => 0, | |
f194ac27 | 1145 | properties => $default_properties->(), |
91bc7652 DM |
1146 | }, |
1147 | returns => { | |
1148 | type => 'array', | |
1149 | items => { | |
1150 | type => "object", | |
1151 | properties => { | |
1152 | level => { | |
1153 | description => 'Spam level.', | |
1154 | type => 'string', | |
1155 | }, | |
1156 | count => { | |
1157 | description => 'Detection count.', | |
1158 | type => 'integer', | |
1159 | }, | |
67832798 DM |
1160 | ratio => { |
1161 | description => 'Portion of overall mail count.', | |
1162 | type => 'number', | |
1163 | }, | |
91bc7652 DM |
1164 | }, |
1165 | } | |
1166 | }, | |
1167 | code => sub { | |
1168 | my ($param) = @_; | |
1169 | ||
f194ac27 | 1170 | my ($start, $end) = $extract_start_end->($param); |
91bc7652 DM |
1171 | |
1172 | my $stat = PMG::Statistic->new($start, $end); | |
1173 | my $rdb = PMG::RuleDB->new(); | |
1174 | ||
1175 | my $totalstat = $stat->total_mail_stat ($rdb); | |
1176 | my $spamstat = $stat->total_spam_stat($rdb); | |
1177 | ||
d67b777f | 1178 | my $res = []; |
91bc7652 | 1179 | |
67832798 | 1180 | my $count_in = $totalstat->{count_in}; |
83081b3d DM |
1181 | |
1182 | my $levelcount = {}; | |
1767b03d | 1183 | my $spamcount = 0; |
91bc7652 | 1184 | foreach my $ref (@$spamstat) { |
1767b03d DM |
1185 | if (my $level = $ref->{spamlevel}) { |
1186 | next if $level < 1; # just to be sure | |
1187 | $spamcount += $ref->{count}; | |
1188 | $level = 10 if $level > 10; | |
1189 | $levelcount->{$level} += $ref->{count}; | |
1190 | } | |
91bc7652 DM |
1191 | } |
1192 | ||
1767b03d | 1193 | $levelcount->{0} = $count_in - $spamcount; |
83081b3d DM |
1194 | |
1195 | for (my $i = 0; $i <= 10; $i++) { | |
67832798 DM |
1196 | my $count = $levelcount->{$i} // 0; |
1197 | my $ratio = $count_in ? $count/$count_in : 0; | |
1198 | push @$res, { level => $i, count => $count, ratio => $ratio }; | |
83081b3d | 1199 | } |
91bc7652 DM |
1200 | |
1201 | return $res; | |
1202 | }}); | |
1203 | ||
89891fa2 DM |
1204 | __PACKAGE__->register_method ({ |
1205 | name => 'maildistribution', | |
1206 | path => 'maildistribution', | |
1207 | method => 'GET', | |
1208 | description => "Get the count of spam mails grouped by spam score. " . | |
1209 | "Count for score 10 includes mails with spam score > 10.", | |
1210 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, | |
1211 | parameters => { | |
1212 | additionalProperties => 0, | |
f194ac27 | 1213 | properties => $default_properties->(), |
89891fa2 DM |
1214 | }, |
1215 | returns => { | |
1216 | type => 'array', | |
1217 | items => { | |
1218 | type => "object", | |
1219 | properties => { | |
1220 | index => { | |
1221 | description => "Hour (0-23).", | |
1222 | type => 'integer', | |
1223 | }, | |
1224 | count => { | |
1225 | description => "Overall mail count (in and out).", | |
1226 | type => 'number', | |
1227 | }, | |
1228 | count_in => { | |
1229 | description => "Incoming mail count.", | |
1230 | type => 'number', | |
1231 | }, | |
1232 | count_out => { | |
1233 | description => "Outgoing mail count.", | |
1234 | type => 'number', | |
1235 | }, | |
1236 | spamcount_in => { | |
1237 | description => "Incoming spam mails (spamcount_in + glcount + spfcount).", | |
1238 | type => 'number', | |
1239 | }, | |
1240 | spamcount_out => { | |
1241 | description => "Outgoing spam mails.", | |
1242 | type => 'number', | |
1243 | }, | |
1244 | viruscount_in => { | |
1245 | description => "Number of incoming virus mails.", | |
1246 | type => 'number', | |
1247 | }, | |
1248 | viruscount_out => { | |
1249 | description => "Number of outgoing virus mails.", | |
1250 | type => 'number', | |
1251 | }, | |
1252 | bounces_in => { | |
1253 | description => "Incoming bounce mail count (sender = <>).", | |
1254 | type => 'number', | |
1255 | }, | |
1256 | bounces_out => { | |
1257 | description => "Outgoing bounce mail count (sender = <>).", | |
1258 | type => 'number', | |
1259 | }, | |
1260 | }, | |
1261 | }, | |
1262 | }, | |
1263 | code => sub { | |
1264 | my ($param) = @_; | |
1265 | ||
f194ac27 | 1266 | my ($start, $end) = $extract_start_end->($param); |
89891fa2 DM |
1267 | |
1268 | my $stat = PMG::Statistic->new($start, $end); | |
1269 | my $rdb = PMG::RuleDB->new(); | |
1270 | ||
1271 | #PMG::Statistic::update_stats_dailystat($rdb->{dbh}, $cinfo); | |
1272 | ||
1273 | my $res = $stat->traffic_stat_day_dist ($rdb); | |
1274 | ||
1275 | return $res; | |
1276 | }}); | |
1277 | ||
2719ef94 | 1278 | __PACKAGE__->register_method ({ |
980ce907 DM |
1279 | name => 'rejectcount', |
1280 | path => 'rejectcount', | |
2719ef94 | 1281 | method => 'GET', |
980ce907 | 1282 | description => "Early SMTP reject count statistic (RBL, PREGREET rejects with postscreen)", |
2719ef94 DM |
1283 | permissions => { check => [ 'admin', 'qmanager', 'audit'] }, |
1284 | parameters => { | |
1285 | additionalProperties => 0, | |
1286 | properties => $default_properties->({ | |
1287 | timespan => { | |
980ce907 | 1288 | description => "Return RBL/PREGREET rejects/<timespan>, where <timespan> is specified in seconds.", |
2719ef94 DM |
1289 | type => 'integer', |
1290 | minimum => 3600, | |
1291 | maximum => 366*86400, | |
1292 | optional => 1, | |
1293 | default => 3600, | |
1294 | }, | |
1295 | }), | |
1296 | }, | |
1297 | returns => { | |
1298 | type => 'array', | |
1299 | items => { | |
1300 | type => "object", | |
1301 | properties => { | |
1302 | index => { | |
1303 | description => "Time index.", | |
1304 | type => 'integer', | |
1305 | }, | |
1306 | time => { | |
1307 | description => "Time (Unix epoch).", | |
1308 | type => 'integer', | |
1309 | }, | |
980ce907 | 1310 | rbl_rejects => { |
2719ef94 | 1311 | description => "RBL recject count.", |
980ce907 DM |
1312 | type => 'integer', |
1313 | }, | |
1314 | pregreet_rejects => { | |
1315 | description => "PREGREET recject count.", | |
1316 | type => 'integer', | |
2719ef94 DM |
1317 | }, |
1318 | }, | |
1319 | }, | |
1320 | }, | |
1321 | code => sub { | |
1322 | my ($param) = @_; | |
1323 | ||
2719ef94 DM |
1324 | my ($start, $end) = $extract_start_end->($param); |
1325 | ||
1326 | my $span = $param->{timespan} // 3600; | |
1327 | ||
1328 | my $count = ($end - $start)/$span; | |
1329 | ||
1330 | die "too many entries - try to increase parameter 'span'\n" if $count > 5000; | |
1331 | ||
1332 | my $stat = PMG::Statistic->new($start, $end); | |
1333 | my $rdb = PMG::RuleDB->new(); | |
1334 | ||
4681645a | 1335 | my $res = $stat->postscreen_stat_graph($rdb, $span); |
2719ef94 DM |
1336 | |
1337 | return $res; | |
1338 | }}); | |
1339 | ||
5de9374c | 1340 | 1; |