diff --git a/lib/NGCP/Panel/Controller/API/LnpCarriersItem.pm b/lib/NGCP/Panel/Controller/API/LnpCarriersItem.pm index df0acd8505..07c235ee52 100644 --- a/lib/NGCP/Panel/Controller/API/LnpCarriersItem.pm +++ b/lib/NGCP/Panel/Controller/API/LnpCarriersItem.pm @@ -100,7 +100,7 @@ sub PATCH :Allow { last unless $preference; my $json = $self->get_valid_patch_data( - c => $c, + c => $c, id => $id, media_type => 'application/json-patch+json', ); @@ -115,7 +115,7 @@ sub PATCH :Allow { 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) { @@ -156,7 +156,7 @@ sub PUT :Allow { $item = $self->update_item($c, $item, $old_resource, $resource, $form); last unless $item; - $guard->commit; + $guard->commit; if ('minimal' eq $preference) { $c->response->status(HTTP_NO_CONTENT); @@ -182,6 +182,12 @@ sub DELETE :Allow { { my $item = $self->item_by_id($c, $id); last unless $self->resource_exists($c, lnpcarrier => $item); + my $number_count = $item->lnp_numbers->count; + if ($number_count > 0) { + $c->log->error("failed to delete lnp carrier, there are still $number_count lnp numbers linked to it."); + $self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete lnp carrier."); + last; + } $item->delete; $guard->commit; diff --git a/lib/NGCP/Panel/Controller/API/LnpNumbers.pm b/lib/NGCP/Panel/Controller/API/LnpNumbers.pm index 1302a1cf3f..c0342cd759 100644 --- a/lib/NGCP/Panel/Controller/API/LnpNumbers.pm +++ b/lib/NGCP/Panel/Controller/API/LnpNumbers.pm @@ -128,7 +128,7 @@ sub GET :Allow { $hal->resource({ total_count => $total_count, }); - my $response = HTTP::Response->new(HTTP_OK, undef, + 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); @@ -164,7 +164,7 @@ sub POST :Allow { my $schema = $c->model('DB'); my $resource; my $data = $self->get_valid_raw_post_data( - c => $c, + c => $c, media_type => [qw#application/json text/csv#], ); last unless $data; @@ -233,27 +233,20 @@ sub POST :Allow { my $carrier = $c->model('DB')->resultset('lnp_providers')->find($resource->{lnp_provider_id}); unless($carrier) { - $c->log->error("invalid carrier_id '$$resource{lnp_provider_id}'"); # TODO: user, message, trace, ... - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "LNP carrier_id does not exist"); + $c->log->error("invalid carrier_id '$$resource{lnp_provider_id}'"); + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "lnp carrier_id does not exist"); last; } - - - my $item; - -=pod - # for now numbers can be inserted duplicated, so don't check - $item = $c->model('DB')->resultset('lnp_numbers')->find({ - lnp_provider_id => $resource->{lnp_provider_id}, - number => $resource->{number}, - }); - if($item) { - $c->log->error("lnp number with number '$$resource{number}' already exists for carrier_id '$$resource{lnp_provider_id}'"); # TODO: user, message, trace, ... - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "LNP number with this number already exists for this LNP carrier"); + if ($c->model('DB')->resultset('lnp_numbers')->search({ + lnp_provider_id => $carrier->id, + number => $resource->{number} + },undef)->count > 0) { + $c->log->error("LNP number '$$resource{number}' already defined for carrier_id '$$resource{lnp_provider_id}'"); + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "lnp number already exists for lnp carrier"); last; } -=cut + my $item; try { $item = $c->model('DB')->resultset('lnp_numbers')->create($resource); } catch($e) { diff --git a/lib/NGCP/Panel/Controller/Billing.pm b/lib/NGCP/Panel/Controller/Billing.pm index 00e35aefa9..a0eaa33777 100644 --- a/lib/NGCP/Panel/Controller/Billing.pm +++ b/lib/NGCP/Panel/Controller/Billing.pm @@ -312,10 +312,10 @@ sub terminate :Chained('base') :PathPart('terminate') :Args(0) { try { #todo: putting the profile fetch into a transaction wouldn't help since the count columns a prone to phantom reads... unless($profile->get_column('contract_cnt') == 0) { - die('Cannnot terminate billing profile that is still used in profile mappings'); + die(['Cannnot terminate billing profile that is still used in profile mappings', "showdetails"]); } unless($profile->get_column('package_cnt') == 0) { - die('Cannnot terminate billing profile that is still used in profile packages'); + die(['Cannnot terminate billing profile that is still used in profile packages', "showdetails"]); } $profile->update({ status => 'terminated', diff --git a/lib/NGCP/Panel/Controller/Customer.pm b/lib/NGCP/Panel/Controller/Customer.pm index 7fbe99f8c4..446adc2a05 100644 --- a/lib/NGCP/Panel/Controller/Customer.pm +++ b/lib/NGCP/Panel/Controller/Customer.pm @@ -1062,7 +1062,7 @@ sub topup_cash :Chained('base_restricted') :PathPart('balance/topupcash') :Args( entities => $entities, err_code => sub { my ($err) = @_; - die($err); + die([$err, "showdetails"]); }, ); @@ -1154,7 +1154,7 @@ sub topup_voucher :Chained('base_restricted') :PathPart('balance/topupvoucher') entities => $entities, err_code => sub { my ($err) = @_; - die($err); + die([$err, "showdetails"]); }, ); diff --git a/lib/NGCP/Panel/Controller/Lnp.pm b/lib/NGCP/Panel/Controller/Lnp.pm index 15356e62c3..8bf665ee06 100644 --- a/lib/NGCP/Panel/Controller/Lnp.pm +++ b/lib/NGCP/Panel/Controller/Lnp.pm @@ -32,6 +32,9 @@ sub list :Chained('/') :PathPart('lnp') :CaptureArgs(0) { { name => "prefix", "search" => 1, "title" => $c->loc("Prefix") }, { name => "authoritative", "search" => 0, "title" => $c->loc("Authoritative") }, { name => "skip_rewrite", "search" => 0, "title" => $c->loc("Skip Rewrite") }, + #better leave this out for performance reasons: + #{ name => "numbers_count", "search" => 0, "title" => $c->loc("#Numbers"), + # literal_sql=>"select count(n.id) from `billing`.`lnp_numbers` n where n.`lnp_provider_id` = `me`.`id`" }, ]); my $number_rs = $c->model('DB')->resultset('lnp_numbers'); @@ -77,7 +80,7 @@ sub carrier_base :Chained('list') :PathPart('carrier') :CaptureArgs(1) { NGCP::Panel::Utils::Message::error( c => $c, data => { id => $carrier_id }, - desc => $c->loc('Invalid lnp carrier id detected!'), + desc => $c->loc('Invalid LNP carrier id detected!'), ); $c->flash(carrier_messages => delete $c->flash->{messages}); $c->response->redirect($c->uri_for()); @@ -193,10 +196,20 @@ sub carrier_delete :Chained('carrier_base') :PathPart('delete') :Args(0) { my ($self, $c) = @_; my $carrier = $c->stash->{carrier_result}; + my $number_count = $carrier->lnp_numbers->count; + if ($number_count > 0) { + NGCP::Panel::Utils::Message::error( + c => $c, + desc => $c->loc("$number_count lnp numbers still linked to LNP carrier."), + ); + $c->flash(carrier_messages => delete $c->flash->{messages}); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/lnp')); + return; + } + try { my $schema = $c->model('DB'); $schema->txn_do(sub { - $carrier->lnp_numbers->delete; $carrier->delete; }); NGCP::Panel::Utils::Message::info( @@ -210,7 +223,7 @@ sub carrier_delete :Chained('carrier_base') :PathPart('delete') :Args(0) { c => $c, error => $e, data => $c->stash->{carrier}, - desc => $c->loc('Failed to terminate LNP carrier'), + desc => $c->loc('Failed to delete LNP carrier'), ); $c->flash(carrier_messages => delete $c->flash->{messages}); }; @@ -224,7 +237,7 @@ sub number_base :Chained('list') :PathPart('number') :CaptureArgs(1) { NGCP::Panel::Utils::Message::error( c => $c, data => { id => $number_id }, - desc => $c->loc('Invalid lnp number id detected!'), + desc => $c->loc('Invalid LNP number id detected!'), ); $c->flash(number_messages => delete $c->flash->{messages}); $c->response->redirect($c->uri_for()); @@ -271,11 +284,35 @@ sub number_edit :Chained('number_base') :PathPart('edit') { back_uri => $c->req->uri, ); if($posted && $form->validated) { + $form->values->{lnp_provider_id} = $form->values->{lnp_provider}{id}; + delete $form->values->{lnp_provider}; + my $carrier = $c->model('DB')->resultset('lnp_providers')->find($form->values->{lnp_provider_id}); + unless($carrier) { + NGCP::Panel::Utils::Message::error( + c => $c, + data => { id => $form->values->{lnp_provider_id} }, + desc => $c->loc('Invalid LNP provider id detected!'), + ); + $c->flash(number_messages => delete $c->flash->{messages}); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/lnp')); + return; + } + if ($c->model('DB')->resultset('lnp_numbers')->search({ + lnp_provider_id => $carrier->id, + number => $form->values->{number} + },undef)->count > 0) { + NGCP::Panel::Utils::Message::error( + c => $c, + data => { number => $form->values->{number} }, + desc => $c->loc("LNP number '" . $form->values->{number} . "' already defined for LNP provider '" . $carrier->name . "'!"), + ); + $c->flash(number_messages => delete $c->flash->{messages}); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/lnp')); + return; + } try { my $schema = $c->model('DB'); $schema->txn_do(sub { - $form->values->{lnp_provider_id} = $form->values->{lnp_provider}{id}; - delete $form->values->{lnp_provider}; if(length $form->values->{start}) { $form->values->{start} .= 'T00:00:00'; } else { @@ -287,15 +324,6 @@ sub number_edit :Chained('number_base') :PathPart('edit') { $form->values->{end} = undef; } $form->values->{routing_number} = undef unless(length $form->values->{routing_number}); - my $carrier = $c->model('DB')->resultset('lnp_providers')->find($form->values->{lnp_provider_id}); - unless($carrier) { - NGCP::Panel::Utils::Message::error( - c => $c, - data => { id => $form->values->{lnp_provider_id} }, - desc => $c->loc('Invalid lnp provider id detected!'), - ); - $c->flash(number_messages => delete $c->flash->{messages}); - } $c->stash->{number_result}->update($form->values); }); @@ -339,18 +367,33 @@ sub number_create :Chained('list') :PathPart('number_create') :Args(0) { back_uri => $c->req->uri, ); if($posted && $form->validated) { + $form->values->{lnp_provider_id} = $form->values->{lnp_provider}{id}; + delete $form->values->{lnp_provider}; + my $carrier = $c->model('DB')->resultset('lnp_providers')->find($form->values->{lnp_provider_id}); + unless($carrier) { + NGCP::Panel::Utils::Message::error( + c => $c, + data => { id => $form->values->{lnp_provider_id} }, + desc => $c->loc('Invalid LNP provider id detected!'), + ); + $c->flash(number_messages => delete $c->flash->{messages}); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/lnp')); + return; + } + if ($c->model('DB')->resultset('lnp_numbers')->search({ + lnp_provider_id => $carrier->id, + number => $form->values->{number} + },undef)->count > 0) { + NGCP::Panel::Utils::Message::error( + c => $c, + data => { number => $form->values->{number} }, + desc => $c->loc("LNP number '" . $form->values->{number} . "' already defined for LNP provider '" . $carrier->name . "'!"), + ); + $c->flash(number_messages => delete $c->flash->{messages}); + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/lnp')); + return; + } try { - $form->values->{lnp_provider_id} = $form->values->{lnp_provider}{id}; - delete $form->values->{lnp_provider}; - my $carrier = $c->model('DB')->resultset('lnp_providers')->find($form->values->{lnp_provider_id}); - unless($carrier) { - NGCP::Panel::Utils::Message::error( - c => $c, - data => { id => $form->values->{lnp_provider_id} }, - desc => $c->loc('Invalid lnp provider id detected!'), - ); - $c->flash(number_messages => delete $c->flash->{messages}); - } if(length $form->values->{start}) { $form->values->{start} .= 'T00:00:00'; } else { @@ -495,4 +538,3 @@ sub numbers_download :Chained('list') :PathPart('download') :Args(0) { __PACKAGE__->meta->make_immutable; 1; - diff --git a/lib/NGCP/Panel/Controller/Network.pm b/lib/NGCP/Panel/Controller/Network.pm index 7738a9864d..4d7ea928b8 100644 --- a/lib/NGCP/Panel/Controller/Network.pm +++ b/lib/NGCP/Panel/Controller/Network.pm @@ -92,7 +92,7 @@ sub create :Chained('network_list') :PathPart('create') :Args(0) { 'reseller.create' => $c->uri_for('/reseller/create'), }, back_uri => $c->req->uri, - ); + ); if($posted && $form->validated) { try { my $reseller_id = ($c->user->is_superuser ? $form->values->{reseller}{id} : $c->user->reseller_id); @@ -108,7 +108,7 @@ sub create :Chained('network_list') :PathPart('create') :Args(0) { delete $c->session->{created_objects}->{reseller}; $c->session->{created_objects}->{network} = { id => $bn->id }; }); - + NGCP::Panel::Utils::Message::info( c => $c, desc => $c->loc('Billing Network successfully created'), @@ -179,7 +179,7 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { try { $c->model('DB')->schema->txn_do( sub { - + $c->stash->{'network_result'}->update({ name => $form->values->{name}, description => $form->values->{description}, @@ -192,7 +192,7 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { NGCP::Panel::Utils::Message::info( c => $c, desc => $c->loc('Billing network successfully updated'), - ); + ); } catch ($e) { NGCP::Panel::Utils::Message::error( c => $c, @@ -219,10 +219,10 @@ sub terminate :Chained('base') :PathPart('terminate') :Args(0) { try { #todo: putting the network fetch into a transaction wouldn't help since the count columns a prone to phantom reads... unless($network->get_column('contract_cnt') == 0) { - die('Cannnot terminate billing network that is still used in profile mappings'); + die(['Cannnot terminate billing network that is still used in profile mappings', "showdetails"]); } unless($network->get_column('package_cnt') == 0) { - die('Cannnot terminate billing network that is still used in profile packages'); + die(['Cannnot terminate billing network that is still used in profile packages', "showdetails"]); } $network->update({ status => 'terminated', diff --git a/lib/NGCP/Panel/Controller/Package.pm b/lib/NGCP/Panel/Controller/Package.pm index 7b100fa239..5167fb51d0 100644 --- a/lib/NGCP/Panel/Controller/Package.pm +++ b/lib/NGCP/Panel/Controller/Package.pm @@ -93,7 +93,7 @@ sub create :Chained('package_list') :PathPart('create') :Args(0) { 'reseller.create' => $c->uri_for('/reseller/create'), }, back_uri => $c->req->uri, - ); + ); if($posted && $form->validated) { try { $form->values->{reseller_id} = ($c->user->is_superuser ? $form->values->{reseller}{id} : $c->user->reseller_id); @@ -106,16 +106,16 @@ sub create :Chained('package_list') :PathPart('create') :Args(0) { my @mappings_to_create = (); push(@mappings_to_create,@{delete $form->values->{initial_profiles}}); push(@mappings_to_create,@{delete $form->values->{underrun_profiles}}); - push(@mappings_to_create,@{delete $form->values->{topup_profiles}}); + push(@mappings_to_create,@{delete $form->values->{topup_profiles}}); $c->model('DB')->schema->txn_do( sub { my $profile_package = $c->model('DB')->resultset('profile_packages')->create($form->values); foreach my $mapping (@mappings_to_create) { - $profile_package->profiles->create($mapping); + $profile_package->profiles->create($mapping); } delete $c->session->{created_objects}->{reseller}; $c->session->{created_objects}->{package} = { id => $profile_package->id }; }); - + NGCP::Panel::Utils::Message::info( c => $c, desc => $c->loc('Profile package successfully created'), @@ -129,7 +129,7 @@ sub create :Chained('package_list') :PathPart('create') :Args(0) { } NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/package')); } - + $c->stash( close_target => $c->uri_for, create_flag => 1, @@ -151,7 +151,7 @@ sub base :Chained('/package/package_list') :PathPart('') :CaptureArgs(1) { $c->detach; return; } - + my $res = $c->stash->{package_rs}->find($package_id); unless(defined($res)) { NGCP::Panel::Utils::Message::error( @@ -162,7 +162,7 @@ sub base :Chained('/package/package_list') :PathPart('') :CaptureArgs(1) { $c->detach; return; } - + $c->stash(package => {$res->get_inflated_columns}, initial_profiles => [ map { { $_->get_inflated_columns }; } $res->initial_profiles->all ], underrun_profiles => [ map { { $_->get_inflated_columns }; } $res->underrun_profiles->all ], @@ -182,7 +182,7 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { $params->{reseller}{id} = delete $params->{reseller_id}; foreach(qw/balance_interval timely_duration/){ $params->{$_} = { unit => delete $params->{$_.'_unit'}, value => delete $params->{$_.'_value'} }; - } + } $params = merge($params, $c->session->{created_objects}); $form->process( posted => $posted, @@ -197,7 +197,7 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { 'reseller.create' => $c->uri_for('/reseller/create'), }, back_uri => $c->req->uri, - ); + ); if($posted && $form->validated) { try { foreach(qw/balance_interval timely_duration/){ @@ -208,19 +208,19 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { my @mappings_to_create = (); push(@mappings_to_create,@{delete $form->values->{initial_profiles}}); push(@mappings_to_create,@{delete $form->values->{underrun_profiles}}); - push(@mappings_to_create,@{delete $form->values->{topup_profiles}}); + push(@mappings_to_create,@{delete $form->values->{topup_profiles}}); $c->model('DB')->schema->txn_do( sub { my $profile_package = $c->stash->{'package_result'}->update($form->values); - $profile_package->profiles->delete; + $profile_package->profiles->delete; foreach my $mapping (@mappings_to_create) { - $profile_package->profiles->create($mapping); + $profile_package->profiles->create($mapping); } }); NGCP::Panel::Utils::Message::info( c => $c, desc => $c->loc('Profile package successfully updated'), - ); + ); } catch ($e) { NGCP::Panel::Utils::Message::error( c => $c, @@ -228,11 +228,11 @@ sub edit :Chained('base') :PathPart('edit') :Args(0) { desc => $c->loc('Failed to update profile package'), ); } - + NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/package')); - + } - + $c->stash( close_target => $c->uri_for, edit_flag => 1, @@ -247,12 +247,12 @@ sub delete :Chained('base') :PathPart('delete') :Args(0) { try { #todo: putting the package fetch into a transaction wouldn't help since the count columns a prone to phantom reads... unless($package->get_column('contract_cnt') == 0) { - die('Cannnot delete profile package that is still assigned to contracts'); + die(['Cannnot delete profile package that is still assigned to contracts', "showdetails"]); } unless($package->get_column('voucher_cnt') == 0) { - die('Cannnot delete profile package that is assigned to vouchers'); + die(['Cannnot delete profile package that is assigned to vouchers', "showdetails"]); } - + $package->delete; NGCP::Panel::Utils::Message::info( c => $c, @@ -294,7 +294,7 @@ sub details_base :Chained('/') :PathPart('package') :CaptureArgs(1) { my $dispatch_to = '_package_resultset_' . $c->user->roles; my $package_rs = $self->$dispatch_to($c); - + unless($package_id && is_int($package_id)) { $package_id //= ''; NGCP::Panel::Utils::Message::error( @@ -306,7 +306,7 @@ sub details_base :Chained('/') :PathPart('package') :CaptureArgs(1) { $c->detach; return; } - + my $res = $package_rs->find($package_id); unless(defined($res)) { NGCP::Panel::Utils::Message::error( @@ -328,8 +328,8 @@ sub details_base :Chained('/') :PathPart('package') :CaptureArgs(1) { ]); $c->stash->{voucher_dt_columns} = NGCP::Panel::Utils::Datatables::set_columns($c, [ NGCP::Panel::Utils::Voucher::get_datatable_cols($c,1) - ]); - + ]); + $c->stash(package_result => $res); } diff --git a/lib/NGCP/Panel/Role/API/LnpNumbers.pm b/lib/NGCP/Panel/Role/API/LnpNumbers.pm index b8576b2bcf..514a5130a9 100644 --- a/lib/NGCP/Panel/Role/API/LnpNumbers.pm +++ b/lib/NGCP/Panel/Role/API/LnpNumbers.pm @@ -92,19 +92,14 @@ sub update_item { $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "LNP carrier_id does not exist"); return; } - -=pod - # for now numbers can be inserted duplicated, so don't check - my $dup_item = $c->model('DB')->resultset('lnp_numbers')->find({ - lnp_provider_id => $resource->{lnp_provider_id}, - number => $resource->{number}, - }); - if($dup_item && $dup_item->id != $item->id) { - $c->log->error("lnp number with number '$$resource{number}' already exists for carrier_id '$$resource{lnp_provider_id}'"); # TODO: user, message, trace, ... - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "LNP number with this number already exists for this carrier"); + if ($c->model('DB')->resultset('lnp_numbers')->search({ + lnp_provider_id => $carrier->id, + number => $resource->{number} + },undef)->count > 0) { + $c->log->error("LNP number '$$resource{number}' already defined for carrier_id '$$resource{lnp_provider_id}'"); + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "lnp number already exists for lnp carrier"); return; } -=cut $resource->{start} ||= undef; if($resource->{start} && $resource->{start} =~ /^\d{4}-\d{2}-\d{2}$/) { diff --git a/t/api-rest/api-lnp.t b/t/api-rest/api-lnp.t new file mode 100644 index 0000000000..3eb971ccb8 --- /dev/null +++ b/t/api-rest/api-lnp.t @@ -0,0 +1,204 @@ +use Sipwise::Base; +use Net::Domain qw(hostfqdn); +use LWP::UserAgent; +use JSON qw(); +use Test::More; + +use warnings; + +my $is_local_env = 0; + +my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443'); +my ($netloc) = ($uri =~ m!^https?://(.*)/?.*$!); + +my ($ua, $req, $res); +$ua = LWP::UserAgent->new; + +$ua->ssl_opts( + verify_hostname => 0, + SSL_verify_mode => 0, + ); +my $user = $ENV{API_USER} // 'administrator'; +my $pass = $ENV{API_PASS} // 'administrator'; +$ua->credentials($netloc, "api_admin_http", $user, $pass); + +#$ua->add_handler("request_send", sub { +# my ($request, $ua, $h) = @_; +# print $request->method . ' ' . $request->uri . "\n" . ($request->content ? $request->content . "\n" : '') unless $request->header('authorization'); +# return undef; +#}); +#$ua->add_handler("response_done", sub { +# my ($response, $ua, $h) = @_; +# print $response->decoded_content . "\n" if $response->code != 401; +# return undef; +#}); + +my $t = time; + +my %carrier_map = (); +my %number_map = (); + +{ #regular case + my $carrier1 = _create_lnp_provider(); + my $number1 = _create_lnp_number($carrier1, number => '123'); + my $number2 = _create_lnp_number($carrier1, number => '456'); + _delete_lnp_number($number1); + _delete_lnp_number($number2); + _delete_lnp_provider($carrier1); +} + +{ #delete provider with numbers left: + my $carrier1 = _create_lnp_provider(); + my $number1 = _create_lnp_number($carrier1, number => '123'); + _delete_lnp_provider($carrier1, 500); +} + +{ #unique number - insert: + my $carrier1 = _create_lnp_provider(); + my $number1 = _create_lnp_number($carrier1, number => '123'); + my $number2 = _create_lnp_number($carrier1, number => '123', expected_code => 422); + #_delete_lnp_provider($carrier1, expected_code => 500); +} + +{ #unique number - update: + my $carrier1 = _create_lnp_provider(); + my $number1 = _create_lnp_number($carrier1, number => '123'); + my $number2 = _create_lnp_number($carrier1, number => '1234'); + _update_lnp_number($number2, number => '123', expected_code => 422); +} + +#todo: multithread insert testcase + +sub _create_lnp_number { + + my $carrier = shift; + my (%further_opts) = @_; + my $expected_code = delete $further_opts{expected_code} // 201; + $req = HTTP::Request->new('POST', $uri.'/api/lnpnumbers/'); + $req->header('Content-Type' => 'application/json'); + $req->content(JSON::to_json({ + carrier_id => $carrier->{id}, + number => 'test'.$t, + %further_opts, + })); + $res = $ua->request($req); + if ($expected_code eq '201') { + is($res->code, 201, "create test lnp number"); + $req = HTTP::Request->new('GET', $uri.'/'.$res->header('Location')); + $res = $ua->request($req); + is($res->code, 200, "fetch test lnp number"); + my $number = JSON::from_json($res->decoded_content); + $number_map{$carrier->{id}} = $number; + return $number; + } else { + is($res->code, $expected_code, "create test lnp number returns $expected_code"); + return undef; + } + +} + +sub _update_lnp_number { + + my $number = shift; + my (%further_opts) = @_; + my $expected_code = delete $further_opts{expected_code} // 200; + my $url = $uri.'/api/lnpnumbers/'.$number->{id}; + $req = HTTP::Request->new('PUT', $url); + $req->header('Content-Type' => 'application/json'); + $req->header('Prefer' => 'return=representation'); + $req->content(JSON::to_json({ + %$number, + %further_opts, + })); + $res = $ua->request($req); + if ($expected_code eq '200') { + is($res->code, 200, "update test lnp number"); + $number = JSON::from_json($res->decoded_content); + $number_map{$number->{id}} = $number; + return $number; + } else { + is($res->code, $expected_code, "update test lnp number returns $expected_code"); + $req = HTTP::Request->new('GET', $url); + $res = $ua->request($req); + is($res->code, 200, "fetch test lnp number"); + my $got_number = JSON::from_json($res->decoded_content); + is_deeply($got_number,$number,"lnp number unchanged"); + return undef; + } +} + +sub _delete_lnp_number { + + my ($number,$expected_code) = @_; + $expected_code //= 204; + my $url = $uri.'/api/lnpnumbers/'.$number->{id}; + $req = HTTP::Request->new('DELETE', $url); + $res = $ua->request($req); + if ($expected_code eq '204') { + is($res->code, 204, "delete test lnp number"); + $req = HTTP::Request->new('GET', $url); + $res = $ua->request($req); + is($res->code, 404, "test lnp number is not found"); + return delete $number_map{$number->{id}}; + } else { + is($res->code, $expected_code, "create test lnp number returns $expected_code"); + $req = HTTP::Request->new('GET', $url); + $res = $ua->request($req); + is($res->code, 200, "test lnp number is still found"); + return undef; + } + +} + +sub _create_lnp_provider { + + my (%further_opts) = @_; + my $expected_code = delete $further_opts{expected_code} // 201; + $req = HTTP::Request->new('POST', $uri.'/api/lnpcarriers/'); + $req->header('Content-Type' => 'application/json'); + $req->content(JSON::to_json({ + #skip_rewrite => JSON::false, + name => "test_lnp_carrier_".(scalar keys %carrier_map).'_'.$t, + prefix => 'test'.$t, + %further_opts, + })); + $res = $ua->request($req); + if ($expected_code eq '201') { + is($res->code, 201, "create test lnp carrier"); + $req = HTTP::Request->new('GET', $uri.'/'.$res->header('Location')); + $res = $ua->request($req); + is($res->code, 200, "fetch test lnp carrier"); + my $carrier = JSON::from_json($res->decoded_content); + $carrier_map{$carrier->{id}} = $carrier; + return $carrier; + } else { + is($res->code, $expected_code, "create test lnp carrier returns $expected_code"); + return undef; + } + +} + +sub _delete_lnp_provider { + + my ($carrier,$expected_code) = @_; + $expected_code //= 204; + my $url = $uri.'/api/lnpcarriers/'.$carrier->{id}; + $req = HTTP::Request->new('DELETE', $url); + $res = $ua->request($req); + if ($expected_code eq '204') { + is($res->code, 204, "delete test lnp carrier"); + $req = HTTP::Request->new('GET', $url); + $res = $ua->request($req); + is($res->code, 404, "test lnp carrier is not found"); + return delete $carrier_map{$carrier->{id}}; + } else { + is($res->code, $expected_code, "create test lnp carrier returns $expected_code"); + $req = HTTP::Request->new('GET', $url); + $res = $ua->request($req); + is($res->code, 200, "test lnp carrier is still found"); + return undef; + } + +} + +done_testing;