diff --git a/lib/NGCP/Panel/Controller/API/Numbers.pm b/lib/NGCP/Panel/Controller/API/Numbers.pm index b2605e642f..6f65de3bb9 100644 --- a/lib/NGCP/Panel/Controller/API/Numbers.pm +++ b/lib/NGCP/Panel/Controller/API/Numbers.pm @@ -3,15 +3,11 @@ use NGCP::Panel::Utils::Generic qw(:all); use Sipwise::Base; -use boolean qw(true); -use Data::HAL qw(); -use Data::HAL::Link qw(); -use HTTP::Headers qw(); -use HTTP::Status qw(:constants); +use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::Numbers/; -use NGCP::Panel::Utils::DateTime; -use Path::Tiny qw(path); -use Safe::Isa qw($_isa); +__PACKAGE__->set_config({ + allowed_roles => [qw/admin reseller subscriberadmin/], +}); sub allowed_methods{ return [qw/GET OPTIONS HEAD/]; @@ -70,74 +66,6 @@ sub query_params { ]; } -use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::Numbers/; - -sub resource_name{ - return 'numbers'; -} - -sub dispatch_path{ - return '/api/numbers/'; -} - -sub relation{ - return 'http://purl.org/sipwise/ngcp-api/#rel-numbers'; -} - -__PACKAGE__->set_config({ - allowed_roles => [qw/admin reseller subscriberadmin/], -}); - -sub GET :Allow { - my ($self, $c) = @_; - my $page = $c->request->params->{page} // 1; - my $rows = $c->request->params->{rows} // 10; - { - my $numbers = $self->item_rs($c); - (my $total_count, $numbers) = $self->paginate_order_collection($c, $numbers); - my (@embedded, @links); - my $form = $self->get_form($c); - for my $domain ($numbers->all) { - push @embedded, $self->hal_from_item($c, $domain, $form); - push @links, Data::HAL::Link->new( - relation => 'ngcp:'.$self->resource_name, - href => sprintf('/%s%d', $c->request->path, $domain->id), - ); - } - push @links, - Data::HAL::Link->new( - relation => 'curies', - href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}', - name => 'ngcp', - templated => true, - ), - Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'), - Data::HAL::Link->new(relation => 'self', href => sprintf('/%s?page=%s&rows=%s', $c->request->path, $page, $rows)); - if(($total_count / $rows) > $page ) { - push @links, Data::HAL::Link->new(relation => 'next', href => sprintf('/%s?page=%d&rows=%d', $c->request->path, $page + 1, $rows)); - } - if($page > 1) { - push @links, Data::HAL::Link->new(relation => 'prev', href => sprintf('/%s?page=%d&rows=%d', $c->request->path, $page - 1, $rows)); - } - - my $hal = Data::HAL->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; -} - 1; # vim: set tabstop=4 expandtab: diff --git a/lib/NGCP/Panel/Controller/API/NumbersItem.pm b/lib/NGCP/Panel/Controller/API/NumbersItem.pm index 4661b5aad4..c72b06376e 100644 --- a/lib/NGCP/Panel/Controller/API/NumbersItem.pm +++ b/lib/NGCP/Panel/Controller/API/NumbersItem.pm @@ -1,160 +1,165 @@ package NGCP::Panel::Controller::API::NumbersItem; -use NGCP::Panel::Utils::Generic qw(:all); use Sipwise::Base; +use NGCP::Panel::Utils::Generic qw(:all); + +use parent qw/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::Numbers/; -use boolean qw(true); -use Data::HAL qw(); -use Data::HAL::Link qw(); -use HTTP::Headers qw(); use HTTP::Status qw(:constants); +use JSON::Types; -use NGCP::Panel::Utils::ValidateJSON qw(); -use NGCP::Panel::Utils::DateTime; -use Path::Tiny qw(path); -use Safe::Isa qw($_isa); -require Catalyst::ActionRole::ACL; -require NGCP::Panel::Role::HTTPMethods; -require Catalyst::ActionRole::RequireSSL; +__PACKAGE__->set_config({ + allowed_roles => { + Default => [qw/admin reseller subscriberadmin/], + Journal => [qw/admin reseller/], + } +}); sub allowed_methods{ return [qw/GET PUT PATCH OPTIONS HEAD/]; } -use parent qw/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::Numbers/; - -sub resource_name{ - return 'numbers'; -} - -sub dispatch_path{ - return '/api/numbers/'; -} - -sub relation{ - return 'http://purl.org/sipwise/ngcp-api/#rel-numbers'; -} - 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/], - Journal => [qw/admin reseller/], +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 handle_journalsitem_put handle_journalsitem_patch/]; +} + +sub update_item_model { + my ($self, $c, $item, $old_resource, $resource, $form) = @_; + my $schema = $c->model('DB'); + + # we maybe want to remove such checks to compare readonly fields: + foreach my $field(qw/cc ac sn is_primary/) { + unless(($old_resource->{$field} // '') eq ($resource->{$field} // '') + or ('JSON::false' eq ref $resource->{$field} and $old_resource->{$field} == 0) + or ('JSON::true' eq ref $resource->{$field} and $old_resource->{$field} == 1)) { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Field '$field' is not allowed to be updated via this API endpoint, use /api/subscriber/\$id instead."); + return; + } } -}); -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, number => $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); + $form //= $self->get_form($c); + return unless $self->validate_form( + c => $c, + form => $form, + resource => $resource, + ); + + my $sub = $schema->resultset('voip_subscribers') + ->find($resource->{subscriber_id}); + unless($sub) { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'subscriber_id', does not exist."); + return; + } + if($c->user->roles eq "subscriberadmin" && $sub->contract_id != $c->user->account_id) { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'subscriber_id', does not exist."); + return; + } + my $old_sub = $schema->resultset('voip_subscribers')->find($old_resource->{subscriber_id}); + if($old_sub->primary_number_id == $old_resource->{id}) { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Cannot reassign primary number, already at subscriber ".$old_sub->id); return; } - return; -} -sub PUT :Allow { - my ($self, $c, $id) = @_; - my $guard = $c->model('DB')->txn_scope_guard; - { - my $preference = $self->require_preference($c); - last unless $preference; + try { - my $item = $self->item_by_id($c, $id); - last unless $self->resource_exists($c, number => $item); - my $resource = $self->get_valid_put_data( + # capture old subscriber's aliases + my $old_aliases_before = NGCP::Panel::Utils::Events::get_aliases_snapshot( c => $c, - id => $id, - media_type => 'application/json', + schema => $schema, + subscriber => $old_sub, ); - last unless $resource; - my $old_resource = { $item->get_inflated_columns }; - - my $form = $self->get_form($c); - $item = $self->update_item($c, $item, $old_resource, $resource, $form); - last unless $item; - - $guard->commit; - - if ('minimal' eq $preference) { - $c->response->status(HTTP_NO_CONTENT); - $c->response->header(Preference_Applied => 'return=minimal'); - $c->response->body(q()); - } else { - my $hal = $self->hal_from_item($c, $item, $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); - } - } - return; -} -sub PATCH :Allow { - my ($self, $c, $id) = @_; - my $guard = $c->model('DB')->txn_scope_guard; - { - my $preference = $self->require_preference($c); - last unless $preference; - - my $json = $self->get_valid_patch_data( - c => $c, - id => $id, - media_type => 'application/json-patch+json', + # capture new subscriber's aliases + my $aliases_before = NGCP::Panel::Utils::Events::get_aliases_snapshot( + c => $c, + schema => $schema, + subscriber => $sub, ); - last unless $json; - - my $item = $self->item_by_id($c, $id); - last unless $self->resource_exists($c, number => $item); - my $old_resource = { $item->get_inflated_columns }; - my $resource = $self->apply_patch($c, $old_resource, $json); - last unless $resource; - - my $form = $self->get_form($c); - $item = $self->update_item($c, $item, $old_resource, $resource, $form); - last unless $item; - - $guard->commit; - - if ('minimal' eq $preference) { - $c->response->status(HTTP_NO_CONTENT); - $c->response->header(Preference_Applied => 'return=minimal'); - $c->response->body(q()); - } else { - my $hal = $self->hal_from_item($c, $item, $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); - } + + my $oldalias = [$old_sub->voip_numbers->all]; + $oldalias = [ map { + if($_->id == $old_sub->primary_number_id) { + # filter primary number + (); + } else { + if($_->id == $item->id) { + # filter number we're about to remove + (); + } else { + # otherwise keep number + { e164 => { cc => $_->cc, ac => $_->ac, sn => $_->sn } }; + } + } + } @{ $oldalias } ]; + + NGCP::Panel::Utils::Subscriber::update_subscriber_numbers( + c => $c, + schema => $schema, + alias_numbers => $oldalias, + reseller_id => $old_sub->contract->contact->reseller_id, + subscriber_id => $old_sub->id, + ); + + my $newalias = [ $sub->voip_numbers->all ]; + $newalias = [ map { + if($_->id == $sub->primary_number_id) { + # filter primary number + (); + } else { + if($_->id == $item->id) { + # filter number we're about to remove + (); + } else { + # otherwise keep number + { e164 => { cc => $_->cc, ac => $_->ac, sn => $_->sn } }; + } + } + } @{ $newalias } ]; + push @{ $newalias }, { e164 => { cc => $item->cc, ac => $item->ac, sn => $item->sn } }; + + NGCP::Panel::Utils::Subscriber::update_subscriber_numbers( + c => $c, + schema => $schema, + alias_numbers => $newalias, + reseller_id => $sub->contract->contact->reseller_id, + subscriber_id => $sub->id, + ); + + # edr events for old sub + my $old_sub_profile = $old_sub->provisioning_voip_subscriber->profile_id; + NGCP::Panel::Utils::Events::insert_profile_events( + c => $c, schema => $schema, subscriber_id => $old_sub->id, + old => $old_sub_profile, new => $old_sub_profile, + %$old_aliases_before, + ); + + # edr events for new sub + my $new_sub_profile = $sub->provisioning_voip_subscriber->profile_id; + NGCP::Panel::Utils::Events::insert_profile_events( + c => $c, schema => $schema, subscriber_id => $sub->id, + old => $new_sub_profile, new => $new_sub_profile, + %$aliases_before, + ); + + } catch($e) { + $c->log->error("failed to update number: $e"); + $self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update number."); + return; } - return; + + # reload item, in case the id changed (which shouldn't happen) + $item = $self->_item_rs($c)->find({ + cc => $item->cc, ac => $item->ac, sn => $item->sn + }); + + return $item; } -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 handle_journalsitem_put handle_journalsitem_patch/]; -} 1; diff --git a/lib/NGCP/Panel/Role/API/Numbers.pm b/lib/NGCP/Panel/Role/API/Numbers.pm index 220304a0e2..7dc33262d1 100644 --- a/lib/NGCP/Panel/Role/API/Numbers.pm +++ b/lib/NGCP/Panel/Role/API/Numbers.pm @@ -5,14 +5,21 @@ use Sipwise::Base; use parent 'NGCP::Panel::Role::API'; -use boolean qw(true); use Data::HAL qw(); use Data::HAL::Link qw(); -use HTTP::Status qw(:constants); -use JSON::Types; use NGCP::Panel::Form; -use NGCP::Panel::Utils::XMLDispatcher; -use NGCP::Panel::Utils::Prosody; + +sub resource_name{ + return 'numbers'; +} + +sub dispatch_path{ + return '/api/numbers/'; +} + +sub relation{ + return 'http://purl.org/sipwise/ngcp-api/#rel-numbers'; +} sub get_form { my ($self, $c) = @_; @@ -28,45 +35,6 @@ sub get_form { return; } -sub hal_from_item { - my ($self, $c, $item, $form) = @_; - my %resource = $item->get_inflated_columns; - - my $hal = Data::HAL->new( - links => [ - Data::HAL::Link->new( - relation => 'curies', - href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}', - name => 'ngcp', - templated => true, - ), - 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)), - Data::HAL::Link->new(relation => 'ngcp:subscribers', href => sprintf("/api/subscribers/%d", $item->subscriber_id)), - $self->get_journal_relation_link($item->id), - ], - relation => 'ngcp:'.$self->resource_name, - ); - - $form //= $self->get_form($c); - - $self->validate_form( - c => $c, - resource => \%resource, - form => $form, - run => 0, - ); - - $resource{id} = int($item->id); - if($c->user->roles eq "admin") { - $resource{reseller_id} = int($item->reseller_id); - } - - $hal->resource({%resource}); - return $hal; -} - sub _item_rs { my ($self, $c) = @_; @@ -106,145 +74,19 @@ sub _item_rs { return $item_rs; } -sub item_by_id { - my ($self, $c, $id) = @_; - - my $item_rs = $self->item_rs($c); - return $item_rs->find($id); +sub hal_links{ + my($self, $c, $item, $resource, $form) = @_; + return [ + Data::HAL::Link->new(relation => 'ngcp:subscribers', href => sprintf("/api/subscribers/%d", $item->subscriber_id)), + ]; } -sub update_item { - my ($self, $c, $item, $old_resource, $resource, $form) = @_; - my $schema = $c->model('DB'); - - # we maybe want to remove such checks to compare readonly fields: - foreach my $field(qw/cc ac sn is_primary/) { - unless(($old_resource->{$field} // '') eq ($resource->{$field} // '') - or ('JSON::false' eq ref $resource->{$field} and $old_resource->{$field} == 0) - or ('JSON::true' eq ref $resource->{$field} and $old_resource->{$field} == 1)) { - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Field '$field' is not allowed to be updated via this API endpoint, use /api/subscriber/\$id instead."); - return; - } - } - - $form //= $self->get_form($c); - return unless $self->validate_form( - c => $c, - form => $form, - resource => $resource, - ); - - my $sub = $schema->resultset('voip_subscribers') - ->find($resource->{subscriber_id}); - unless($sub) { - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'subscriber_id', does not exist."); - return; - } - if($c->user->roles eq "subscriberadmin" && $sub->contract_id != $c->user->account_id) { - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'subscriber_id', does not exist."); - return; - } - my $old_sub = $schema->resultset('voip_subscribers')->find($old_resource->{subscriber_id}); - if($old_sub->primary_number_id == $old_resource->{id}) { - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Cannot reassign primary number, already at subscriber ".$old_sub->id); - return; - } - - try { - - # capture old subscriber's aliases - my $old_aliases_before = NGCP::Panel::Utils::Events::get_aliases_snapshot( - c => $c, - schema => $schema, - subscriber => $old_sub, - ); - - # capture new subscriber's aliases - my $aliases_before = NGCP::Panel::Utils::Events::get_aliases_snapshot( - c => $c, - schema => $schema, - subscriber => $sub, - ); - - my $oldalias = [$old_sub->voip_numbers->all]; - $oldalias = [ map { - if($_->id == $old_sub->primary_number_id) { - # filter primary number - (); - } else { - if($_->id == $item->id) { - # filter number we're about to remove - (); - } else { - # otherwise keep number - { e164 => { cc => $_->cc, ac => $_->ac, sn => $_->sn } }; - } - } - } @{ $oldalias } ]; - - NGCP::Panel::Utils::Subscriber::update_subscriber_numbers( - c => $c, - schema => $schema, - alias_numbers => $oldalias, - reseller_id => $old_sub->contract->contact->reseller_id, - subscriber_id => $old_sub->id, - ); - - - - my $newalias = [ $sub->voip_numbers->all ]; - $newalias = [ map { - if($_->id == $sub->primary_number_id) { - # filter primary number - (); - } else { - if($_->id == $item->id) { - # filter number we're about to remove - (); - } else { - # otherwise keep number - { e164 => { cc => $_->cc, ac => $_->ac, sn => $_->sn } }; - } - } - } @{ $newalias } ]; - push @{ $newalias }, { e164 => { cc => $item->cc, ac => $item->ac, sn => $item->sn } }; - - NGCP::Panel::Utils::Subscriber::update_subscriber_numbers( - c => $c, - schema => $schema, - alias_numbers => $newalias, - reseller_id => $sub->contract->contact->reseller_id, - subscriber_id => $sub->id, - ); - - # edr events for old sub - my $old_sub_profile = $old_sub->provisioning_voip_subscriber->profile_id; - NGCP::Panel::Utils::Events::insert_profile_events( - c => $c, schema => $schema, subscriber_id => $old_sub->id, - old => $old_sub_profile, new => $old_sub_profile, - %$old_aliases_before, - ); - - # edr events for new sub - my $new_sub_profile = $sub->provisioning_voip_subscriber->profile_id; - NGCP::Panel::Utils::Events::insert_profile_events( - c => $c, schema => $schema, subscriber_id => $sub->id, - old => $new_sub_profile, new => $new_sub_profile, - %$aliases_before, - ); - - } catch($e) { - $c->log->error("failed to update number: $e"); - $self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update number."); - return; +sub post_process_hal_resource { + my($self, $c, $item, $resource, $form) = @_; + if($c->user->roles eq "admin") { + $resource->{reseller_id} = int($item->reseller_id); } - - # reload item, in case the id changed (which shouldn't happen) - $item = $self->_item_rs($c)->find({ - cc => $item->cc, ac => $item->ac, sn => $item->sn - }); - - return $item; + return $resource; } 1; diff --git a/t/api-rest/api-numbers.t b/t/api-rest/api-numbers.t new file mode 100644 index 0000000000..a1e46de440 --- /dev/null +++ b/t/api-rest/api-numbers.t @@ -0,0 +1,103 @@ +use strict; +use warnings; + +use Test::Collection; +use Test::FakeData; +use Test::More; +use Data::Dumper; +use Clone qw/clone/; + +#use NGCP::Panel::Utils::Subscriber; + +my $test_machine = Test::Collection->new( + name => 'numbers', +); +my $fake_data = Test::FakeData->new; + +$fake_data->set_data_from_script({ + 'numbers' => { + 'data' => { + subscriber_id => sub { return shift->get_id('subscribers',@_); }, + cc => 1, + ac => 1, + sn => 1, + }, + }, +}); + +my $fake_data_processed = $fake_data->process('numbers'); +$test_machine->DATA_ITEM_STORE($fake_data_processed); +$test_machine->form_data_item(); + +{ + my $ticket = '32913'; + my $time = time(); + my $subscriber_test_machine = Test::Collection->new( + name => 'subscribers', + ); + $subscriber_test_machine->DATA_ITEM_STORE($fake_data->process('subscribers')); + my $subscriber1 = $fake_data->create('subscribers')->[0]; + my $subscriber2 = $fake_data->create('subscribers')->[0]; + #print Dumper $subscriber1; + $subscriber1->{content}->{alias_numbers} = [ + { cc=> '111', ac => $ticket, sn => $time }, + { cc=> '112', ac => $ticket, sn => $time }, + { cc=> '113', ac => $ticket, sn => $time }, + ]; + $subscriber2->{content}->{alias_numbers} = [ + { cc=> '211', ac => $ticket, sn => $time }, + { cc=> '212', ac => $ticket, sn => $time }, + { cc=> '213', ac => $ticket, sn => $time }, + ]; + my ($res,$content,$request); + ($res,$content,$request) = $subscriber_test_machine->request_put(@{$subscriber1}{qw/content location/}); + ($res,$content,$request) = $subscriber_test_machine->request_put(@{$subscriber2}{qw/content location/}); + my ($alias1) = $test_machine->get_item_hal('numbers', '/api/numbers/?type=alias&subscriber_id='.$subscriber1->{content}->{id}); + my ($alias2) = $test_machine->get_item_hal('numbers','/api/numbers/?type=alias&subscriber_id='.$subscriber2->{content}->{id}); + + test_numbers_reassign($alias1,$alias2,$subscriber1,$subscriber2); + + my $pbxsubscriberadmin = $fake_data->create('subscribers')->[0]; + ($res) = $subscriber_test_machine->request_patch([ + { op => 'replace', path => '/administrative', value => 1 }, + { op => 'replace', path => '/webpassword', value => 'pbxadminpwd' }, + { op => 'replace', path => '/password', value => 'pbxadminpwd' } + ] , $pbxsubscriberadmin->{location}); + $subscriber_test_machine->http_code_msg(200, "PATCH for /pbxsubscriberadmin/", $res); + $pbxsubscriberadmin = $subscriber_test_machine->get_item_hal('subscribers', $pbxsubscriberadmin->{location}); + + $test_machine->set_subscriber_credentials($pbxsubscriberadmin->{content}); + $test_machine->runas('subscriber'); + + test_numbers_reassign($alias1,$alias2,$subscriber1,$subscriber2); + + $test_machine->runas('admin'); + + $subscriber_test_machine->clear_test_data_all();#fake data aren't registered in this test +} + +$fake_data->clear_test_data_all(); +$test_machine->clear_test_data_all();#fake data aren't registered in this test machine, so they will stay. +$fake_data->clear_test_data_all(); +undef $test_machine; +undef $fake_data; +done_testing; + +sub test_numbers_reassign{ + my($alias1,$alias2,$subscriber1,$subscriber2) = @_; + my $res; + $alias1->{content}->{subscriber_id} = $subscriber2->{content}->{id}; + ($res) = $test_machine->request_patch([ { op => 'replace', path => '/subscriber_id', value => $subscriber2->{content}->{id} } ] , $alias1->{location}); + $test_machine->http_code_msg(200, "PATCH for /numbers/", $res); + + ($res) = $test_machine->request_patch([ { op => 'replace', path => '/subscriber_id', value => $subscriber1->{content}->{id} } ] , $alias1->{location}); + $test_machine->http_code_msg(200, "PATCH for /numbers/", $res); + + ($res) = $test_machine->request_patch([ { op => 'replace', path => '/subscriber_id', value => $subscriber1->{content}->{id} } ] , $alias2->{location}); + $test_machine->http_code_msg(200, "PATCH for /numbers/", $res); + + ($res) = $test_machine->request_patch([ { op => 'replace', path => '/subscriber_id', value => $subscriber2->{content}->{id} } ] , $alias2->{location}); + $test_machine->http_code_msg(200, "PATCH for /numbers/", $res); +} + +# vim: set tabstop=4 expandtab: diff --git a/t/api-rest/api-subscribers.t b/t/api-rest/api-subscribers.t index 6de08e08f2..3381f1f3b9 100644 --- a/t/api-rest/api-subscribers.t +++ b/t/api-rest/api-subscribers.t @@ -6,7 +6,7 @@ use Test::FakeData; use Test::More; use Data::Dumper; use Clone qw/clone/; - +use feature 'state'; #use NGCP::Panel::Utils::Subscriber; my $test_machine = Test::Collection->new( @@ -53,18 +53,22 @@ $fake_data->set_data_from_script({ }, 'query' => [['username',{'query_type'=> 'string_like'}]], 'create_special'=> sub { + state $num; + $num //= 0; + $num++; my ($self,$collection_name,$test_machine) = @_; my $pilot = $test_machine->get_item_hal('subscribers','/api/subscribers/?customer_id='.$self->data->{$collection_name}->{data}->{customer_id}.'&'.'is_pbx_pilot=1'); if($pilot->{total_count} <= 0){ undef $pilot; } - $test_machine->check_create_correct(1, sub{ + return $test_machine->check_create_correct(1, sub{ + my $time = time; $_[0]->{is_pbx_pilot} = ($pilot || $_[1]->{i} > 1)? 0 : 1; - $_[0]->{pbx_extension} = time(); - $_[0]->{webusername} .= time(); - $_[0]->{username} .= time(); + $_[0]->{pbx_extension} = $time.$num; + $_[0]->{webusername} .= $time.$num; + $_[0]->{username} .= $time.$num; delete $_[0]->{alias_numbers}; - $_[0]->{primary_number}->{sn} = time(); + $_[0]->{primary_number}->{sn} = $time.$num; }, $self->data->{$collection_name}->{data} ); }, 'update_change_fields' => [qw/modify_timestamp create_timestamp primary_number_id/], diff --git a/t/lib/Test/Collection.pm b/t/lib/Test/Collection.pm index da6026f52f..f7b6844a55 100644 --- a/t/lib/Test/Collection.pm +++ b/t/lib/Test/Collection.pm @@ -677,6 +677,7 @@ sub get_request_patch{ $content and $req->content($content); return $req; } + sub request_put{ my($self,$content,$uri) = @_; $uri ||= $self->get_uri_current; @@ -687,6 +688,7 @@ sub request_put{ return wantarray ? ($res,$rescontent,$req) : $res; } } + sub request_patch{ my($self,$content, $uri, $req) = @_; $uri ||= $self->get_uri_current; @@ -718,6 +720,7 @@ sub request_post{ my $additional_info = { id => $self->get_id_from_location($location) // '' }; return wantarray ? ($res,$rescontent,$req,$content,$additional_info) : $res; }; + sub request_options{ my ($self,$uri) = @_; # OPTIONS tests @@ -1336,6 +1339,8 @@ sub put_and_get{ my($put_out,$put_get_out,$get_out); $params //= (); + + $put_in->{uri} //= $put_in->{location}; $get_in->{ignore_fields} //= []; $put_in->{ignore_fields} //= [];