diff --git a/lib/NGCP/Panel/Controller/Billing.pm b/lib/NGCP/Panel/Controller/Billing.pm index a183ebd313..23496fd0f7 100644 --- a/lib/NGCP/Panel/Controller/Billing.pm +++ b/lib/NGCP/Panel/Controller/Billing.pm @@ -529,7 +529,7 @@ sub peaktime_specials_delete :Chained('peaktime_specials_base') :PathPart('delet $c->stash->{special_result}->delete; } -sub peaktime_specials_create :Chained('peaktimes_list') :PathPart('create') :Args(0) { +sub peaktime_specials_create :Chained('peaktimes_list') :PathPart('date/create') :Args(0) { my ($self, $c) = @_; $self->load_weekdays($c); diff --git a/lib/NGCP/Panel/Controller/Peering.pm b/lib/NGCP/Panel/Controller/Peering.pm index e6438eeb2e..24c502240e 100644 --- a/lib/NGCP/Panel/Controller/Peering.pm +++ b/lib/NGCP/Panel/Controller/Peering.pm @@ -4,8 +4,10 @@ use namespace::autoclean; BEGIN { extends 'Catalyst::Controller'; } -use NGCP::Panel::Form::PeeringGroup; use NGCP::Panel::Utils; +use NGCP::Panel::Form::PeeringGroup; +use NGCP::Panel::Form::PeeringRule; +use NGCP::Panel::Form::PeeringServer; sub group_list :Chained('/') :PathPart('peering') :CaptureArgs(0) :Args(0) { my ( $self, $c ) = @_; @@ -39,6 +41,7 @@ sub base :Chained('group_list') :PathPart('') :CaptureArgs(1) :Args(0) { unless($group_id && $group_id->is_integer) { $c->flash(messages => [{type => 'error', text => 'Invalid group id detected!'}]); $c->response->redirect($c->uri_for()); + $c->detach; return; } @@ -46,6 +49,7 @@ sub base :Chained('group_list') :PathPart('') :CaptureArgs(1) :Args(0) { unless(defined($res)) { $c->flash(messages => [{type => 'error', text => 'Peering Group does not exist!'}]); $c->response->redirect($c->uri_for()); + $c->detach; return; } $c->stash(group => {$res->get_columns}); @@ -68,9 +72,13 @@ sub edit :Chained('base') :PathPart('edit') { back_uri => $c->req->uri, ); if($posted && $form->validated) { - $c->stash->{group_result}->update($form->custom_get_values); - - $c->flash(messages => [{type => 'success', text => 'Peering Group successfully changed!'}]); + try { + $c->stash->{group_result}->update($form->custom_get_values); + $c->flash(messages => [{type => 'success', text => 'Peering Group successfully changed!'}]); + } catch (DBIx::Class::Exception $e) { + $c->flash(messages => [{type => 'error', text => 'Update of peering group failed.'}]); + $c->log->info("Update failed: " . $e); + }; $c->response->redirect($c->uri_for()); return; } @@ -82,15 +90,14 @@ sub edit :Chained('base') :PathPart('edit') { sub delete :Chained('base') :PathPart('delete') { my ($self, $c) = @_; - return unless (defined $c->stash->{group_result}); try { $c->stash->{group_result}->delete; $c->flash(messages => [{type => 'success', text => 'Peering Group successfully deleted!'}]); } catch (DBIx::Class::Exception $e) { $c->flash(messages => [{type => 'error', text => 'Delete failed.'}]); + $c->log->info("Delete failed: " . $e); }; $c->response->redirect($c->uri_for()); - } sub create :Chained('group_list') :PathPart('create') :Args(0) { @@ -108,9 +115,14 @@ sub create :Chained('group_list') :PathPart('create') :Args(0) { ); if($form->validated) { my $formdata = $form->custom_get_values; - $c->model('provisioning')->resultset('voip_peer_groups')->create( - $formdata ); - $c->flash(messages => [{type => 'success', text => 'Peering group successfully created!'}]); + try { + $c->model('provisioning')->resultset('voip_peer_groups')->create( + $formdata ); + $c->flash(messages => [{type => 'success', text => 'Peering group successfully created!'}]); + } catch (DBIx::Class::Exception $e) { + $c->flash(rules_messages => [{type => 'error', text => 'Creation of peering group failed.'}]); + $c->log->info("Create failed: " . $e); + }; $c->response->redirect($c->uri_for_action('/peering/root')); return; } @@ -120,6 +132,231 @@ sub create :Chained('group_list') :PathPart('create') :Args(0) { $c->stash(form => $form); } +sub servers_list :Chained('base') :PathPart('servers') :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'); +} + +sub servers_root :Chained('servers_list') :PathPart('') :Args(0) { + my ($self, $c) = @_; +} + +sub servers_ajax :Chained('servers_list') :PathPart('s_ajax') :Args(0) { + my ($self, $c) = @_; + + my $resultset = $c->stash->{group_result}->voip_peer_hosts; + + $c->forward( "/ajax_process_resultset", [$resultset, + ["id", "name", "ip", "host", "port", "transport", "weight"], + [1,2,3,4,6]]); + + $c->detach( $c->view("JSON") ); +} + +sub servers_create :Chained('servers_list') :PathPart('create') :Args(0) { + my ($self, $c) = @_; + + my $form = NGCP::Panel::Form::PeeringServer->new; + $form->process( + posted => ($c->request->method eq 'POST'), + params => $c->request->params, + action => $c->uri_for_action('/peering/servers_create', [$c->req->captures->[0]]), + ); + if($form->validated) { + try { + $c->stash->{group_result}->voip_peer_hosts->create( $form->fif ); + $c->flash(messages => [{type => 'success', text => 'Peering server successfully created!'}]); + } catch (DBIx::Class::Exception $e) { + $c->flash(messages => [{type => 'error', text => 'Creation of Peering server failed.'}]); + $c->log->info("Create failed: " . $e); + }; + $c->response->redirect($c->stash->{sr_list_uri}); + return; + } + + $c->stash(close_target => $c->stash->{sr_list_uri}); + $c->stash(servers_create_flag => 1); + $c->stash(servers_form => $form); +} + +sub servers_base :Chained('servers_list') :PathPart('') :CaptureArgs(1) { + my ($self, $c, $server_id) = @_; + + unless($server_id && $server_id->is_integer) { + $c->flash(messages => [{type => 'error', text => 'Invalid peering sever (host) id detected!'}]); + $c->response->redirect($c->stash->{sr_list_uri}); + $c->detach; + return; + } + + my $res = $c->stash->{group_result}->voip_peer_hosts->find($server_id); + unless(defined($res)) { + $c->flash(messages => [{type => 'error', text => 'Peering Server does not exist!'}]); + $c->response->redirect($c->stash->{sr_list_uri}); + $c->detach; + return; + } + $c->stash(server => {$res->get_columns}); + $c->stash(server_result => $res); +} + +sub servers_edit :Chained('servers_base') :PathPart('edit') :Args(0) { + my ($self, $c) = @_; + + my $posted = ($c->request->method eq 'POST'); + my $form = NGCP::Panel::Form::PeeringServer->new; + $form->process( + posted => 1, + params => $posted ? $c->request->params : $c->stash->{server}, + action => $c->uri_for_action('/peering/servers_edit', $c->req->captures) + ); + if($posted && $form->validated) { + try { + $c->stash->{server_result}->update($form->fif); + $c->flash(messages => [{type => 'success', text => 'Peering Server successfully changed!'}]); + } catch (DBIx::Class::Exception $e) { + $c->flash(messages => [{type => 'error', text => 'Updating of Peering server failed.'}]); + $c->log->info("Update failed: " . $e); + }; + + $c->response->redirect($c->stash->{sr_list_uri}); + return; + } + + $c->stash(close_target => $c->stash->{sr_list_uri}); + $c->stash(servers_form => $form); + $c->stash(servers_edit_flag => 1); +} + +sub servers_delete :Chained('servers_base') :PathPart('delete') :Args(0) { + my ($self, $c) = @_; + + try { + $c->stash->{server_result}->delete; + $c->flash(messages => [{type => 'success', text => 'Peering Server successfully deleted!'}]); + } catch (DBIx::Class::Exception $e) { + $c->flash(rules_messages => [{type => 'error', text => 'Delete failed.'}]); + $c->log->info("Delete failed: " . $e); + }; + $c->response->redirect($c->stash->{sr_list_uri}); +} + +sub servers_preferences :Chained('servers_base') :PathPart('preferences') :Args(0) { + +} + +sub rules_list :Chained('base') :PathPart('rules') :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'); +} + +sub rules_ajax :Chained('rules_list') :PathPart('r_ajax') :Args(0) { + my ($self, $c) = @_; + + my $resultset = $c->stash->{group_result}->voip_peer_rules; + + $c->forward( "/ajax_process_resultset", [$resultset, + ["id", "callee_prefix", "callee_pattern", "caller_pattern", "description"], + [1,2,3,4]]); + + $c->detach( $c->view("JSON") ); +} + +sub rules_create :Chained('rules_list') :PathPart('create') :Args(0) { + my ($self, $c) = @_; + + my $form = NGCP::Panel::Form::PeeringRule->new; + $form->process( + posted => ($c->request->method eq 'POST'), + params => $c->request->params, + action => $c->uri_for_action('/peering/rules_create', [$c->req->captures->[0]]), + ); + if($form->validated) { + try { + $c->stash->{group_result}->voip_peer_rules->create( $form->fif ); + $c->flash(rules_messages => [{type => 'success', text => 'Peering rule successfully created!'}]); + } catch (DBIx::Class::Exception $e) { + $c->flash(rules_messages => [{type => 'error', text => 'Create failed.'}]); + $c->log->info("Create failed: " . $e); + }; + $c->response->redirect($c->stash->{sr_list_uri}); + return; + } + + $c->stash(close_target => $c->stash->{sr_list_uri}); + $c->stash(rules_create_flag => 1); + $c->stash(rules_form => $form); +} + +sub rules_base :Chained('rules_list') :PathPart('') :CaptureArgs(1) { + my ($self, $c, $rule_id) = @_; + + unless($rule_id && $rule_id->is_integer) { + $c->flash(rules_messages => [{type => 'error', text => 'Invalid peering rule id detected!'}]); + $c->response->redirect($c->stash->{sr_list_uri}); + $c->detach; + return; + } + + my $res = $c->stash->{group_result}->voip_peer_rules->find($rule_id); + unless(defined($res)) { + $c->flash(rules_messages => [{type => 'error', text => 'Peering Rule does not exist!'}]); + $c->response->redirect($c->stash->{sr_list_uri}); + $c->detach; + return; + } + $c->stash(rule => {$res->get_columns}); + $c->stash(rule_result => $res); +} + +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::PeeringRule->new; + $form->process( + posted => 1, + params => $posted ? $c->request->params : $c->stash->{rule}, + action => $c->uri_for_action('/peering/rules_edit', $c->req->captures) + ); + if($posted && $form->validated) { + try { + $c->stash->{rule_result}->update($form->fif); + $c->flash(rules_messages => [{type => 'success', text => 'Peering Rule successfully changed!'}]); + } catch (DBIx::Class::Exception $e) { + $c->flash(rules_messages => [{type => 'error', text => 'Edit failed.'}]); + $c->log->info("Update failed: " . $e); + }; + $c->response->redirect($c->stash->{sr_list_uri}); + return; + } + + $c->stash(close_target => $c->stash->{sr_list_uri}); + $c->stash(rules_form => $form); + $c->stash(rules_edit_flag => 1); +} + +sub rules_delete :Chained('rules_base') :PathPart('delete') :Args(0) { + my ($self, $c) = @_; + + try { + $c->stash->{rule_result}->delete; + $c->flash(rules_messages => [{type => 'success', text => 'Peering Rule successfully deleted!'}]); + } catch (DBIx::Class::Exception $e) { + $c->flash(rules_messages => [{type => 'error', text => 'Delete failed.'}]); + $c->log->info("Delete failed: " . $e); + }; + $c->response->redirect($c->stash->{sr_list_uri}); +} + __PACKAGE__->meta->make_immutable; 1; @@ -170,6 +407,69 @@ Delete a peering group. Show a modal to create a new peering group. +=head2 servers_list + +Basis for peering servers. Chains from L. + +=head2 servers_root + +Display peering servers and peering groups through +F template. Uses datatables. + +=head2 servers_ajax + +Get provisioning.voip_peer_hosts from the database and output them as JSON. +The format is meant for parsing with datatables. +Only returns data from the current peering group. + +=head2 servers_create + +Show a modal to create a new peering server. + +=head2 servers_base + +Fetch a provisioning.voip_peer_hosts from the database by its id. +Only searches data that belongs to the current peering group. + +=head2 servers_edit + +Show a modal to edit a peering server. + +=head2 servers_delete + +Delete a peering server. + +=head2 servers_preferences + +Not yet implemented. + +=head2 rules_list + +Basis for peering rules. Chains from L. + +=head2 rules_ajax + +Get provisioning.voip_peer_rules from the database and output them as JSON. +The format is meant for parsing with datatables. +Only returns data from the current peering group. + +=head2 rules_create + +Show a modal to create a new peering rule. + +=head2 rules_base + +Fetch a provisioning.voip_peer_rules from the database by its id. +Only searches data that belongs to the current peering group. + +=head2 rules_edit + +Show a modal to edit a peering rule. + +=head2 rules_delete + +Delete a peering rule. + =head1 AUTHOR Gerhard Jungwirth C<< >> diff --git a/lib/NGCP/Panel/Form/PeeringRule.pm b/lib/NGCP/Panel/Form/PeeringRule.pm new file mode 100644 index 0000000000..58a73f0af9 --- /dev/null +++ b/lib/NGCP/Panel/Form/PeeringRule.pm @@ -0,0 +1,74 @@ +package NGCP::Panel::Form::PeeringRule; + +use HTML::FormHandler::Moose; +use Moose; +extends 'HTML::FormHandler'; +use Moose::Util::TypeConstraints; + +use HTML::FormHandler::Widget::Block::Bootstrap; + +has '+widget_wrapper' => ( default => 'Bootstrap' ); +sub build_render_list {[qw/fields actions/]} +sub build_form_element_class { [qw/form-horizontal/] } + +has_field 'callee_prefix' => ( + type => 'Text', +); + +has_field 'callee_pattern' => ( + type => 'Text', +); + +has_field 'caller_pattern' => ( + type => 'Text', +); + +has_field 'description' => ( + type => 'Text', +); + +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/ callee_prefix callee_pattern caller_pattern description /], +); + +has_block 'actions' => ( + tag => 'div', + class => [qw/modal-footer/], + render_list => [qw/save/], +); + +1; + +__END__ + +=head1 NAME + +NGCP::Panel::Form::PeeringRule + +=head1 DESCRIPTION + +- + +=head1 METHODS + +=head1 AUTHOR + +Gerhard Jungwirth + +=head1 LICENSE + +This library is free software. You can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + +# vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Form/PeeringServer.pm b/lib/NGCP/Panel/Form/PeeringServer.pm new file mode 100644 index 0000000000..291a869d23 --- /dev/null +++ b/lib/NGCP/Panel/Form/PeeringServer.pm @@ -0,0 +1,95 @@ +package NGCP::Panel::Form::PeeringServer; + +use HTML::FormHandler::Moose; +use Moose; +extends 'HTML::FormHandler'; +use Moose::Util::TypeConstraints; + +use HTML::FormHandler::Widget::Block::Bootstrap; + +has '+widget_wrapper' => ( default => 'Bootstrap' ); +sub build_render_list {[qw/fields actions/]} +sub build_form_element_class { [qw/form-horizontal/] } + +has_field 'name' => ( + type => 'Text', + required => 1, +); + +has_field 'ip' => ( + type => 'Text', #IP Address + required => 1, + label => 'IP Address', +); + +has_field 'host' => ( + type => 'Text', + label => 'Hostname', +); + +has_field 'port' => ( + type => 'PosInteger', + max_range => 65535, + default => '5060', +); + +has_field 'transport' => ( + type => 'Select', + label => 'Protocol', + options => [ + { value => '1', label => 'UDP' }, + { value => '2', label => 'TCP' }, + { value => '3', label => 'TLS' }, + ], +); + +has_field 'weight' => ( + type => 'PosInteger', + max_range => 25, +); + +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/ name ip host port transport weight /], +); + +has_block 'actions' => ( + tag => 'div', + class => [qw/modal-footer/], + render_list => [qw/save/], +); + +1; + +__END__ + +=head1 NAME + +NGCP::Panel::Form::PeeringServer + +=head1 DESCRIPTION + +- + +=head1 METHODS + +=head1 AUTHOR + +Gerhard Jungwirth + +=head1 LICENSE + +This library is free software. You can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + +# vim: set tabstop=4 expandtab: diff --git a/share/templates/helpers/datatables.tt b/share/templates/helpers/datatables.tt index 9f1039cf04..2b50979cf1 100644 --- a/share/templates/helpers/datatables.tt +++ b/share/templates/helpers/datatables.tt @@ -70,7 +70,7 @@ $(document).ready(function() { [% IF helper.messages -%]
diff --git a/share/templates/peering/servers_rules.tt b/share/templates/peering/servers_rules.tt new file mode 100644 index 0000000000..a77aeab5df --- /dev/null +++ b/share/templates/peering/servers_rules.tt @@ -0,0 +1,43 @@ +[% site_config.title = 'SIP Peering Group ' _ group.name -%] +[% + helper.name = 'Peering Servers'; + helper.messages = messages; + helper.column_titles = [ '#', 'Name', 'IP Address', 'Hostname', 'Port', 'Protocol', 'Weight' ]; + helper.column_fields = [ 'id', 'name', 'ip', 'host', 'port', 'transport', 'weight' ]; + + helper.close_target = close_target; + helper.create_flag = servers_create_flag; + helper.edit_flag = servers_edit_flag; + helper.form_object = servers_form; + helper.has_edit = 1; + helper.has_delete = 1; + helper.ajax_uri = c.uri_for_action( "/peering/servers_ajax", [c.req.captures.0] ); + helper.base_uri = c.uri_for_action( "/peering/servers_root", [c.req.captures.0] ); + + helper.extra_buttons = [ + [ 'Preferences', 'preferences'], + ]; + + PROCESS 'helpers/datatables.tt'; +-%] + +[% + helper.name = 'Peering Rules'; + helper.messages = rules_messages; + helper.column_titles = [ '#', 'Callee Prefix', 'Callee Pattern', 'Caller Pattern', 'Description' ]; + helper.column_fields = [ 'id', 'callee_prefix', 'callee_pattern', 'caller_pattern', 'description' ]; + + helper.close_target = close_target; + helper.create_flag = rules_create_flag; + helper.edit_flag = rules_edit_flag; + helper.form_object = rules_form; + helper.has_edit = 1; + helper.has_delete = 1; + helper.ajax_uri = c.uri_for_action( "/peering/rules_ajax", [c.req.captures.0] ); + helper.base_uri = c.uri_for( group.id, "rules" ); + + helper.extra_buttons = undef; + + PROCESS 'helpers/datatables.tt'; +-%] +[% # vim: set tabstop=4 syntax=html expandtab: -%]