TT#63545 remove fraud lock, add fraud notifier

* ngcp-fraud-daily-lock and ngcp-fraud-auto-lock are
      not supported anymore and replacted by ngcp-fraud-notifier
      that does not lock contracts/subscribers but sends email
      notifications and updates cdr_period_costs "notify_status"
      and "nofified_at"

Change-Id: Icacbddc68fb25408a388f52427aab993c085dba3
changes/82/32182/3
Kirill Solomko 6 years ago
parent 666267798b
commit 0eee41bd97

@ -1,274 +0,0 @@
#!/usr/bin/perl
use strict;
use warnings;
use English;
use Getopt::Long;
use Pod::Usage;
use NGCP::API::Client;
use Readonly;
use XML::Simple;
use Template;
use Email::Sender::Simple qw();
use Email::Simple;
use Email::Simple::Creator;
use Email::Sender::Transport::Sendmail qw();
Readonly my @required => qw();
Readonly my $config_file => '/etc/ngcp-panel/provisioning.conf';
Readonly my $interval => 'month';
my $page_size = 100;
my $opts = {
verbose => 0,
};
my $config;
GetOptions( $opts,
"help|h" => \&usage,
"verbose",
) or usage();
sub check_params {
my @missing;
foreach my $param (@required) {
push @missing, $param unless $opts->{$param};
}
usage(join(' ', @missing)) if scalar @missing;
return;
}
sub usage {
my $msg = shift;
pod2usage(-exitval => $msg ? 1 : 0,
-verbose => 99,
-message => $msg
? $msg =~ /not found/i
? $msg
: "Missing parameters: $msg"
: '',
);
return;
}
sub load_config {
$config = XML::Simple->new()->XMLin($config_file, ForceArray => 0)
or die "Cannot load config: $config_file: $ERRNO";
return;
}
sub get_data {
my ($uri, $link) = @_;
my $client = new NGCP::API::Client;
$client->set_verbose($opts->{verbose});
$client->set_page_rows($page_size);
my @result = ();
while (my $res = $client->next_page($uri)) {
die $res->result unless $res->is_success;
my $res_hash = $res->as_hash;
my $data = $res_hash->{_embedded}{'ngcp:'.$link};
if ('ARRAY' eq ref $data) {
push(@result,@$data);
} elsif ($data) {
push(@result,$data);
}
}
return \@result;
}
sub get_email_template {
my $event = shift;
my $lock_type = $event->{interval_lock} ? 'lock' : 'warning';
my $reseller_id = $event->{reseller_id};
my @templates_data = ();
foreach my $reseller ($event->{reseller_id}, 'NULL') {
@templates_data = (
@templates_data,
@{get_data(sprintf('/api/emailtemplates/?reseller_id=%s', $reseller),
'emailtemplates')});
}
my $selected_template;
foreach my $template (@templates_data) {
next if $template->{name} ne 'customer_fraud_'.$lock_type.'_default_email'
&& $template->{name} ne 'customer_fraud_'.$lock_type.'_email';
next if $template->{reseller_id} && $template->{reseller_id} != $reseller_id;
$selected_template = $template;
last if $template->{reseller_id};
}
unless ($selected_template) {
die sprintf "No template 'customer_fraud_%s_default_email' OR 'customer_fraud_%s_email' is defined.", $lock_type, $lock_type;
}
return $selected_template;
}
sub send_email {
my ($event, $subscribers) = @_;
my $template = get_email_template($event);
my $vars = { adminmail => $config->{adminmail},
customer_id => $event->{id},
interval => $event->{interval},
interval_cost => sprintf('%.2f', $event->{interval_cost}/100),
interval_limit => sprintf('%.2f', $event->{interval_limit}/100),
type => $event->{type} eq 'profile_limit'
? 'billing profile' : 'customer',
};
foreach my $subscriber (@{$subscribers}) {
$vars->{subscribers} .= sprintf "%s\@%s %s\n",
@{$subscriber}{qw(username domain)},
$subscriber->{external_id}
? '('.$subscriber->{external_id}.')' : '';
}
my $tt = Template->new();
map { my $out;
$tt->process(\$template->{$_}, $vars, \$out);
$out and $template->{$_} = $out;
} keys %{$template};
die "'To' header is empty in the email" unless $event->{interval_notify};
die "'From' header is empty in the email" unless $template->{from_email};
die "'Subject' header is empty in the email" unless $template->{subject};
my $transport = Email::Sender::Transport::Sendmail->new;
my $email = Email::Simple->create(
header => [
To => $event->{interval_notify},
From => $template->{from_email},
Subject => $template->{subject},
],
body => $template->{body},
);
Email::Sender::Simple->send($email, { transport => $transport })
or die sprintf "Cannot send fraud auto lock notification to %s: $ERRNO",
$email->header('To');
return;
}
sub lock_customer {
my ($event, $subscribers) = @_;
my $client = new NGCP::API::Client;
$client->set_verbose($opts->{verbose});
my $uri = '/api/customers/'.$event->{id};
my $data = [ { op => 'replace',
path => '/status',
value => 'locked' } ];
my $res = $client->request("PATCH", $uri, $data);
if ($res->status_line =~ /200 OK/) {
foreach my $subscriber (@{$subscribers}) {
$uri = '/api/subscribers/'.$subscriber->{id};
$data = [ { op => 'replace',
path => '/status',
value => 'locked' },
{ op => 'replace',
path => '/lock',
value => $event->{interval_lock} } ];
$res = $client->request("PATCH", $uri, $data);
}
}
return;
}
sub main {
check_params();
load_config();
my $events = get_data(sprintf('/api/customerfraudevents/?no_count=true&interval=%s',
$interval),
'customerfraudevents');
foreach my $event (@{$events}) {
my $subscribers = get_data(sprintf('/api/subscribers/?customer_id=%d',
$event->{id}),
'subscribers');
$event->{interval} = 'month';
if (defined $event->{interval_lock} && $event->{interval_lock} > 0) {
lock_customer($event, $subscribers);
}
if ($event->{interval_notify}) {
eval {
send_email($event, $subscribers);
};
}
print $EVAL_ERROR if $EVAL_ERROR;
}
return;
}
main();
exit 0;
__END__
=head1 NAME
ngcp-fraud-auto-lock - checks for contract balances above fraud limit thresholds
=head1 SYNOPSIS
B<ngcp-fraud-auto-lock> [I<options>...]
=head1 DESCRIPTION
B<This program> checks for contract balances above fraud limit warning
thresholds and sends email notifications about the incidents as applying
actions on such contracts (e.g. lock). Interval: 'month'.
=head1 OPTIONS
=over 8
=item B<--verbose>
Show additional debug information. Default false.
=item B<--help>
Print a brief help message.
=back
=head1 EXIT STATUS
Exit code 0 means everything is ok otherwise 1.
=head1 SEE ALSO
NGCP::API::Client
=head1 BUGS AND LIMITATIONS
Please report problems you notice to the Sipwise
Development Team <support@sipwise.com>.
=head1 AUTHOR
Kirill Solomko <ksolomko@sipwise.com>
=head1 LICENSE
Copyright (C) 2016 Sipwise GmbH, Austria
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
=cut

