Used to fetch whether pbx, faxserver, rtcengine etc is enabled. * Fix rtcengine reseller creation: - Refuse to create reseller if rtcengine part fails - Use proper auto-generated rtcengine values (pass, domain) to not fail on reseller names which are not forming valid hostnames. * Implement /api/admins/id to support testing - add test - fix creating admins with overly long login - fix various ACL bugs handling /api/admins/ - fix creating /api/admincerts/ as r/o user * Fix test framework - use proper client cert when switching API user Change-Id: I602fdd8181c0b3f23e76e3eab0df90a1ff9e986f (cherry picked from commit 0d376bd8b59db65296090d26f2c84d704129beef)changes/14/15614/9
parent
7482153f3f
commit
a52558b411
@ -0,0 +1,157 @@
|
||||
package NGCP::Panel::Controller::API::AdminsItem;
|
||||
use NGCP::Panel::Utils::Generic qw(:all);
|
||||
|
||||
use Sipwise::Base;
|
||||
|
||||
use boolean qw(true);
|
||||
use NGCP::Panel::Utils::DataHal qw();
|
||||
use NGCP::Panel::Utils::DataHalLink qw();
|
||||
use HTTP::Headers qw();
|
||||
use HTTP::Status qw(:constants);
|
||||
|
||||
require Catalyst::ActionRole::ACL;
|
||||
require NGCP::Panel::Role::HTTPMethods;
|
||||
require Catalyst::ActionRole::RequireSSL;
|
||||
|
||||
sub allowed_methods{
|
||||
return [qw/GET OPTIONS HEAD DELETE/];
|
||||
}
|
||||
|
||||
use parent qw/Catalyst::Controller NGCP::Panel::Role::API::Admins/;
|
||||
|
||||
sub resource_name{
|
||||
return 'admins';
|
||||
}
|
||||
sub dispatch_path{
|
||||
return '/api/admins/';
|
||||
}
|
||||
sub relation{
|
||||
return 'http://purl.org/sipwise/ngcp-api/#rel-admins';
|
||||
}
|
||||
|
||||
sub journal_query_params {
|
||||
my($self,$query_params) = @_;
|
||||
return $self->get_journal_query_params($query_params);
|
||||
}
|
||||
|
||||
__PACKAGE__->config(
|
||||
action => {
|
||||
(map { $_ => {
|
||||
ACLDetachTo => '/api/root/invalid_user',
|
||||
AllowedRole => [qw/admin reseller/],
|
||||
Args => 1,
|
||||
Does => [qw(ACL RequireSSL)],
|
||||
Method => $_,
|
||||
Path => __PACKAGE__->dispatch_path,
|
||||
} } @{ __PACKAGE__->allowed_methods }),
|
||||
@{ __PACKAGE__->get_journal_action_config(__PACKAGE__->resource_name,{
|
||||
ACLDetachTo => '/api/root/invalid_user',
|
||||
AllowedRole => [qw/admin reseller/],
|
||||
Does => [qw(ACL RequireSSL)],
|
||||
}) },
|
||||
},
|
||||
);
|
||||
|
||||
sub gather_default_action_roles {
|
||||
my ($self, %args) = @_; my @roles = ();
|
||||
push @roles, 'NGCP::Panel::Role::HTTPMethods' if $args{attributes}->{Method};
|
||||
return @roles;
|
||||
}
|
||||
|
||||
sub auto :Private {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
$self->set_body($c);
|
||||
$self->log_request($c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub GET :Allow {
|
||||
my ($self, $c, $id) = @_;
|
||||
{
|
||||
last unless $self->valid_id($c, $id);
|
||||
my $admin = $self->item_by_id($c, $id);
|
||||
last unless $self->resource_exists($c, admin => $admin);
|
||||
|
||||
my $hal = $self->hal_from_item($c, $admin);
|
||||
|
||||
my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new(
|
||||
(map { # XXX Data::HAL must be able to generate links with multiple relations
|
||||
s|rel="(http://purl.org/sipwise/ngcp-api/#rel-resellers)"|rel="item $1"|r =~
|
||||
s/rel=self/rel="item self"/r;
|
||||
} $hal->http_headers),
|
||||
), $hal->as_json);
|
||||
$c->response->headers($response->headers);
|
||||
$c->response->body($response->content);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub HEAD :Allow {
|
||||
my ($self, $c, $id) = @_;
|
||||
$c->forward(qw(GET));
|
||||
$c->response->body(q());
|
||||
return;
|
||||
}
|
||||
|
||||
sub OPTIONS :Allow {
|
||||
my ($self, $c, $id) = @_;
|
||||
my $allowed_methods = $self->allowed_methods_filtered($c);
|
||||
$c->response->headers(HTTP::Headers->new(
|
||||
Allow => join(', ', @{ $allowed_methods }),
|
||||
Accept_Patch => 'application/json-patch+json',
|
||||
));
|
||||
$c->response->content_type('application/json');
|
||||
$c->response->body(JSON::to_json({ methods => $allowed_methods })."\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sub DELETE :Allow {
|
||||
my ($self, $c, $id) = @_;
|
||||
my $guard = $c->model('DB')->txn_scope_guard;
|
||||
{
|
||||
my $admin = $self->item_by_id($c, $id);
|
||||
last unless $self->resource_exists($c, admin => $admin);
|
||||
|
||||
$c->log->error("++++++ trying to delete admin #$id as #" . $c->user->id);
|
||||
if($c->user->id == $id) {
|
||||
$self->error($c, HTTP_FORBIDDEN, "Cannot delete own user");
|
||||
last;
|
||||
}
|
||||
if($c->user->read_only) {
|
||||
$self->error($c, HTTP_FORBIDDEN, "Insufficient permissions");
|
||||
last;
|
||||
}
|
||||
|
||||
# reseller association is checked in item_rs of role
|
||||
|
||||
last unless $self->add_delete_journal_item_hal($c,sub {
|
||||
my $self = shift;
|
||||
my ($c) = @_;
|
||||
return $self->hal_from_item($c,$admin); });
|
||||
|
||||
$admin->delete;
|
||||
|
||||
$guard->commit;
|
||||
|
||||
$c->response->status(HTTP_NO_CONTENT);
|
||||
$c->response->body(q());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub get_journal_methods{
|
||||
return [qw/handle_item_base_journal handle_journals_get handle_journalsitem_get handle_journals_options handle_journalsitem_options handle_journals_head handle_journalsitem_head/];
|
||||
}
|
||||
|
||||
sub end : Private {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
$self->log_response($c);
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# vim: set tabstop=4 expandtab:
|
@ -0,0 +1,154 @@
|
||||
package NGCP::Panel::Controller::API::Capabilities;
|
||||
use NGCP::Panel::Utils::Generic qw(:all);
|
||||
|
||||
use Sipwise::Base;
|
||||
|
||||
use boolean qw(true);
|
||||
use NGCP::Panel::Utils::DataHal qw();
|
||||
use NGCP::Panel::Utils::DataHalLink qw();
|
||||
use HTTP::Headers qw();
|
||||
use HTTP::Status qw(:constants);
|
||||
|
||||
use NGCP::Panel::Utils::DateTime;
|
||||
use Path::Tiny qw(path);
|
||||
use Safe::Isa qw($_isa);
|
||||
require Catalyst::ActionRole::ACL;
|
||||
require Catalyst::ActionRole::CheckTrailingSlash;
|
||||
require NGCP::Panel::Role::HTTPMethods;
|
||||
require Catalyst::ActionRole::RequireSSL;
|
||||
|
||||
sub allowed_methods{
|
||||
return [qw/GET OPTIONS HEAD/];
|
||||
}
|
||||
|
||||
sub api_description {
|
||||
return 'Lists the capabilities/features enabled for the access role.'
|
||||
};
|
||||
|
||||
sub query_params {
|
||||
return [
|
||||
{
|
||||
param => 'name',
|
||||
description => 'Filter for capability name.',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
use parent qw/Catalyst::Controller NGCP::Panel::Role::API::Capabilities/;
|
||||
|
||||
sub resource_name{
|
||||
return 'capabilities';
|
||||
}
|
||||
sub dispatch_path{
|
||||
return '/api/capabilities/';
|
||||
}
|
||||
sub relation{
|
||||
return 'http://purl.org/sipwise/ngcp-api/#rel-capabilities';
|
||||
}
|
||||
|
||||
__PACKAGE__->config(
|
||||
action => {
|
||||
map { $_ => {
|
||||
ACLDetachTo => '/api/root/invalid_user',
|
||||
AllowedRole => [qw/admin reseller subscriberadmin subscriber/],
|
||||
Args => 0,
|
||||
Does => [qw(ACL CheckTrailingSlash RequireSSL)],
|
||||
Method => $_,
|
||||
Path => __PACKAGE__->dispatch_path,
|
||||
} } @{ __PACKAGE__->allowed_methods },
|
||||
},
|
||||
);
|
||||
|
||||
sub gather_default_action_roles {
|
||||
my ($self, %args) = @_; my @roles = ();
|
||||
push @roles, 'NGCP::Panel::Role::HTTPMethods' if $args{attributes}->{Method};
|
||||
return @roles;
|
||||
}
|
||||
|
||||
sub auto :Private {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
$self->set_body($c);
|
||||
$self->log_request($c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub GET :Allow {
|
||||
my ($self, $c) = @_;
|
||||
my $page = $c->request->params->{page} // 1;
|
||||
my $rows = $c->request->params->{rows} // 10;
|
||||
{
|
||||
my $capabilities = $self->item_rs($c);
|
||||
(my $total_count, $capabilities) = $self->paginate_order_collection($c, $capabilities);
|
||||
my (@embedded, @links);
|
||||
my $form = $self->get_form($c);
|
||||
for my $cap (@{ $capabilities }) {
|
||||
push @embedded, $self->hal_from_item($c, $cap, $form);
|
||||
push @links, NGCP::Panel::Utils::DataHalLink->new(
|
||||
relation => 'ngcp:'.$self->resource_name,
|
||||
href => sprintf('/%s%d', $c->request->path, $cap->{id}),
|
||||
);
|
||||
}
|
||||
push @links,
|
||||
NGCP::Panel::Utils::DataHalLink->new(
|
||||
relation => 'curies',
|
||||
href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
|
||||
name => 'ngcp',
|
||||
templated => true,
|
||||
),
|
||||
NGCP::Panel::Utils::DataHalLink->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
|
||||
NGCP::Panel::Utils::DataHalLink->new(relation => 'self', href => sprintf('/%s?page=%s&rows=%s', $c->request->path, $page, $rows));
|
||||
if(($total_count / $rows) > $page ) {
|
||||
push @links, NGCP::Panel::Utils::DataHalLink->new(relation => 'next', href => sprintf('/%s?page=%d&rows=%d', $c->request->path, $page + 1, $rows));
|
||||
}
|
||||
if($page > 1) {
|
||||
push @links, NGCP::Panel::Utils::DataHalLink->new(relation => 'prev', href => sprintf('/%s?page=%d&rows=%d', $c->request->path, $page - 1, $rows));
|
||||
}
|
||||
|
||||
my $hal = NGCP::Panel::Utils::DataHal->new(
|
||||
embedded => [@embedded],
|
||||
links => [@links],
|
||||
);
|
||||
$hal->resource({
|
||||
total_count => $total_count,
|
||||
});
|
||||
my $rname = $self->resource_name;
|
||||
|
||||
my $response = HTTP::Response->new(HTTP_OK, undef,
|
||||
HTTP::Headers->new($hal->http_headers(skip_links => 1)), $hal->as_json);
|
||||
$c->response->headers($response->headers);
|
||||
$c->response->body($response->content);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub HEAD :Allow {
|
||||
my ($self, $c) = @_;
|
||||
$c->forward(qw(GET));
|
||||
$c->response->body(q());
|
||||
return;
|
||||
}
|
||||
|
||||
sub OPTIONS :Allow {
|
||||
my ($self, $c) = @_;
|
||||
my $allowed_methods = $self->allowed_methods_filtered($c);
|
||||
$c->response->headers(HTTP::Headers->new(
|
||||
Allow => join(', ', @{ $allowed_methods }),
|
||||
Accept_Post => 'application/hal+json; profile=http://purl.org/sipwise/ngcp-api/#rel-'.$self->resource_name,
|
||||
));
|
||||
$c->response->content_type('application/json');
|
||||
$c->response->body(JSON::to_json({ methods => $allowed_methods })."\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sub end : Private {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
$self->log_response($c);
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# vim: set tabstop=4 expandtab:
|
@ -0,0 +1,102 @@
|
||||
package NGCP::Panel::Controller::API::CapabilitiesItem;
|
||||
use NGCP::Panel::Utils::Generic qw(:all);
|
||||
|
||||
use Sipwise::Base;
|
||||
|
||||
use boolean qw(true);
|
||||
use NGCP::Panel::Utils::DataHal qw();
|
||||
use NGCP::Panel::Utils::DataHalLink qw();
|
||||
use HTTP::Headers qw();
|
||||
use HTTP::Status qw(:constants);
|
||||
|
||||
require Catalyst::ActionRole::ACL;
|
||||
require NGCP::Panel::Role::HTTPMethods;
|
||||
require Catalyst::ActionRole::RequireSSL;
|
||||
|
||||
sub allowed_methods{
|
||||
return [qw/GET OPTIONS HEAD/];
|
||||
}
|
||||
|
||||
use parent qw/Catalyst::Controller NGCP::Panel::Role::API::Capabilities/;
|
||||
|
||||
sub resource_name{
|
||||
return 'capabilities';
|
||||
}
|
||||
sub dispatch_path{
|
||||
return '/api/capabilities/';
|
||||
}
|
||||
sub relation{
|
||||
return 'http://purl.org/sipwise/ngcp-api/#rel-capabilities';
|
||||
}
|
||||
|
||||
__PACKAGE__->config(
|
||||
action => {
|
||||
(map { $_ => {
|
||||
ACLDetachTo => '/api/root/invalid_user',
|
||||
AllowedRole => [qw/admin reseller subscriberadmin subscriber/],
|
||||
Args => 1,
|
||||
Does => [qw(ACL RequireSSL)],
|
||||
Method => $_,
|
||||
Path => __PACKAGE__->dispatch_path,
|
||||
} } @{ __PACKAGE__->allowed_methods }),
|
||||
},
|
||||
);
|
||||
|
||||
sub gather_default_action_roles {
|
||||
my ($self, %args) = @_; my @roles = ();
|
||||
push @roles, 'NGCP::Panel::Role::HTTPMethods' if $args{attributes}->{Method};
|
||||
return @roles;
|
||||
}
|
||||
|
||||
sub auto :Private {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
$self->set_body($c);
|
||||
$self->log_request($c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub GET :Allow {
|
||||
my ($self, $c, $id) = @_;
|
||||
{
|
||||
last unless $self->valid_id($c, $id);
|
||||
my $item = $self->item_by_id($c, $id);
|
||||
last unless $self->resource_exists($c, capability => $item);
|
||||
|
||||
my $hal = $self->hal_from_item($c, $item);
|
||||
|
||||
my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new(
|
||||
(map { # XXX Data::HAL must be able to generate links with multiple relations
|
||||
s|rel="(http://purl.org/sipwise/ngcp-api/#rel-resellers)"|rel="item $1"|r =~
|
||||
s/rel=self/rel="item self"/r;
|
||||
} $hal->http_headers),
|
||||
), $hal->as_json);
|
||||
$c->response->headers($response->headers);
|
||||
$c->response->body($response->content);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub HEAD :Allow {
|
||||
my ($self, $c, $id) = @_;
|
||||
$c->forward(qw(GET));
|
||||
$c->response->body(q());
|
||||
return;
|
||||
}
|
||||
|
||||
sub OPTIONS :Allow {
|
||||
my ($self, $c, $id) = @_;
|
||||
my $allowed_methods = $self->allowed_methods_filtered($c);
|
||||
$c->response->headers(HTTP::Headers->new(
|
||||
Allow => join(', ', @{ $allowed_methods }),
|
||||
Accept_Patch => 'application/json-patch+json',
|
||||
));
|
||||
$c->response->content_type('application/json');
|
||||
$c->response->body(JSON::to_json({ methods => $allowed_methods })."\n");
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# vim: set tabstop=4 expandtab:
|
@ -0,0 +1,32 @@
|
||||
package NGCP::Panel::Form::Capabilities::API;
|
||||
|
||||
use HTML::FormHandler::Moose;
|
||||
extends 'HTML::FormHandler';
|
||||
|
||||
has_field 'id' => (
|
||||
type => 'PosInteger',
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['The id of the capability.']
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
has_field 'name' => (
|
||||
type => 'Text',
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['The name of the capability.']
|
||||
},
|
||||
);
|
||||
|
||||
has_field 'enabled' => (
|
||||
type => 'Boolean',
|
||||
element_attr => {
|
||||
rel => ['tooltip'],
|
||||
title => ['Whether the capability is enabled.']
|
||||
},
|
||||
);
|
||||
|
||||
1;
|
||||
# vim: set tabstop=4 expandtab:
|
@ -0,0 +1,137 @@
|
||||
package NGCP::Panel::Role::API::Capabilities;
|
||||
use NGCP::Panel::Utils::Generic qw(:all);
|
||||
|
||||
use Sipwise::Base;
|
||||
use parent 'NGCP::Panel::Role::API';
|
||||
|
||||
use boolean qw(true);
|
||||
use NGCP::Panel::Utils::DataHal qw();
|
||||
use NGCP::Panel::Utils::DataHalLink qw();
|
||||
use HTTP::Status qw(:constants);
|
||||
use JSON::Types;
|
||||
|
||||
use NGCP::Panel::Utils::Contract;
|
||||
use NGCP::Panel::Form::Capabilities::API;
|
||||
|
||||
sub get_form {
|
||||
my ($self, $c) = @_;
|
||||
return NGCP::Panel::Form::Capabilities::API->new(ctx => $c);
|
||||
}
|
||||
|
||||
sub hal_from_item {
|
||||
my ($self, $c, $item, $form) = @_;
|
||||
|
||||
my $hal = NGCP::Panel::Utils::DataHal->new(
|
||||
links => [
|
||||
NGCP::Panel::Utils::DataHalLink->new(
|
||||
relation => 'curies',
|
||||
href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
|
||||
name => 'ngcp',
|
||||
templated => true,
|
||||
),
|
||||
NGCP::Panel::Utils::DataHalLink->new(relation => 'collection', href => sprintf("/api/%s/", $self->resource_name)),
|
||||
NGCP::Panel::Utils::DataHalLink->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
|
||||
NGCP::Panel::Utils::DataHalLink->new(relation => 'self', href => sprintf("%s%d", $self->dispatch_path, $item->{id})),
|
||||
],
|
||||
relation => 'ngcp:'.$self->resource_name,
|
||||
);
|
||||
|
||||
$form //= $self->get_form($c);
|
||||
|
||||
$self->validate_form(
|
||||
c => $c,
|
||||
resource => $item,
|
||||
form => $form,
|
||||
run => 0,
|
||||
);
|
||||
|
||||
$hal->resource($item);
|
||||
return $hal;
|
||||
}
|
||||
|
||||
sub _item_rs {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
my ($cloudpbx, $sms, $faxserver, $rtcengine, $fileshare, $mobilepush);
|
||||
|
||||
$cloudpbx = $c->config->{features}->{cloudpbx} // 0;
|
||||
$sms = $c->config->{features}->{sms} // 0;
|
||||
$faxserver = $c->config->{features}->{faxserver} // 0;
|
||||
$rtcengine = $c->config->{features}->{rtcengine} // 0;
|
||||
$fileshare = $c->config->{features}->{fileshare} // 0;
|
||||
$mobilepush = $c->config->{features}->{mobilepush} // 0;
|
||||
|
||||
if($c->user->roles eq "admin") {
|
||||
# nothing to be done
|
||||
} elsif($c->user->roles eq "reseller") {
|
||||
# TODO: is it correct to just check rtc_user of reseller?
|
||||
$rtcengine &= ($c->user->reseller->rtc_user // 0);
|
||||
} else {
|
||||
|
||||
$rtcengine &= ($c->user->voip_subscriber->contract->contact->reseller->rtc_user // 0);
|
||||
|
||||
my $customer_rs = NGCP::Panel::Utils::Contract::get_customer_rs(
|
||||
c => $c,
|
||||
contract_id => $c->user->account_id,
|
||||
);
|
||||
$customer_rs = $customer_rs->search({
|
||||
'-or' => [
|
||||
'product.class' => 'sipaccount',
|
||||
'product.class' => 'pbxaccount',
|
||||
],
|
||||
},{
|
||||
'+select' => [ 'product.class' ],
|
||||
'+as' => [ 'product_class' ],
|
||||
});
|
||||
my $customer = $customer_rs->first;
|
||||
|
||||
my $cpbx = ($customer->get_column('product_class') eq 'pbxaccount') ? 1 : 0;
|
||||
$cloudpbx &= $cpbx;
|
||||
|
||||
# TODO: sms and rtcengine are not specially restricted; should it?
|
||||
my $profile = $c->user->voip_subscriber_profile;
|
||||
if($profile) {
|
||||
my $attrs = [ map { $_->attribute->attribute } $profile->profile_attributes->all ];
|
||||
if(grep(/^fax_server$/, @{ $attrs })) {
|
||||
$faxserver &= 1;
|
||||
} else {
|
||||
$faxserver = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $item_rs = [
|
||||
{ id => 1, name => 'cloudpbx', enabled => $cloudpbx },
|
||||
{ id => 2, name => 'sms', enabled => $sms },
|
||||
{ id => 3, name => 'faxserver', enabled => $faxserver },
|
||||
{ id => 4, name => 'rtcengine', enabled => $rtcengine },
|
||||
{ id => 5, name => 'fileshare', enabled => $fileshare},
|
||||
{ id => 6, name => 'mobilepush',enabled => $mobilepush},
|
||||
];
|
||||
|
||||
if($c->req->param('name')) {
|
||||
my $res = [];
|
||||
foreach my $item (@{ $item_rs }) {
|
||||
if($item->{name} eq $c->req->param('name')) {
|
||||
push @{ $res }, $item;
|
||||
last;
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
return $item_rs;
|
||||
}
|
||||
|
||||
sub item_by_id {
|
||||
my ($self, $c, $id) = @_;
|
||||
|
||||
my $item_rs = $self->item_rs($c);
|
||||
foreach my $item(@{ $item_rs }) {
|
||||
return $item if $item->{id} == $id;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
# vim: set tabstop=4 expandtab:
|
@ -0,0 +1,384 @@
|
||||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
|
||||
use NGCP::Test;
|
||||
use Test::More;
|
||||
use Clone 'clone';
|
||||
use JSON qw/from_json to_json/;
|
||||
use Data::Dumper;
|
||||
|
||||
my $test = NGCP::Test->new(log_debug => 0);
|
||||
my $t = $test->generate_sid();
|
||||
my $c_admin = $test->client();
|
||||
|
||||
my $ref = $test->reference_data(
|
||||
client => $c_admin,
|
||||
use_persistent => 1,
|
||||
delete_persistent => 0,
|
||||
depends => [
|
||||
{
|
||||
resource => 'admins',
|
||||
hints => [{ name => 'superuser admin' }],
|
||||
name => 'my_super_admin'
|
||||
},
|
||||
{
|
||||
resource => 'admins',
|
||||
hints => [{ name => 'readonly admin' }],
|
||||
name => 'my_ro_admin'
|
||||
},
|
||||
{
|
||||
resource => 'admins',
|
||||
hints => [{ name => 'master reseller admin' }],
|
||||
name => 'my_reseller_admin'
|
||||
},
|
||||
{
|
||||
resource => 'admins',
|
||||
hints => [{ name => 'nomaster reseller admin' }],
|
||||
name => 'my_std_admin'
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
my $sid = $ref->sid();
|
||||
|
||||
my $c_su_admin = $test->client(
|
||||
role => 'admin',
|
||||
username => $ref->data('my_super_admin')->{login},
|
||||
password => "superadmin_$sid",
|
||||
);
|
||||
my $c_ro_admin = $test->client(
|
||||
role => 'admin',
|
||||
username => $ref->data('my_ro_admin')->{login},
|
||||
password => "roadmin_$sid",
|
||||
);
|
||||
my $c_res_admin = $test->client(
|
||||
role => 'admin',
|
||||
username => $ref->data('my_reseller_admin')->{login},
|
||||
password => "mstreselleradmin_$sid",
|
||||
);
|
||||
my $c_std_admin = $test->client(
|
||||
role => 'admin',
|
||||
username => $ref->data('my_std_admin')->{login},
|
||||
password => "stdreselleradmin_$sid",
|
||||
);
|
||||
|
||||
|
||||
### let's roll
|
||||
|
||||
my $adm_res = $test->resource(
|
||||
client => $c_su_admin,
|
||||
resource => 'admins',
|
||||
data => {
|
||||
login => "testadmin_$sid",
|
||||
password => "testadmin_$sid",
|
||||
reseller_id => $ref->data('my_super_admin')->{reseller_id},
|
||||
},
|
||||
);
|
||||
|
||||
# superuser can fetch all admins
|
||||
my $admins = $adm_res->test_get(
|
||||
name => 'fetch all admins as superuser',
|
||||
expected_links => [qw/
|
||||
ngcp:resellers
|
||||
/],
|
||||
expected_result => { code => '200' }
|
||||
);
|
||||
|
||||
# superuser can create admin in own reseller
|
||||
# superuser can create admin in other reseller
|
||||
# superuser can't create admin with login > 31 chars
|
||||
$adm_res->test_post(
|
||||
name => 'create reseller as su admin',
|
||||
data_replace => [
|
||||
{},
|
||||
[
|
||||
{ field => 'reseller_id', value => $ref->data('my_reseller_admin')->{reseller_id} },
|
||||
{ field => 'login', value => "o_res_admin_$sid" }
|
||||
],
|
||||
{ field => 'login', value => "some_overly_long_admin_$sid" }
|
||||
],
|
||||
skip_test_fields => [qw/password/],
|
||||
expected_result => [
|
||||
{ code => '201' },
|
||||
{ code => '201' },
|
||||
{ code => '422', error_re => 'Field should not exceed 31 characters' }
|
||||
],
|
||||
);
|
||||
|
||||
my $adm = $adm_res->pop_created_item();
|
||||
|
||||
# superuser can update admin in own reseller
|
||||
$adm_res->test_put(
|
||||
name => 'update own reseller admin as su admin',
|
||||
item => $adm,
|
||||
data_replace => {
|
||||
field => 'login', value => "s_up_admin_$sid"
|
||||
},
|
||||
skip_test_fields => [qw/password/],
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
# superuser can delete admin in own reseller
|
||||
$adm_res->test_delete(
|
||||
name => 'delete own reseller admin as su admin',
|
||||
item => $adm,
|
||||
expected_result => { code => '204' }
|
||||
);
|
||||
|
||||
$adm = $adm_res->pop_created_item();
|
||||
|
||||
# superuser can update admin in other reseller
|
||||
$adm_res->test_put(
|
||||
name => 'update other reseller admin as su admin',
|
||||
item => $adm,
|
||||
data_replace => {
|
||||
field => 'login', value => "another_updated_admin_$sid"
|
||||
},
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
# superuser can delete admin in other reseller
|
||||
$adm_res->test_delete(
|
||||
name => 'delete other reseller admin as su admin',
|
||||
item => $adm,
|
||||
expected_result => { code => '204' }
|
||||
);
|
||||
|
||||
# superuser can't delete self
|
||||
$adm_res->test_delete(
|
||||
name => 'delete self as su admin',
|
||||
item => $ref->data('my_super_admin'),
|
||||
expected_result => { code => '403' }
|
||||
);
|
||||
|
||||
### read-only tests
|
||||
|
||||
$adm_res->client($c_ro_admin);
|
||||
|
||||
# ro admin can fetch all admins
|
||||
$admins = $adm_res->test_get(
|
||||
name => 'fetch all admins as ro admin',
|
||||
expected_links => [],
|
||||
expected_result => { code => '200' }
|
||||
);
|
||||
|
||||
my @admins = @{ $admins->[0]->{_embedded}->{'ngcp:admins'} };
|
||||
foreach my $a(@admins) {
|
||||
is($a->{reseller_id}, undef,
|
||||
"ro-fetched admin belongs to own reseller");
|
||||
$test->inc_test_count();
|
||||
}
|
||||
|
||||
# ro admin can't create admin
|
||||
$adm_res->test_post(
|
||||
name => 'create reseller as ro admin',
|
||||
data_replace => [
|
||||
{ field => 'login', value => "roadm_$sid" }
|
||||
],
|
||||
expected_result => [
|
||||
{ code => '403' },
|
||||
],
|
||||
);
|
||||
|
||||
# ro admin can't update own admin
|
||||
$adm_res->test_put(
|
||||
name => 'update self as ro admin',
|
||||
item => $ref->data('my_ro_admin'),
|
||||
data_replace => {
|
||||
field => 'login', value => "up_adm_$sid"
|
||||
},
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
# ro admin can't update other admin
|
||||
$adm_res->test_put(
|
||||
name => 'update self as ro admin',
|
||||
item => $ref->data('my_reseller_admin'),
|
||||
data_replace => {
|
||||
field => 'login', value => "up_adm_$sid"
|
||||
},
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
# ro admin can't delete other admin
|
||||
$adm_res->test_delete(
|
||||
name => 'delete reseller admin as ro admin',
|
||||
item => $ref->data('my_reseller_admin'),
|
||||
expected_result => { code => '403' }
|
||||
);
|
||||
|
||||
# ro admin can't delete self
|
||||
$adm_res->test_delete(
|
||||
name => 'delete self as ro admin',
|
||||
item => $ref->data('my_ro_admin'),
|
||||
expected_result => { code => '403' }
|
||||
);
|
||||
|
||||
### reseller admin tests
|
||||
|
||||
$adm_res->client($c_res_admin);
|
||||
|
||||
# res admin can fetch all admins
|
||||
$admins = $adm_res->test_get(
|
||||
name => 'fetch all admins as reseller admin',
|
||||
expected_links => [],
|
||||
expected_result => { code => '200' }
|
||||
);
|
||||
|
||||
@admins = @{ $admins->[0]->{_embedded}->{'ngcp:admins'} };
|
||||
foreach my $a(@admins) {
|
||||
is($a->{reseller_id}, undef,
|
||||
"reseller-fetched admin belongs to own reseller");
|
||||
$test->inc_test_count();
|
||||
}
|
||||
|
||||
# reseller admin can create admin
|
||||
$adm_res->test_post(
|
||||
name => 'create reseller as reseller admin',
|
||||
data_replace => [
|
||||
{ field => 'login', value => "resadm_$sid" }
|
||||
],
|
||||
skip_test_fields => [qw/reseller_id password/],
|
||||
expected_result => [
|
||||
{ code => '201' },
|
||||
],
|
||||
);
|
||||
$adm = $adm_res->pop_created_item();
|
||||
|
||||
# reseller admin can update own admin
|
||||
$adm_res->test_put(
|
||||
name => 'update self as reseller admin',
|
||||
item => $ref->data('my_reseller_admin'),
|
||||
data_replace => {
|
||||
field => 'login', value => "up_adm_$sid"
|
||||
},
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
# reseller admin can update other admin
|
||||
$adm_res->test_put(
|
||||
name => 'update other as reseller admin',
|
||||
item => $ref->data('my_reseller_admin'),
|
||||
data_replace => {
|
||||
field => 'login', value => "up_adm_$sid"
|
||||
},
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
# reseller admin can delete other admin
|
||||
$adm_res->test_delete(
|
||||
name => 'delete reseller admin as reseller admin',
|
||||
item => $adm,
|
||||
expected_result => { code => '204' }
|
||||
);
|
||||
|
||||
# reseller admin can't delete other admin in foreign reseller
|
||||
$adm_res->test_delete(
|
||||
name => 'delete other reseller admin as reseller admin',
|
||||
item => $ref->data('my_ro_admin'),
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
# reseller admin can't delete self
|
||||
$adm_res->test_delete(
|
||||
name => 'delete self as reseller admin',
|
||||
item => $ref->data('my_reseller_admin'),
|
||||
expected_result => { code => '403' }
|
||||
);
|
||||
|
||||
$adm_res->test_get(
|
||||
name => 'fetch other admin as reseller admin',
|
||||
item => $ref->data('my_std_admin'),
|
||||
skip_test_fields => [qw/is_superuser lawful_intercept reseller_id/],
|
||||
expected_result => { code => '200' }
|
||||
);
|
||||
|
||||
$adm_res->test_get(
|
||||
name => 'fetch other reseller admin as reseller admin',
|
||||
item => $ref->data('my_ro_admin'),
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
### standard reseller without master tests
|
||||
|
||||
$adm_res->client($c_std_admin);
|
||||
|
||||
# std admin can only fetch self
|
||||
$admins = $adm_res->test_get(
|
||||
name => 'fetch all admins as reseller',
|
||||
expected_links => [],
|
||||
expected_result => { code => '200' }
|
||||
);
|
||||
is($admins->[0]->{total_count}, 1, "check if only own admin is returned");
|
||||
$test->inc_test_count();
|
||||
|
||||
@admins = @{ $admins->[0]->{_embedded}->{'ngcp:admins'} };
|
||||
foreach my $a(@admins) {
|
||||
is($a->{id}, $ref->data('my_std_admin')->{id},
|
||||
"std reseller-fetched admin is self");
|
||||
$test->inc_test_count();
|
||||
}
|
||||
|
||||
# std admin can't create admin
|
||||
$adm_res->test_post(
|
||||
name => 'create admin as std admin',
|
||||
data_replace => [
|
||||
{ field => 'login', value => "resadm_$sid" }
|
||||
],
|
||||
expected_result => [
|
||||
{ code => '403' },
|
||||
],
|
||||
);
|
||||
|
||||
# reseller admin can update own admin
|
||||
$adm_res->test_put(
|
||||
name => 'update self as std admin',
|
||||
item => $ref->data('my_std_admin'),
|
||||
data_replace => {
|
||||
field => 'login', value => "up_adm_$sid"
|
||||
},
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
# reseller admin can update other admin
|
||||
$adm_res->test_put(
|
||||
name => 'update other as std admin',
|
||||
item => $ref->data('my_reseller_admin'),
|
||||
data_replace => {
|
||||
field => 'login', value => "up_adm_$sid"
|
||||
},
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
# reseller admin can't delete other admin
|
||||
$adm_res->test_delete(
|
||||
name => 'delete reseller admin as std admin',
|
||||
item => $ref->data('my_reseller_admin'),
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
$adm_res->test_delete(
|
||||
name => 'delete other reseller admin as std admin',
|
||||
item => $ref->data('my_ro_admin'),
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
# reseller admin can't delete self
|
||||
$adm_res->test_delete(
|
||||
name => 'delete self as reseller admin',
|
||||
item => $ref->data('my_std_admin'),
|
||||
expected_result => { code => '403' }
|
||||
);
|
||||
|
||||
$adm_res->test_get(
|
||||
name => 'fetch other admin as std admin',
|
||||
item => $ref->data('my_reseller_admin'),
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
$adm_res->test_get(
|
||||
name => 'fetch other reseller admin as std admin',
|
||||
item => $ref->data('my_ro_admin'),
|
||||
expected_result => { code => '404' }
|
||||
);
|
||||
|
||||
$test->done();
|
@ -0,0 +1,417 @@
|
||||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
|
||||
use NGCP::Test;
|
||||
use Test::More;
|
||||
use Clone 'clone';
|
||||
use JSON qw/from_json to_json/;
|
||||
use Data::Dumper;
|
||||
|
||||
my $test = NGCP::Test->new(log_debug => 0);
|
||||
my $t = $test->generate_sid();
|
||||
my $c_admin = $test->client();
|
||||
|
||||
my $ref = $test->reference_data(
|
||||
client => $c_admin,
|
||||
use_persistent => 1,
|
||||
delete_persistent => 0,
|
||||
depends => [
|
||||
{
|
||||
resource => 'admins',
|
||||
hints => [{ name => 'reseller admin' }],
|
||||
name => 'my_reseller_admin'
|
||||
},
|
||||
{
|
||||
resource => 'admins',
|
||||
hints => [{ name => 'rtc reseller admin' }],
|
||||
name => 'my_rtcreseller_admin'
|
||||
},
|
||||
{
|
||||
resource => 'subscriberprofiles',
|
||||
hints => [{ name => 'subscriber profile' }],
|
||||
name => 'my_sub_profile'
|
||||
},
|
||||
{
|
||||
resource => 'subscribers',
|
||||
hints => [{ name => 'pbx pilot subscriber' }],
|
||||
name => 'my_pbx_subscriber'
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
my $sid = $ref->sid();
|
||||
|
||||
# test capabilities as admin
|
||||
diag("test capabilities as admin");
|
||||
{
|
||||
my $expected = {
|
||||
cloudpbx => $ENV{HAS_CLOUDPBX} // 0,
|
||||
sms => $ENV{HAS_SMS} // 0,
|
||||
faxserver => $ENV{HAS_FAXSERVER} // 1,
|
||||
rtcengine => $ENV{HAS_RTCENGINE} // 0,
|
||||
fileshare => $ENV{HAS_FILESHARE} // 0,
|
||||
mobilepush => $ENV{HAS_MOBILEPUSH} // 0,
|
||||
};
|
||||
|
||||
my $cap_res = $test->resource(
|
||||
client => $c_admin,
|
||||
resource => 'capabilities',
|
||||
);
|
||||
|
||||
my $caps = $cap_res->test_get(
|
||||
name => 'fetch capabilities as admin',
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
|
||||
my $tmpexpected = clone($expected);
|
||||
my @caps = ();
|
||||
foreach my $cap (@{ $caps->[0]->{_embedded}->{'ngcp:capabilities'} }) {
|
||||
my $name = $cap->{name};
|
||||
my $val = $cap->{enabled} ? 1 : 0;
|
||||
is(exists $expected->{$name}, 1, "returned admin capability $name is expected");
|
||||
$test->inc_test_count();
|
||||
is($val, $expected->{$name}, "returned admin capability $name has value $$expected{$name}");
|
||||
$test->inc_test_count();
|
||||
delete $tmpexpected->{$cap->{name}};
|
||||
push @caps, $cap;
|
||||
}
|
||||
is(keys %{ $tmpexpected }, 0, "all expected admin capabilities seen");
|
||||
$test->inc_test_count();
|
||||
|
||||
foreach my $cap(@caps) {
|
||||
diag("test individual capability $cap->{name} with id $cap->{id} as admin");
|
||||
my $items = $cap_res->test_get(
|
||||
name => "fetch individual capability $cap->{name} as admin",
|
||||
item => $cap,
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# test capabilities as reseller without rtcengine enabled
|
||||
diag("test capabilities as reseller without rtcengine");
|
||||
{
|
||||
my $c_reseller = $test->client(
|
||||
role => 'reseller',
|
||||
username => $ref->data('my_reseller_admin')->{login},
|
||||
password => "reseller_$sid",
|
||||
);
|
||||
|
||||
my $expected = {
|
||||
cloudpbx => $ENV{HAS_CLOUDPBX} // 0,
|
||||
sms => $ENV{HAS_SMS} // 0,
|
||||
faxserver => $ENV{HAS_FAXSERVER} // 1,
|
||||
rtcengine => 0,
|
||||
fileshare => $ENV{HAS_FILESHARE} // 0,
|
||||
mobilepush => $ENV{HAS_MOBILEPUSH} // 0,
|
||||
};
|
||||
|
||||
my $cap_res = $test->resource(
|
||||
client => $c_reseller,
|
||||
resource => 'capabilities',
|
||||
);
|
||||
|
||||
my $caps = $cap_res->test_get(
|
||||
name => 'fetch capabilities as reseller',
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
|
||||
my $tmpexpected = clone($expected);
|
||||
my @caps = ();
|
||||
foreach my $cap (@{ $caps->[0]->{_embedded}->{'ngcp:capabilities'} }) {
|
||||
my $name = $cap->{name};
|
||||
my $val = $cap->{enabled} ? 1 : 0;
|
||||
is(exists $expected->{$name}, 1, "returned reseller capability $name is expected");
|
||||
$test->inc_test_count();
|
||||
is($val, $expected->{$name}, "returned reseller capability $name has value $$expected{$name}");
|
||||
$test->inc_test_count();
|
||||
delete $tmpexpected->{$cap->{name}};
|
||||
push @caps, $cap;
|
||||
}
|
||||
is(keys %{ $tmpexpected }, 0, "all expected reseller capabilities seen");
|
||||
$test->inc_test_count();
|
||||
|
||||
foreach my $cap(@caps) {
|
||||
diag("test individual capability $cap->{name} with id $cap->{id} as reseller");
|
||||
my $items = $cap_res->test_get(
|
||||
name => "fetch individual capability $cap->{name} as reseller",
|
||||
item => $cap,
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# test capabilities as reseller with rtcengine enabled
|
||||
diag("test capabilities as reseller with rtcengine");
|
||||
{
|
||||
my $c_rtcreseller = $test->client(
|
||||
role => 'reseller',
|
||||
username => $ref->data('my_rtcreseller_admin')->{login},
|
||||
password => "rtcreseller_$sid",
|
||||
);
|
||||
|
||||
my $expected = {
|
||||
cloudpbx => $ENV{HAS_CLOUDPBX} // 0,
|
||||
sms => $ENV{HAS_SMS} // 0,
|
||||
faxserver => $ENV{HAS_FAXSERVER} // 1,
|
||||
rtcengine => $ENV{HAS_RTCENGINE} // 1,
|
||||
fileshare => $ENV{HAS_FILESHARE} // 0,
|
||||
mobilepush => $ENV{HAS_MOBILEPUSH} // 0,
|
||||
};
|
||||
|
||||
my $cap_res = $test->resource(
|
||||
client => $c_rtcreseller,
|
||||
resource => 'capabilities',
|
||||
);
|
||||
|
||||
my $caps = $cap_res->test_get(
|
||||
name => 'fetch capabilities as rtc reseller',
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
|
||||
my $tmpexpected = clone($expected);
|
||||
my @caps = ();
|
||||
foreach my $cap (@{ $caps->[0]->{_embedded}->{'ngcp:capabilities'} }) {
|
||||
my $name = $cap->{name};
|
||||
my $val = $cap->{enabled} ? 1 : 0;
|
||||
is(exists $expected->{$name}, 1, "returned rtc reseller capability $name is expected");
|
||||
$test->inc_test_count();
|
||||
is($val, $expected->{$name}, "returned rtc reseller capability $name has value $$expected{$name}");
|
||||
$test->inc_test_count();
|
||||
delete $tmpexpected->{$cap->{name}};
|
||||
push @caps, $cap;
|
||||
}
|
||||
is(keys %{ $tmpexpected }, 0, "all expected rtc reseller capabilities seen");
|
||||
$test->inc_test_count();
|
||||
|
||||
foreach my $cap(@caps) {
|
||||
diag("test individual capability $cap->{name} with id $cap->{id} as rtc reseller");
|
||||
my $items = $cap_res->test_get(
|
||||
name => "fetch individual capability $cap->{name} as rtc reseller",
|
||||
item => $cap,
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
diag("test capabilities as pbx subscriber");
|
||||
{
|
||||
my $c_subscriber = $test->client(
|
||||
role => 'subscriber',
|
||||
username => $ref->data('my_pbx_subscriber')->{webusername} . '@' .
|
||||
$ref->data('my_pbx_subscriber')->{domain},
|
||||
password => $ref->data('my_pbx_subscriber')->{webpassword},
|
||||
);
|
||||
|
||||
my $expected = {
|
||||
cloudpbx => 1,
|
||||
sms => $ENV{HAS_SMS} // 0,
|
||||
faxserver => $ENV{HAS_FAXSERVER} // 1,
|
||||
rtcengine => 0,
|
||||
fileshare => $ENV{HAS_FILESHARE} // 0,
|
||||
mobilepush => $ENV{HAS_MOBILEPUSH} // 0,
|
||||
};
|
||||
|
||||
my $cap_res = $test->resource(
|
||||
client => $c_subscriber,
|
||||
resource => 'capabilities',
|
||||
);
|
||||
|
||||
my $caps = $cap_res->test_get(
|
||||
name => 'fetch capabilities as pbx subscriber',
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
|
||||
my $tmpexpected = clone($expected);
|
||||
my @caps = ();
|
||||
foreach my $cap (@{ $caps->[0]->{_embedded}->{'ngcp:capabilities'} }) {
|
||||
my $name = $cap->{name};
|
||||
my $val = $cap->{enabled} ? 1 : 0;
|
||||
is(exists $expected->{$name}, 1, "returned pbx capability $name is expected");
|
||||
$test->inc_test_count();
|
||||
is($val, $expected->{$name}, "returned pbx capability $name has value $$expected{$name}");
|
||||
$test->inc_test_count();
|
||||
delete $tmpexpected->{$cap->{name}};
|
||||
push @caps, $cap;
|
||||
}
|
||||
is(keys %{ $tmpexpected }, 0, "all expected pbx capabilities seen");
|
||||
$test->inc_test_count();
|
||||
|
||||
foreach my $cap(@caps) {
|
||||
diag("test individual capability $cap->{name} with id $cap->{id} as pbx subscriber");
|
||||
my $items = $cap_res->test_get(
|
||||
name => "fetch individual capability $cap->{name} as pbx reseller",
|
||||
item => $cap,
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
}
|
||||
|
||||
# get a subscriber profile assigned
|
||||
my $sub_res = $test->resource(
|
||||
client => $c_admin,
|
||||
resource => 'subscribers'
|
||||
);
|
||||
$sub_res->test_put(
|
||||
name => 'assign subscriber profile',
|
||||
item => $ref->data('my_pbx_subscriber'),
|
||||
skip_test_fields => [qw/modify_timestamp/],
|
||||
data_replace => [[
|
||||
{
|
||||
field => 'profile_set_id',
|
||||
value => $ref->data('my_sub_profile')->{profile_set_id},
|
||||
},
|
||||
{
|
||||
field => 'profile_id',
|
||||
value => $ref->data('my_sub_profile')->{id},
|
||||
},
|
||||
]],
|
||||
expected_result => { code => '200' },
|
||||
);
|
||||
|
||||
$caps = $cap_res->test_get(
|
||||
name => 'fetch capabilities as pbx subscriber after profile',
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
|
||||
$expected->{faxserver} = $ENV{FAXSERVER}//1;
|
||||
$tmpexpected = clone($expected);
|
||||
@caps = ();
|
||||
foreach my $cap (@{ $caps->[0]->{_embedded}->{'ngcp:capabilities'} }) {
|
||||
my $name = $cap->{name};
|
||||
my $val = $cap->{enabled} ? 1 : 0;
|
||||
is(exists $expected->{$name}, 1, "returned pbx profile capability $name is expected");
|
||||
$test->inc_test_count();
|
||||
is($val, $expected->{$name}, "returned pbx profile capability $name has value $$expected{$name}");
|
||||
$test->inc_test_count();
|
||||
delete $tmpexpected->{$cap->{name}};
|
||||
push @caps, $cap;
|
||||
}
|
||||
is(keys %{ $tmpexpected }, 0, "all expected pbx profile capabilities seen");
|
||||
$test->inc_test_count();
|
||||
|
||||
foreach my $cap(@caps) {
|
||||
diag("test individual pbx profile capability $cap->{name} with id $cap->{id} as pbx subscriber");
|
||||
my $items = $cap_res->test_get(
|
||||
name => "fetch individual pbx profile capability $cap->{name}",
|
||||
item => $cap,
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
}
|
||||
|
||||
# modify profile to remove fax_server attribute
|
||||
my $prof_res = $test->resource(
|
||||
client => $c_admin,
|
||||
resource => 'subscriberprofiles'
|
||||
);
|
||||
my $orig_attrs = clone($ref->data('my_sub_profile')->{attributes});
|
||||
$prof_res->test_put(
|
||||
name => 'remove all attributes',
|
||||
item => $ref->data('my_sub_profile'),
|
||||
data_replace => {
|
||||
field => 'attributes', value => [qw/ncos clir/],
|
||||
},
|
||||
expected_result => { code => '200' },
|
||||
);
|
||||
|
||||
|
||||
# test again
|
||||
$caps = $cap_res->test_get(
|
||||
name => 'fetch capabilities as pbx subscriber after profile change',
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
|
||||
$expected->{faxserver} = 0;
|
||||
$tmpexpected = clone($expected);
|
||||
@caps = ();
|
||||
foreach my $cap (@{ $caps->[0]->{_embedded}->{'ngcp:capabilities'} }) {
|
||||
my $name = $cap->{name};
|
||||
my $val = $cap->{enabled} ? 1 : 0;
|
||||
is(exists $expected->{$name}, 1, "returned pbx profile change capability $name is expected");
|
||||
$test->inc_test_count();
|
||||
is($val, $expected->{$name}, "returned pbx profile change capability $name has value $$expected{$name}");
|
||||
$test->inc_test_count();
|
||||
delete $tmpexpected->{$cap->{name}};
|
||||
push @caps, $cap;
|
||||
}
|
||||
is(keys %{ $tmpexpected }, 0, "all expected pbx profile change capabilities seen");
|
||||
$test->inc_test_count();
|
||||
|
||||
foreach my $cap(@caps) {
|
||||
diag("test individual pbx profile change capability $cap->{name} with id $cap->{id} as pbx subscriber");
|
||||
my $items = $cap_res->test_get(
|
||||
name => "fetch individual pbx profile change capability $cap->{name}",
|
||||
item => $cap,
|
||||
expected_links => [],
|
||||
expected_fields => [qw/
|
||||
id name enabled
|
||||
/],
|
||||
expected_result => { code => 200 }
|
||||
);
|
||||
}
|
||||
|
||||
# reset profile
|
||||
$sub_res->test_put(
|
||||
name => 'unassign subscriber profile',
|
||||
item => $ref->data('my_pbx_subscriber'),
|
||||
skip_test_fields => [qw/modify_timestamp/],
|
||||
data_replace => [[
|
||||
{ field => 'profile_set_id', value => undef },
|
||||
{ field => 'profile_id', value => undef },
|
||||
]],
|
||||
expected_result => { code => '200' },
|
||||
);
|
||||
$prof_res->test_put(
|
||||
name => 'restore profile attributes',
|
||||
item => $ref->data('my_sub_profile'),
|
||||
data_replace => {
|
||||
field => 'attributes', value => $orig_attrs,
|
||||
},
|
||||
expected_result => { code => '200' },
|
||||
);
|
||||
}
|
||||
|
||||
$test->done();
|
@ -0,0 +1,47 @@
|
||||
[
|
||||
{
|
||||
"name": "superuser admin",
|
||||
"type": "admins",
|
||||
"depends": [],
|
||||
"data": {
|
||||
"reseller_id": 1,
|
||||
"login": "superadmin_${sid}",
|
||||
"password": "superadmin_${sid}",
|
||||
"is_superuser": true,
|
||||
"is_master": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "readonly admin",
|
||||
"type": "admins",
|
||||
"depends": [],
|
||||
"data": {
|
||||
"reseller_id": 1,
|
||||
"login": "roadmin_${sid}",
|
||||
"password": "roadmin_${sid}",
|
||||
"read_only": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "master reseller admin",
|
||||
"type": "admins",
|
||||
"depends": [ "reseller" ],
|
||||
"data": {
|
||||
"reseller_id": "${reseller}",
|
||||
"login": "mstreselleradmin_${sid}",
|
||||
"password": "mstreselleradmin_${sid}",
|
||||
"is_master": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nomaster reseller admin",
|
||||
"type": "admins",
|
||||
"depends": [ "reseller" ],
|
||||
"data": {
|
||||
"reseller_id": "${reseller}",
|
||||
"login": "stdreselleradmin_${sid}",
|
||||
"password": "stdreselleradmin_${sid}",
|
||||
"is_master": false
|
||||
}
|
||||
}
|
||||
]
|
@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"name": "subscriber profile set",
|
||||
"type": "subscriberprofilesets",
|
||||
"depends": [
|
||||
"reseller"
|
||||
],
|
||||
"data": {
|
||||
"reseller_id": "${reseller}",
|
||||
"name": "subprofileset_${sid}",
|
||||
"description": "subprofileset ${sid}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "subscriber profile",
|
||||
"type": "subscriberprofiles",
|
||||
"depends": [
|
||||
"subscriber profile set"
|
||||
],
|
||||
"data": {
|
||||
"profile_set_id": "${subscriber profile set}",
|
||||
"name": "subscriber_profile_${sid}",
|
||||
"description": "subscriber profile ${sid}",
|
||||
"set_default": false,
|
||||
"attributes": [
|
||||
"fax_server",
|
||||
"ncos",
|
||||
"cfu"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
Loading…
Reference in new issue