From 3fc22bd2775351093e9c327434c02d6301f81094 Mon Sep 17 00:00:00 2001 From: Gerhard Jungwirth Date: Thu, 22 Dec 2016 17:03:22 +0100 Subject: [PATCH] TT#4334 adapt soundsets and autoattendants for subadmin Change-Id: I62f5d4d6227f209ebe1e8949fe0d5db5303c30e9 --- .../Panel/Controller/API/AutoAttendants.pm | 2 +- .../Controller/API/AutoAttendantsItem.pm | 2 +- lib/NGCP/Panel/Controller/API/SoundSets.pm | 21 +++---- .../Panel/Controller/API/SoundSetsItem.pm | 4 +- lib/NGCP/Panel/Form/Sound/SubadminSet.pm | 61 +++++++++++++++++++ .../Panel/Form/Subscriber/AutoAttendantAPI.pm | 4 ++ lib/NGCP/Panel/Role/API/AutoAttendants.pm | 10 ++- lib/NGCP/Panel/Role/API/SoundSets.pm | 27 ++++++-- 8 files changed, 107 insertions(+), 24 deletions(-) create mode 100644 lib/NGCP/Panel/Form/Sound/SubadminSet.pm diff --git a/lib/NGCP/Panel/Controller/API/AutoAttendants.pm b/lib/NGCP/Panel/Controller/API/AutoAttendants.pm index fdcfe672c7..7988527b98 100644 --- a/lib/NGCP/Panel/Controller/API/AutoAttendants.pm +++ b/lib/NGCP/Panel/Controller/API/AutoAttendants.pm @@ -49,7 +49,7 @@ __PACKAGE__->config( action => { map { $_ => { ACLDetachTo => '/api/root/invalid_user', - AllowedRole => [qw/admin reseller/], + AllowedRole => [qw/admin reseller subscriberadmin/], Args => 0, Does => [qw(ACL CheckTrailingSlash RequireSSL)], Method => $_, diff --git a/lib/NGCP/Panel/Controller/API/AutoAttendantsItem.pm b/lib/NGCP/Panel/Controller/API/AutoAttendantsItem.pm index 76636f22ad..db6b4ba6d7 100644 --- a/lib/NGCP/Panel/Controller/API/AutoAttendantsItem.pm +++ b/lib/NGCP/Panel/Controller/API/AutoAttendantsItem.pm @@ -42,7 +42,7 @@ __PACKAGE__->config( action => { (map { $_ => { ACLDetachTo => '/api/root/invalid_user', - AllowedRole => [qw/admin reseller/], + AllowedRole => [qw/admin reseller subscriberadmin/], Args => 1, Does => [qw(ACL RequireSSL)], Method => $_, diff --git a/lib/NGCP/Panel/Controller/API/SoundSets.pm b/lib/NGCP/Panel/Controller/API/SoundSets.pm index b8cfb9ccc5..40886035f1 100644 --- a/lib/NGCP/Panel/Controller/API/SoundSets.pm +++ b/lib/NGCP/Panel/Controller/API/SoundSets.pm @@ -22,13 +22,13 @@ sub allowed_methods{ } sub api_description { - return 'Defines sound sets for both system and customers.'; + return 'Defines sound sets for both system and customers.'; # should allow a different description per role }; sub query_params { return [ { - param => 'customer_id', + param => 'customer_id', # should allow different params per role (no security-problem) description => 'Filter for sound sets of a specific customer', query => { first => sub { @@ -79,7 +79,7 @@ __PACKAGE__->config( action => { map { $_ => { ACLDetachTo => '/api/root/invalid_user', - AllowedRole => [qw/admin reseller/], + AllowedRole => [qw/admin reseller subscriberadmin/], Args => 0, Does => [qw(ACL CheckTrailingSlash RequireSSL)], Method => $_, @@ -182,17 +182,14 @@ sub POST :Allow { form => $form, ); - #$form //= $self->get_form($c); - #return unless $self->validate_form( - # c => $c, - # form => $form, - # resource => $resource, - #); - - if($c->user->roles eq "admin") { - } elsif($c->user->roles eq "reseller") { + if ($c->user->roles eq "admin") { + } elsif ($c->user->roles eq "reseller") { $resource->{reseller_id} = $c->user->reseller_id; + } elsif ($c->user->roles eq "subscriberadmin") { + $resource->{contract_id} = $c->user->account_id; + $resource->{reseller_id} = $c->user->contract->contact->reseller_id; } + my $reseller = $c->model('DB')->resultset('resellers')->find({ id => $resource->{reseller_id}, }); diff --git a/lib/NGCP/Panel/Controller/API/SoundSetsItem.pm b/lib/NGCP/Panel/Controller/API/SoundSetsItem.pm index d9d8f84c4a..9ecf0f6390 100644 --- a/lib/NGCP/Panel/Controller/API/SoundSetsItem.pm +++ b/lib/NGCP/Panel/Controller/API/SoundSetsItem.pm @@ -39,7 +39,7 @@ __PACKAGE__->config( action => { (map { $_ => { ACLDetachTo => '/api/root/invalid_user', - AllowedRole => [qw/admin reseller/], + AllowedRole => [qw/admin reseller subscriberadmin/], Args => 1, Does => [qw(ACL RequireSSL)], Method => $_, @@ -47,7 +47,7 @@ __PACKAGE__->config( } } @{ __PACKAGE__->allowed_methods }), @{ __PACKAGE__->get_journal_action_config(__PACKAGE__->resource_name,{ ACLDetachTo => '/api/root/invalid_user', - AllowedRole => [qw/admin reseller/], + AllowedRole => [qw/admin reseller subscriberadmin/], Does => [qw(ACL RequireSSL)], }) } }, diff --git a/lib/NGCP/Panel/Form/Sound/SubadminSet.pm b/lib/NGCP/Panel/Form/Sound/SubadminSet.pm new file mode 100644 index 0000000000..fadef60aa9 --- /dev/null +++ b/lib/NGCP/Panel/Form/Sound/SubadminSet.pm @@ -0,0 +1,61 @@ +package NGCP::Panel::Form::Sound::SubadminSet; + +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 'name' => ( + type => 'Text', + label => 'Name', + required => 1, + element_attr => { + rel => ['tooltip'], + title => ['The name of the sound set'], + }, +); + +has_field 'description' => ( + type => 'Text', + element_attr => { + rel => ['tooltip'], + title => ['The description of the sound set'], + }, +); + +has_field 'contract_default' => ( + type => 'Boolean', + label => 'Default for Subscribers', + element_attr => { + rel => ['tooltip'], + title => ['If active (and a customer is selected), this sound set is used for all existing and new subscribers within this customer if no specific sound set is specified for the subscribers'], + }, +); + +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 description contract_default/], +); + +has_block 'actions' => ( + tag => 'div', + class => [qw/modal-footer/], + render_list => [qw/save/], +); + +# TODO: inheritance? + +1; diff --git a/lib/NGCP/Panel/Form/Subscriber/AutoAttendantAPI.pm b/lib/NGCP/Panel/Form/Subscriber/AutoAttendantAPI.pm index d33a9a56ea..43efb7962e 100644 --- a/lib/NGCP/Panel/Form/Subscriber/AutoAttendantAPI.pm +++ b/lib/NGCP/Panel/Form/Subscriber/AutoAttendantAPI.pm @@ -10,6 +10,10 @@ sub build_form_element_class {return [qw(form-horizontal)]} has_field 'slots' => ( type => 'Repeatable', label => 'IVR Slots', + element_attr => { + rel => ['tooltip'], + title => ['IVR Slots. A list of items each containing the keys slot and destination. "slot" from 0-9. "destination" can be a number, username or full SIP URI.'], + }, ); has_field 'slots.slot' => ( diff --git a/lib/NGCP/Panel/Role/API/AutoAttendants.pm b/lib/NGCP/Panel/Role/API/AutoAttendants.pm index 62eea392e9..497050350f 100644 --- a/lib/NGCP/Panel/Role/API/AutoAttendants.pm +++ b/lib/NGCP/Panel/Role/API/AutoAttendants.pm @@ -23,7 +23,7 @@ sub hal_from_item { my ($self, $c, $item) = @_; my $p_subs = $item->provisioning_voip_subscriber; - my $resource = { subscriber_id => $item->id, slots => $self->autoattendants_from_subscriber($p_subs) }; + my $resource = { subscriber_id => $item->id, slots => $self->_autoattendants_from_subscriber($p_subs) }; my $hal = Data::HAL->new( links => [ @@ -70,6 +70,12 @@ sub _item_rs { }, { join => { 'contract' => 'contact' }, }); + } elsif($c->user->roles eq "subscriberadmin") { + $item_rs = $item_rs->search({ + 'provisioning_voip_subscriber.account_id' => $c->user->account_id, + }); + } else { + return; # subscriber role not allowed } return $item_rs; @@ -121,7 +127,7 @@ sub update_item { return $billing_subs; } -sub autoattendants_from_subscriber { +sub _autoattendants_from_subscriber { my ($self, $prov_subscriber) = @_; my @aas; diff --git a/lib/NGCP/Panel/Role/API/SoundSets.pm b/lib/NGCP/Panel/Role/API/SoundSets.pm index 0dea5f187c..36c5cd53e2 100644 --- a/lib/NGCP/Panel/Role/API/SoundSets.pm +++ b/lib/NGCP/Panel/Role/API/SoundSets.pm @@ -12,16 +12,23 @@ use Data::HAL::Link qw(); use HTTP::Status qw(:constants); use NGCP::Panel::Form::Sound::AdminSet; use NGCP::Panel::Form::Sound::ResellerSet; +use NGCP::Panel::Form::Sound::SubadminSet; sub _item_rs { my ($self, $c) = @_; my $item_rs = $c->model('DB')->resultset('voip_sound_sets'); - if($c->user->roles eq "admin") { - } elsif($c->user->roles eq "reseller") { + if ($c->user->roles eq "admin") { + } elsif ($c->user->roles eq "reseller") { $item_rs = $item_rs->search({ - 'reseller_id' => $c->user->reseller_id + 'reseller_id' => $c->user->reseller_id, }); + } elsif ($c->user->roles eq "subscriberadmin") { + $item_rs = $item_rs->search_rs({ + 'contract_id' => $c->user->account_id, + }); + } else { + return; # subscriber role not allowed } return $item_rs; } @@ -32,6 +39,8 @@ sub get_form { return NGCP::Panel::Form::Sound::AdminSet->new; } elsif($c->user->roles eq "reseller") { return NGCP::Panel::Form::Sound::ResellerSet->new; + } elsif ($c->user->roles eq "subscriberadmin") { + return NGCP::Panel::Form::Sound::SubadminSet->new; } } @@ -49,6 +58,7 @@ sub hal_from_item { name => 'ngcp', templated => true, ), + # nth: these should also be adapted/adaptable when using subscriber(admin) roles Data::HAL::Link->new(relation => 'collection', href => sprintf("/api/%s/", $self->resource_name)), Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'), Data::HAL::Link->new(relation => 'self', href => sprintf("%s%d", $self->dispatch_path, $item->id)), @@ -67,7 +77,9 @@ sub hal_from_item { form => $form, run => 0, ); - $resource->{customer_id} = delete $resource->{contract_id}; + if (exists $resource->{contract_id}) { + $resource->{customer_id} = delete $resource->{contract_id}; + } $resource->{id} = int($item->id); $hal->resource($resource); @@ -99,9 +111,12 @@ sub update_item { resource => $resource, ); - if($c->user->roles eq "admin") { - } elsif($c->user->roles eq "reseller") { + if ($c->user->roles eq "admin") { + } elsif ($c->user->roles eq "reseller") { $resource->{reseller_id} = $c->user->reseller_id; + } elsif ($c->user->roles eq "subscriberadmin") { + $resource->{contract_id} = $c->user->account_id; + $resource->{reseller_id} = $c->user->contract->contact->reseller_id; } my $reseller = $c->model('DB')->resultset('resellers')->find({ id => $resource->{reseller_id},