@ -12,10 +12,22 @@ use Email::Sender::Simple qw();
use Email::Simple;
use Email::Simple::Creator;
use Email::Sender::Transport::Sendmail qw();
use POSIX qw(strftime);
use File::Pid;
Readonly my @required => qw();
Readonly my $config_file => '/etc/ngcp-panel/provisioning.conf';
Readonly my $interval => 'day';
my $PROGRAM_BASE = "ngcp-fraud-notifier";
my $retcode = 0;
my $piddir = "/run/ngcp-fraud-notifier";
my $pidfile = "$piddir/ngcp-fraud-notifier.pid";
my $pf = File::Pid->new({ file => $pidfile });
local $PROGRAM_NAME = $PROGRAM_BASE;
local $OUTPUT_AUTOFLUSH = 1;
local $SIG{INT} = \&cleanup;
my $page_size = 100;
@ -30,6 +42,10 @@ GetOptions( $opts,
"verbose",
) or usage();
sub DESTROY {
cleanup();
}
sub check_params {
my @missing;
foreach my $param (@required) {
@ -149,50 +165,51 @@ sub send_email {
or die sprintf "Cannot send fraud daily lock notification to %s: $ERRNO",
$email->header('To');
update_notify_status($event);
return;
}
sub lock_customer {
my ($event, $subscribers) = @_;
sub update_notify_status {
my $event = shift;
my $client = new NGCP::API::Client;
$client->set_verbose($opts->{verbose});
my $uri = '/api/customers/'.$event->{id};
my $id = sprintf("%d-%s-%s",
@{$event}{qw(id interval interval_date)});
my $now = strftime('%Y-%m-%d %H:%M:%S', localtime(time));
my $uri = '/api/customerfraudevents/'.$id;
my $data = [ { op => 'replace',
path => '/status',
value => 'locked' } ];
path => '/notify_status',
value => 'notified' },
{ op => 'replace',
path => '/notified_at',
value => $now } ];
my $res = $client->request("PATCH", $uri, $data);
if ($res->status_line =~ /200 OK/) {
foreach my $subscriber (@{$subscribers}) {
$uri = '/api/subscribers/'.$subscriber->{id};
$data = [ { op => 'replace',
path => '/status',
value => 'locked' },
{ op => 'replace',
path => '/lock',
value => $event->{interval_lock} } ];
$res = $client->request("PATCH", $uri, $data);
}
}
return;
}
sub main {
if (my $num = $pf->running) {
print "$PROGRAM_BASE is already running.\n";
$retcode = 1;
exit $retcode;
}
mkdir $piddir unless -e $piddir;
$pf->write;
check_params();
load_config();
my $events = get_data(sprintf('/api/customerfraudevents/?no_count=true&interval=%s',
$interval),
my $events = get_data(sprintf('/api/customerfraudevents/?no_count=true&notify_status=%s',
'new'),
'customerfraudevents');
foreach my $event (@{$events}) {
my $subscribers = get_data(sprintf('/api/subscribers/?customer_id=%d',
$event->{id}),
'subscribers');
$event->{interval} = 'day';
if (defined $event->{interval_lock} && $event->{interval_lock} > 0) {
lock_customer($event, $subscribers);
}
if ($event->{interval_notify}) {
eval {
send_email($event, $subscribers);
@ -203,25 +220,34 @@ sub main {
return;
}
main();
sub cleanup {
$pf->remove;
rmdir $piddir if $piddir;
}
eval { main() };
if ($EVAL_ERROR) {
print STDERR $EVAL_ERROR;
$retcode = 1;
}
exit 0;
exit $retcode;
__END__
=head1 NAME
ngcp-fraud-daily-lock - checks for contract balances above fraud limit thresholds
ngcp-fraud-notifier - sends fraud notifications for customers that exceed the threshold
=head1 SYNOPSIS
B<ngcp-fraud-daily-lock> [I<options>...]
B<ngcp-fraud-nofifier> [I<options>...]
=head1 DESCRIPTION
B<This program> checks for contract balances above fraud limit warning
thresholds and sends email notifications about the incidents as applying
actions on such contracts (e.g. lock). Interval: 'day'.
thresholds and sends email notifications about the incidents.
=head1 OPTIONS
@ -256,7 +282,7 @@ Kirill Solomko <ksolomko@sipwise.com>
=head1 LICENSE
Copyright (C) 2016 Sipwise GmbH, Austria
Copyright (C) 2019 Sipwise GmbH, Austria
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

@ -1,3 +1,2 @@
bin/ngcp-credit-warning usr/sbin/
bin/ngcp-fraud-auto-lock usr/sbin/
bin/ngcp-fraud-daily-lock usr/sbin/
bin/ngcp-fraud-notifier usr/sbin/

Loading…
Cancel
Save