TT#34021 Allow PUT and PATCH to subscriberadmin on subscribers

Change-Id: I3c3d5b0c5d1bfd4c3c8771ed332cbf00d3d3c1dc
changes/81/19781/6
Irina Peshinskaya 8 years ago
parent 2d002f5ea2
commit cb1a3a4cd8

@ -68,6 +68,7 @@ sub GET :Allow {
$config{numbermanagement}->{auto_allow_cli} = $config_internal{numbermanagement}->{auto_allow_cli};
$config{security}->{password_web_validate} = $config_internal{security}->{password_web_validate};
$config{security}->{password_sip_validate} = $config_internal{security}->{password_sip_validate};
$config{acl} = $config_internal{acl};
$config{features} = $config_internal{features};
my $meta = {

@ -2,6 +2,7 @@ package NGCP::Panel::Controller::API::Subscribers;
use NGCP::Panel::Utils::Generic qw(:all);
use Sipwise::Base;
use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::Subscribers/;
use boolean qw(true);
use Data::HAL qw();
@ -16,6 +17,10 @@ use NGCP::Panel::Utils::ProfilePackages qw();
use NGCP::Panel::Utils::Events qw();
use UUID;
__PACKAGE__->set_config({
allowed_roles => [qw/admin reseller subscriberadmin subscriber/],
});
sub allowed_methods{
return [qw/GET POST OPTIONS HEAD/];
}
@ -258,24 +263,6 @@ sub query_params {
return $params;
}
use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::Subscribers/;
sub resource_name{
return 'subscribers';
}
sub dispatch_path{
return '/api/subscribers/';
}
sub relation{
return 'http://purl.org/sipwise/ngcp-api/#rel-subscribers';
}
__PACKAGE__->set_config({
allowed_roles => [qw/admin reseller subscriberadmin subscriber/],
});
sub GET :Allow {
my ($self, $c) = @_;
my $page = $c->request->params->{page} // 1;
@ -341,21 +328,6 @@ sub GET :Allow {
sub POST :Allow {
my ($self, $c) = @_;
if($c->user->roles eq "admin" || $c->user->roles eq "reseller") {
} elsif($c->user->roles eq "subscriber") {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
} elsif($c->user->roles eq "subscriberadmin") {
unless($c->config->{features}->{cloudpbx}) {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
}
my $customer = $self->get_customer($c, $c->user->account_id);
if($customer->get_column('product_class') ne 'pbxaccount') {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
}
}
my $schema = $c->model('DB');
$schema->set_transaction_isolation('READ COMMITTED');

@ -21,29 +21,19 @@ sub allowed_methods{
use parent qw/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::Subscribers/;
sub resource_name{
return 'subscribers';
}
sub dispatch_path{
return '/api/subscribers/';
}
__PACKAGE__->set_config({
allowed_roles => {
Default => [qw/admin reseller subscriberadmin subscriber/],
Journal => [qw/admin reseller/],
}
});
sub relation{
return 'http://purl.org/sipwise/ngcp-api/#rel-subscribers';
}
sub journal_query_params {
my($self,$query_params) = @_;
return $self->get_journal_query_params($query_params);
}
__PACKAGE__->set_config({
allowed_roles => {
Default => [qw/admin reseller subscriberadmin subscriber/],
Journal => [qw/admin reseller/],
}
});
sub GET :Allow {
my ($self, $c, $id) = @_;
@ -81,10 +71,7 @@ sub GET :Allow {
sub PUT :Allow {
my ($self, $c, $id) = @_;
if($c->user->roles eq "subscriberadmin" || $c->user->roles eq "subscriber") {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
}
return unless $self->check_write_access($c);
my $schema = $c->model('DB');
$schema->set_transaction_isolation('READ COMMITTED');
@ -118,21 +105,7 @@ sub PUT :Allow {
last unless $self->add_update_journal_item_hal($c,$hal);
$guard->commit;
if ('minimal' eq $preference) {
$c->response->status(HTTP_NO_CONTENT);
$c->response->header(Preference_Applied => 'return=minimal');
$c->response->body(q());
} else {
#$resource = $self->resource_from_item($c, $subscriber, $form);
#my $hal = $self->hal_from_item($c, $subscriber, $resource, $form);
my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new(
$hal->http_headers,
), $hal->as_json);
$c->response->headers($response->headers);
$c->response->header(Preference_Applied => 'return=representation');
$c->response->body($response->content);
}
$self->return_representation($c, 'hal' => $hal, 'preference' => $preference );
}
return;
}
@ -140,10 +113,7 @@ sub PUT :Allow {
sub PATCH :Allow {
my ($self, $c, $id) = @_;
if($c->user->roles eq "subscriberadmin" || $c->user->roles eq "subscriber") {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
}
return unless $self->check_write_access($c);
my $schema = $c->model('DB');
$schema->set_transaction_isolation('READ COMMITTED');
@ -184,21 +154,7 @@ sub PATCH :Allow {
last unless $self->add_update_journal_item_hal($c,$hal);
$guard->commit;
if ('minimal' eq $preference) {
$c->response->status(HTTP_NO_CONTENT);
$c->response->header(Preference_Applied => 'return=minimal');
$c->response->body(q());
} else {
#$resource = $self->resource_from_item($c, $subscriber, $form);
#my $hal = $self->hal_from_item($c, $subscriber, $resource, $form);
my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new(
$hal->http_headers,
), $hal->as_json);
$c->response->headers($response->headers);
$c->response->header(Preference_Applied => 'return=representation');
$c->response->body($response->content);
}
$self->return_representation($c, 'hal' => $hal, 'preference' => $preference );
}
return;
}
@ -206,10 +162,7 @@ sub PATCH :Allow {
sub DELETE :Allow {
my ($self, $c, $id) = @_;
if($c->user->roles eq "subscriber") {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
}
return unless $self->check_write_access($c);
my $guard = $c->model('DB')->txn_scope_guard;
{
@ -217,12 +170,6 @@ sub DELETE :Allow {
last unless $self->resource_exists($c, subscriber => $subscriber);
if($c->user->roles eq "subscriberadmin") {
my $customer = $self->get_customer($c, $c->user->account_id);
if($customer->get_column('product_class') ne 'pbxaccount') {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
}
my $prov_sub = $subscriber->provisioning_voip_subscriber;
if($prov_sub->is_pbx_pilot) {
$self->error($c, HTTP_FORBIDDEN, "Cannot terminate pilot subscriber");

@ -5,7 +5,6 @@ use Sipwise::Base;
use parent 'NGCP::Panel::Role::API';
use boolean qw(true);
use Data::HAL qw();
use Data::HAL::Link qw();
@ -19,6 +18,18 @@ use NGCP::Panel::Utils::Subscriber;
use NGCP::Panel::Utils::Events;
use NGCP::Panel::Utils::DateTime;
sub resource_name{
return 'subscribers';
}
sub dispatch_path{
return '/api/subscribers/';
}
sub relation{
return 'http://purl.org/sipwise/ngcp-api/#rel-subscribers';
}
sub get_form {
my ($self, $c) = @_;
@ -119,7 +130,7 @@ sub resource_from_item {
# don't leak internal info to subscribers via API for those fields
# not filtered via forms
my $contract_id = int(delete $resource{contract_id});
if($c->user->roles eq "admin" || $c->user->roles eq "reseller") {
if ($c->user->roles eq "admin" || $c->user->roles eq "reseller") {
$resource{customer_id} = $contract_id;
$resource{uuid} = $item->uuid;
@ -134,16 +145,17 @@ sub resource_from_item {
$resource{lock} = undef;
}
} else {
# fields we never want to see
foreach my $k(qw/domain_id status profile_id profile_set_id external_id/) {
delete $resource{$k};
}
if (!$self->subscriberadmin_write_access($c)) {
# fields we never want to see
foreach my $k(qw/domain_id status profile_id profile_set_id external_id/) {
delete $resource{$k};
}
# TODO: make custom filtering configurable!
foreach my $k(qw/password webpassword/) {
delete $resource{$k};
# TODO: make custom filtering configurable!
foreach my $k(qw/password webpassword/) {
delete $resource{$k};
}
}
if($c->user->roles eq "subscriberadmin") {
$resource{customer_id} = $contract_id;
}
@ -597,10 +609,7 @@ sub prepare_resource {
sub update_item {
my ($self, $c, $schema, $item, $full_resource, $resource, $form) = @_;
if($c->user->roles eq "subscriberadmin" || $c->user->roles eq "subscriber") {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
}
return unless $self->check_write_access($c);
my $subscriber = $item;
my $customer = $full_resource->{customer};
@ -817,5 +826,33 @@ sub update_item {
return $subscriber;
}
sub check_write_access {
my($self, $c) = @_;
if($c->user->roles eq "admin" || $c->user->roles eq "reseller") {
} elsif($c->user->roles eq "subscriber") {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
} elsif($c->user->roles eq "subscriberadmin") {
unless($c->config->{features}->{cloudpbx}) {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
}
my $customer = $self->get_customer($c, $c->user->account_id);
if($customer->get_column('product_class') ne 'pbxaccount') {
$self->error($c, HTTP_FORBIDDEN, "Read-only resource for authenticated role");
return;
}
}
return 1;
}
sub subscriberadmin_write_access {
my($self,$c) = @_;
if ($c->user->roles eq "subscriberadmin" && $c->config->{acl}->{subscriberadmin}->{subscribers} =~/write/ ) {
return 1;
}
return 0;
}
1;
# vim: set tabstop=4 expandtab:

@ -1,12 +1,12 @@
use strict;
use warnings;
use threads;
use Test::Collection;
use Test::FakeData;
use Test::More;
use Data::Dumper;
use Clone qw/clone/;
use threads;
#use NGCP::Panel::Utils::Subscriber;

@ -331,7 +331,46 @@ if($remote_config->{config}->{features}->{cloudpbx}){
}
$test_machine->runas('admin');
}
{#TT#34021
diag("34021: check subscriberadmin PUT and PATCH. Possible only for pbx subscriberadmin. Access priveleges:".$remote_config->{config}->{acl}->{subscriberadmin}->{subscribers} .";\n");
my $data = clone $test_machine->DATA_ITEM;
$data->{administrative} = 1;
my $pbxsubscriberadmin = $test_machine->check_create_correct(1, sub {
my $num = $_[1]->{i};
$_[0]->{administrative} = 1;
$_[0]->{webusername} .= time().'_34021';
$_[0]->{webpassword} = 'api_test_webpassword';
$_[0]->{username} .= time().'_34021' ;
$_[0]->{pbx_extension} .= '34021';
$_[0]->{primary_number}->{ac} .= '34021';
$_[0]->{is_pbx_group} = 0;
$_[0]->{is_pbx_pilot} = ($pilot || $_[1]->{i} > 1)? 0 : 1;
delete $_[0]->{alias_numbers};
} )->[0];
$test_machine->set_subscriber_credentials($pbxsubscriberadmin->{content});
$test_machine->runas('subscriber');
my $subscriber = $test_machine->check_create_correct(1, sub {
my $num = $_[1]->{i};
$_[0]->{webusername} .= time().'_34021_1';
$_[0]->{webpassword} = 'api_test_webpassword';
$_[0]->{username} .= time().'_34021_1' ;
$_[0]->{pbx_extension} .= '340211';
$_[0]->{primary_number}->{ac} .= '34021';
$_[0]->{is_pbx_group} = 0;
$_[0]->{is_pbx_pilot} = 0;
delete $_[0]->{alias_numbers};
} )->[0];
if ($remote_config->{config}->{acl}->{subscriberadmin}->{subscribers} =~/write/) {
$test_machine->check_get2put($subscriber,{},$put2get_check_params);
my($res,$content,$req) = $test_machine->request_patch( [ { op => 'replace', path => '/display_name', value => 'patched 34021' } ], $subscriber->{location} );
$test_machine->http_code_msg(200, "Check display_name patch for subscriberadmin", $res, $content);
}else{
my($res,$content,$req) = $test_machine->request_patch( [ { op => 'replace', path => '/display_name', value => 'patched 34021' } ], $subscriber->{location} );
$test_machine->http_code_msg(403, "Check display_name patch for subscriberadmin", $res, $content, "Read-only resource for authenticated role");
}
}
}
#TT#21818 variant 2 - pbx feature off, subscriberadmin is read-only. No subscriber exists
if (!$remote_config->{config}->{features}->{cloudpbx}) {
diag("21818: check password validation: subscriber and subscriberadmin are read-only roles;\n");
@ -385,10 +424,10 @@ done_testing;
#--------- aux
sub check_password_validation_config{
if(
$remote_config->{config}->{security}->{password_sip_validate}
&&
$remote_config->{config}->{security}->{password_web_validate}
&&
$remote_config->{config}->{security}->{password_sip_validate}
&&
$remote_config->{config}->{security}->{password_web_validate}
&&
ok($remote_config->{config}->{security}->{password_sip_validate},"check www_admin.security.password_sip_validate should be true.")
&&
ok($remote_config->{config}->{security}->{password_web_validate},"check www_admin.security.password_web_validate should be true.")) {
@ -396,6 +435,7 @@ sub check_password_validation_config{
}
return 0;
}
sub test_password_validation {
my ($subscriber_put, $actions) = @_;
my %fields = ('web' => 'web%s','' => '%s');

@ -1222,6 +1222,7 @@ sub check_get2put{
$get_in //= {};
$put_in //= {};
$put_in->{uri} //= $put_in->{location};
$get_in->{uri} //= $put_in->{uri};
$put_in->{uri} //= $get_in->{uri};

Loading…
Cancel
Save