TT#2766 Implement inbound peering rules.

This is panel only so far, API to be done.

Change-Id: Ibc66595b3cacf15d681144f52188c525a4c230d7
changes/41/8041/2
Andreas Granig 9 years ago
parent ecc390c618
commit 031bfebada

@ -6,6 +6,7 @@ use parent 'Catalyst::Controller';
use NGCP::Panel::Form::Peering::Group;
use NGCP::Panel::Form::Peering::Rule;
use NGCP::Panel::Form::Peering::InboundRule;
use NGCP::Panel::Form::Peering::Server;
use NGCP::Panel::Utils::DialogicImg;
use NGCP::Panel::Utils::Message;
@ -95,6 +96,15 @@ sub base :Chained('group_list') :PathPart('') :CaptureArgs(1) {
{ name => 'description', search => 1, title => $c->loc('Description') },
{ name => 'enabled', search => 1, title => $c->loc('Enabled') },
]);
$c->stash->{inbound_rules_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [
{ name => 'priority', search => 0, title => $c->loc('Priority') },
{ name => 'id', search => 1, title => $c->loc('#') },
{ name => 'field', search => 1, title => $c->loc('Field') },
{ name => 'pattern', search => 1, title => $c->loc('Pattern') },
{ name => 'reject_code', search => 1, title => $c->loc('Reject Code') },
{ name => 'reject_reason', search => 1, title => $c->loc('Reject Reason') },
{ name => 'enabled', search => 1, title => $c->loc('Enabled') },
]);
$c->stash(group => {$res->get_columns});
@ -107,7 +117,7 @@ sub edit :Chained('base') :PathPart('edit') {
my ($self, $c) = @_;
my $posted = ($c->request->method eq 'POST');
my $form = NGCP::Panel::Form::Peering::Group->new;
my $form = NGCP::Panel::Form::Peering::Group->new(ctx => $c);
my $params = { $c->stash->{group_result}->get_inflated_columns };
$params->{contract}{id} = delete $params->{peering_contract_id};
$params = merge($params, $c->session->{created_objects});
@ -176,7 +186,7 @@ sub create :Chained('group_list') :PathPart('create') :Args(0) {
my ($self, $c) = @_;
my $posted = ($c->request->method eq 'POST');
my $form = NGCP::Panel::Form::Peering::Group->new;
my $form = NGCP::Panel::Form::Peering::Group->new(ctx => $c);
my $params = {};
$params = merge($params, $c->session->{created_objects});
$form->process(
@ -568,7 +578,7 @@ sub rules_create :Chained('rules_list') :PathPart('create') :Args(0) {
my ($self, $c) = @_;
my $posted = ($c->request->method eq 'POST');
my $form = NGCP::Panel::Form::Peering::Rule->new;
my $form = NGCP::Panel::Form::Peering::Rule->new(ctx => $c);
$form->process(
posted => $posted,
params => $c->request->params,
@ -640,7 +650,7 @@ sub rules_edit :Chained('rules_base') :PathPart('edit') :Args(0) {
my ($self, $c) = @_;
my $posted = ($c->request->method eq 'POST');
my $form = NGCP::Panel::Form::Peering::Rule->new;
my $form = NGCP::Panel::Form::Peering::Rule->new(ctx => $c);
$form->process(
posted => $posted,
params => $c->request->params,
@ -701,6 +711,230 @@ sub rules_delete :Chained('rules_base') :PathPart('delete') :Args(0) {
return;
}
sub inbound_rules_list :Chained('base') :PathPart('inboundrules') :CaptureArgs(0) {
my ($self, $c) = @_;
my $sr_list_uri = $c->uri_for_action(
'/peering/servers_root', [$c->req->captures->[0]]);
$c->stash(sr_list_uri => $sr_list_uri);
$c->stash(template => 'peering/servers_rules.tt');
return;
}
sub inbound_rules_ajax :Chained('inbound_rules_list') :PathPart('r_ajax') :Args(0) {
my ($self, $c) = @_;
my $resultset = $c->stash->{group_result}->voip_peer_inbound_rules->search(undef, {
order_by => {'-asc' => 'priority'},
});
NGCP::Panel::Utils::Datatables::process($c, $resultset, $c->stash->{inbound_rules_dt_columns});
$c->detach( $c->view("JSON") );
return;
}
sub inbound_rules_create :Chained('inbound_rules_list') :PathPart('create') :Args(0) {
my ($self, $c) = @_;
my $posted = ($c->request->method eq 'POST');
my $form = NGCP::Panel::Form::Peering::InboundRule->new(ctx => $c);
$form->process(
posted => $posted,
params => $c->request->params,
);
NGCP::Panel::Utils::Navigation::check_form_buttons(
c => $c,
form => $form,
fields => {},
back_uri => $c->req->uri,
);
if($posted && $form->validated) {
try {
my $last_priority = $c->stash->{group_result}->voip_peer_inbound_rules->get_column('priority')->max() || 49;
$form->values->{priority} = $last_priority + 1;
$c->stash->{group_result}->voip_peer_inbound_rules->create($form->values);
$c->stash->{group_result}->update({has_inbound_rules => 1});
NGCP::Panel::Utils::Message::info(
c => $c,
desc => $c->loc('Inbound peering rule successfully created'),
);
} catch ($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
error => $e,
desc => $c->loc('Failed to create inbound peering rule'),
);
};
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/peering/servers_root', [$c->req->captures->[0]]));
}
$c->stash(
close_target => $c->uri_for_action('/peering/servers_root', [$c->req->captures->[0]]),
inbound_rules_create_flag => 1,
inbound_rules_form => $form,
);
return;
}
sub inbound_rules_base :Chained('inbound_rules_list') :PathPart('') :CaptureArgs(1) {
my ($self, $c, $rule_id) = @_;
unless($rule_id && is_int($rule_id)) {
NGCP::Panel::Utils::Message::error(
c => $c,
log => 'Invalid inbound peering rule id detected',
desc => $c->loc('Invalid inbound peering rule id detected'),
);
$c->response->redirect($c->stash->{sr_list_uri});
$c->detach;
return;
}
my $res = $c->stash->{group_result}->voip_peer_inbound_rules->find($rule_id);
unless(defined($res)) {
NGCP::Panel::Utils::Message::error(
c => $c,
log => 'Inbound Peering Rule does not exist',
desc => $c->loc('Inbound Peering Rule does not exist'),
);
$c->response->redirect($c->stash->{sr_list_uri});
$c->detach;
return;
}
$c->stash(inbound_rule => {$res->get_columns});
$c->stash(inbound_rule_result => $res);
return;
}
sub inbound_rules_edit :Chained('inbound_rules_base') :PathPart('edit') :Args(0) {
my ($self, $c) = @_;
my $posted = ($c->request->method eq 'POST');
my $form = NGCP::Panel::Form::Peering::InboundRule->new(ctx => $c);
$form->process(
posted => $posted,
params => $c->request->params,
item => $c->stash->{inbound_rule},
);
NGCP::Panel::Utils::Navigation::check_form_buttons(
c => $c,
form => $form,
fields => {},
back_uri => $c->req->uri,
);
if($posted && $form->validated) {
try {
$c->stash->{inbound_rule_result}->update($form->values);
NGCP::Panel::Utils::Message::info(
c => $c,
desc => $c->loc('Inbound peering rule successfully changed'),
);
} catch ($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
error => $e,
desc => $c->loc('Failed to update inbound peering rule'),
);
};
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/peering/servers_root', [$c->req->captures->[0]]));
}
$c->stash(
close_target => $c->uri_for_action('/peering/servers_root', [$c->req->captures->[0]]),
inbound_rules_form => $form,
inbound_rules_edit_flag => 1,
);
return;
}
sub inbound_rules_delete :Chained('inbound_rules_base') :PathPart('delete') :Args(0) {
my ($self, $c) = @_;
try {
$c->stash->{inbound_rule_result}->delete;
unless($c->stash->{group_result}->voip_peer_inbound_rules->count)
{
$c->stash->{group_result}->update({has_inbound_rules => 0});
}
NGCP::Panel::Utils::Message::info(
c => $c,
data => { $c->stash->{inbound_rule_result}->get_inflated_columns },
desc => $c->loc('Inbound peering rule successfully deleted'),
);
} catch ($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
error => $e,
desc => $c->loc('Failed to delete inbound peering rule'),
);
};
NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for_action('/peering/servers_root', [$c->req->captures->[0]]));
return;
}
sub inbound_rules_up :Chained('inbound_rules_base') :PathPart('up') :Args(0) {
my ($self, $c) = @_;
my $elem = $c->stash->{inbound_rule_result};
my $swap_elem = $c->stash->{group_result}->voip_peer_inbound_rules->search({
priority => { '<' => $elem->priority },
},{
order_by => {'-desc' => 'priority'},
})->first;
try {
if ($swap_elem) {
my $tmp_priority = $swap_elem->priority;
$swap_elem->priority($elem->priority);
$elem->priority($tmp_priority);
$swap_elem->update;
$elem->update;
} else {
my $last_priority = $c->stash->{group_result}->voip_peer_inbound_rules->get_column('priority')->min() || 1;
$elem->priority(int($last_priority) - 1);
$elem->update;
}
} catch($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
error => $e,
desc => $c->loc('Failed to move inbound peering rule up.'),
);
}
return;
}
sub inbound_rules_down :Chained('inbound_rules_base') :PathPart('down') :Args(0) {
my ($self, $c) = @_;
my $elem = $c->stash->{inbound_rule_result};
my $swap_elem = $c->stash->{group_result}->voip_peer_inbound_rules->search({
priority => { '>' => $elem->priority },
},{
order_by => {'-asc' => 'priority'},
})->first;
try {
if ($swap_elem) {
my $tmp_priority = $swap_elem->priority;
$swap_elem->priority($elem->priority);
$elem->priority($tmp_priority);
$swap_elem->update;
$elem->update;
} else {
my $last_priority = $c->stash->{group_result}->voip_peer_inbound_rules->get_column('priority')->max() || 49;
$elem->priority(int($last_priority) + 1);
$elem->update;
}
} catch($e) {
NGCP::Panel::Utils::Message::error(
c => $c,
error => $e,
desc => $c->loc('Failed to move inbound peering rule down.'),
);
}
return;
}
__PACKAGE__->meta->make_immutable;

@ -0,0 +1,112 @@
package NGCP::Panel::Form::Peering::InboundRule;
use Sipwise::Base;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler';
use HTML::FormHandler::Widget::Block::Bootstrap;
has '+widget_wrapper' => ( default => 'Bootstrap' );
has_field 'submitid' => ( type => 'Hidden' );
sub build_render_list {[qw/submitid fields actions/]}
sub build_form_element_class {[qw(form-horizontal)]}
has_field 'field' => (
type => 'Select',
label => 'Match Field',
options => [
{ value => 'from_user', label => 'From-User' },
{ value => 'from_domain', label => 'From-Domain' },
{ value => 'from_uri', label => 'From-URI' },
{ value => 'to_user', label => 'To-User' },
{ value => 'to_domain', label => 'To-Domain' },
{ value => 'to_uri', label => 'To-URI' },
{ value => 'ruri_user', label => 'RURI-User' },
{ value => 'ruri_domain', label => 'RURI-Domain' },
{ value => 'ruri_uri', label => 'RURI-URI' },
{ value => 'pai_user', label => 'PAI-User' },
{ value => 'pai_domain', label => 'PAI-Domain' },
{ value => 'pai_uri', label => 'PAI-URI' },
],
element_attr => {
rel => ['tooltip'],
title => ['The field of the inbound SIP message to match the pattern against']
},
);
has_field 'pattern' => (
type => '+NGCP::Panel::Field::Regexp',
max_length => 1023,
element_attr => {
rel => ['tooltip'],
title => [q!A POSIX regex matching against the specified field (e.g. '^sip:.+@example\.org$' or '^sip:431') when matching against a full URI!]
},
);
has_field 'reject_code' => (
type => 'PosInteger',
not_nullable => 0,
range_start => 400,
range_end => 699,
element_attr => {
rel => ['tooltip'],
title => ['If specified, the call is rejected if the source IP of the request is found in a peering server of the group, but the given pattern does not match; Range of 400-699']
},
);
has_field 'reject_reason' => (
type => 'Text',
not_nullable => 0,
max_length => 64,
element_attr => {
rel => ['tooltip'],
title => ['If reject code is specified and the call is rejected, the reason in the response is taken from this value']
},
);
has_field 'enabled' => (
type => 'Boolean',
label => 'Enabled',
default => 1,
element_attr => {
rel => ['tooltip'],
title => ['Rule enabled state.'],
},
);
has_field 'save' => (
type => 'Submit',
value => 'Save',
element_class => [qw/btn btn-primary/],
label => '',
);
has_block 'fields' => (
tag => 'div',
class => [qw/modal-body/],
render_list => [qw/field pattern reject_code reject_reason enabled/],
);
has_block 'actions' => (
tag => 'div',
class => [qw/modal-footer/],
render_list => [qw/save/],
);
sub validate {
my ($self) = @_;
my $c = $self->ctx;
my $reason = $self->field('reject_reason');
my $code = $self->field('reject_code');
if(defined $code->value && !defined $reason->value) {
return $reason->add_error($c->loc('reject reason must be filled if reject code is filled'));
} elsif(defined $reason->value && !defined $code->value) {
return $code->add_error($c->loc('reject code must be filled if reject reason is filled'));
}
return;
}
1;

@ -5,6 +5,7 @@
helper.identifier = 'peering_servers';
helper.messages = messages;
helper.dt_columns = server_dt_columns;
helper.length_change = 1;
helper.close_target = close_target;
helper.create_flag = servers_create_flag;
@ -32,9 +33,10 @@
-%]
<div class="ngcp-separator"></div>
<h3>[% c.loc('Peering Rules') %]</h3>
<h3>[% c.loc('Outbound Peering Rules') %]</h3>
<p>ANY of the rules must match to choose the peering group for outbound calls.</p>
[%
helper.name = c.loc('Peering Rule');
helper.name = c.loc('Outbound Peering Rule');
helper.identifier = 'PeeringRules';
helper.messages = rules_messages;
helper.dt_columns = rules_dt_columns;
@ -42,6 +44,7 @@
helper.create_flag = rules_create_flag;
helper.edit_flag = rules_edit_flag;
helper.form_object = rules_form;
helper.length_change = 1;
helper.ajax_uri = c.uri_for_action( "/peering/rules_ajax", [c.req.captures.0] );
helper.tmpuri = c.uri_for(group.id, "rules");
@ -51,7 +54,41 @@
{ name = c.loc('Delete'), uri = helper.tmpuri _ "/'+full[\"id\"]+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' },
];
helper.top_buttons = [
{ name = c.loc('Create Peering Rule'), uri = helper.tmpuri _ "/create", icon = 'icon-star' },
{ name = c.loc('Create Outbound Peering Rule'), uri = helper.tmpuri _ "/create", icon = 'icon-star' },
];
ELSE;
helper.dt_buttons = [];
helper.top_buttons = [];
END;
PROCESS 'helpers/datatables.tt';
-%]
<div class="ngcp-separator"></div>
<h3>[% c.loc('Inbound Peering Rules') %]</h3>
<p>ALL of the rules must match to choose the peering group for inbound calls.</p>
[%
helper.name = c.loc('Inbound Peering Rule');
helper.identifier = 'InboundPeeringRules';
helper.messages = inbound_rules_messages;
helper.dt_columns = inbound_rules_dt_columns;
helper.close_target = close_target;
helper.create_flag = inbound_rules_create_flag;
helper.edit_flag = inbound_rules_edit_flag;
helper.form_object = inbound_rules_form;
helper.length_change = 1;
helper.ajax_uri = c.uri_for_action( "/peering/inbound_rules_ajax", [c.req.captures.0] );
helper.tmpuri = c.uri_for(group.id, "inboundrules");
UNLESS c.user.read_only;
helper.dt_buttons = [
{ name = c.loc('Up'), uri = helper.tmpuri _ "/'+full[\"id\"]+'/up", class = 'btn-small btn-primary', icon = 'icon-arrow-up' },
{ name = c.loc('Down'), uri = helper.tmpuri _ "/'+full[\"id\"]+'/down", class = 'btn-small btn-primary', icon = 'icon-arrow-down' },
{ name = c.loc('Edit'), uri = helper.tmpuri _ "/'+full[\"id\"]+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' },
{ name = c.loc('Delete'), uri = helper.tmpuri _ "/'+full[\"id\"]+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' },
];
helper.top_buttons = [
{ name = c.loc('Create Inbound Peering Rule'), uri = helper.tmpuri _ "/create", icon = 'icon-star' },
];
ELSE;
helper.dt_buttons = [];

Loading…
Cancel
Save