MT#59478 API better transaction and error handling

* Role/Entities*: POST/PUT/PATCH/DELETE methods changes:
  - support deadlock detection and transaction retry
    (2 retry attempts at the moment)
  - improve transaction control, use local $guard
    instead of saving the ref to $c->stash, as in that
    case it went out of scope too late and also reported
    an error message into the log about abnormal $guard out
    of scope interruption
  - move all non transaction related code outside
    of the scope
  - add error handling when methods such as update_item,
    and a like do not return the expected data, instead of
    simply going out of scope and resulting in an uncontrolled
    reply
* Role/API:
  - rework transaction control:
    + get_transaction_control() is renamed to start_transaction()
      to better reflect what it does
    + complete_transaction() is renamed to commit_transaction()
    + remove unused %params arg
    + pass $guard into commit_transaction() instead of having it
      stored as $c->stash->{transaction_guard) that caused the $guard
      ref to be destroyed much late than expected
      (there was also a typo as transaction_quard,
      which is not relevant anymore with the changes
    + add check_deadlock() that is invoked when an exception is caught
      or an $c->errors contain an error, and if the error message
      represents a transaction error, the transaction block is
      re-invoked via "goto TX_START"
  - rework error():
    + it now accepts args as following:
      ($self, $c, $code, $message, @errors)
      # code -> returned as HTTP code in the reply
      # message -> returned as HTTP message in the reply
      # errors -> contain errors for internal logging, last element often contains a DBIx exception
    + populates all @errors into $c->error so they are available on
      demend in the code via $c->error or $c->last_error
    + $c->log->error is not invoked now as the errors become printed
      in log_response()
  - log_response() now prints collected errors from $c->error correctly
    as a separate log line, that is alike to the other api logs so that
    those can be looked up by the request's tx_id, also all errors are
    now printed only into api.log
* Adjust all $self->error() calls in catch($e) to include $e as the last
  argument, as well as the duplicate $c->log->error is removed from
  those ocassions
* Remove all $c->log->error() calls as they are replaced with either
  $self->error() (that logs it correctly into api.log) or
  $c->error('err') that also adds it correctly into api.log
* API::CallForwards: rework to use Entities/EntitiesItem
* API::Contracts: rework POST to use Entities
* API::PeeringGroups: rework POST to use Entities
* API::SubscriberRegistrations: rework POST to use Entities
* API::RewriteRuleSets: improve create_item() functionality
* Utils/Message: add 'api_retry' log type
* $c->session->{api_request_tx_id} is changed to
  $c->stash->{api_request_tx_id} because sometimes the session
  ref is different and a different tx_id becomes used

Change-Id: I633ce7a8047b1bf00a2f6889003088edf0825dcd
mr12.4
Kirill Solomko 1 year ago
parent 1fdaa6bd47
commit 205b27a267

@ -65,7 +65,7 @@ sub create_item {
my $err;
my $res = NGCP::Panel::Utils::Auth::generate_client_cert($c, $admin, sub {
my $e = shift;
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to generate client certificate");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to generate client certificate", $e);
$err = 1;
});
return if $err;

@ -33,8 +33,7 @@ sub delete_item {
ssl_client_certificate => undef,
});
} catch($e) {
$c->log->error("failed to delete administrator certificate: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete administrator certificate.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete administrator certificate.", $e);
return;
}

@ -59,8 +59,7 @@ sub create_item {
try {
$item = $c->model('DB')->resultset('admins')->create($resource);
} catch($e) {
$c->log->error("failed to create admin: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create admin.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create admin.", $e);
return;
}

@ -72,13 +72,13 @@ sub POST :Allow {
}
my $subscriber = $subscriber_rs->first;
unless($subscriber) {
$c->log->error("invalid subscriber id $$resource{subscriber_id} for outbound call");
$self->error($c, HTTP_NOT_FOUND, "Calling subscriber not found.");
$self->error($c, HTTP_NOT_FOUND, "Calling subscriber not found.",
"invalid subscriber id $$resource{subscriber_id} for outbound call");
last;
}
if (($c->user->roles eq "subscriber" || $c->user->roles eq "subscriberadmin") && $subscriber->provisioning_voip_subscriber->id != $c->user->id) {
$c->log->error("Insuficient permissions to apply rewrites for subscriber id $$resource{subscriber_id}");
$self->error($c, HTTP_FORBIDDEN, "Insuficient permissions.");
$self->error($c, HTTP_FORBIDDEN, "Insuficient permissions.",
"Insuficient permissions to apply rewrites for subscriber id $$resource{subscriber_id}");
return;
}
@ -101,8 +101,7 @@ sub POST :Allow {
push @result, $normalized;
}
} catch($e) {
$c->log->error("failed to rewrite number: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to rewrite number.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to rewrite number.", $e);
last;
}

@ -176,8 +176,8 @@ sub POST :Allow {
$c->response->body(q());
} catch($e) {
$c->log->error("failed to upload csv: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"failed to upload csv", $e);
last;
};
} else {
@ -207,8 +207,7 @@ sub POST :Allow {
return_created => 1,
)->[0];
} catch($e) {
$c->log->error("failed to create billing fee: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create billing fee.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create billing fee.", $e);
last;
}
$guard->commit;

@ -125,8 +125,8 @@ sub DELETE :Allow {
try {
$fee->delete;
} catch($e) {
$c->log->error("Failed to delete billing fee with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete billing fee with id '$id'", $e);
last;
}

@ -157,8 +157,7 @@ sub POST :Allow {
$bn->create_related("billing_network_blocks", $block);
}
} catch($e) {
$c->log->error("failed to create billingnetwork: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create billingnetwork.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create billingnetwork.", $e);
return;
};

@ -153,8 +153,8 @@ sub DELETE :Allow {
status => 'terminated'
});
} catch($e) {
$c->log->error("Failed to terminate billingnetwork with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to terminate billingnetwork with id '$id'", $e);
last;
}
$guard->commit;

@ -182,12 +182,10 @@ sub POST :Allow {
$log_error = "failed to create subscriber, reseller-billing profile combination " . $c->qs($1) . " already exists";
@http_errors = ("Reseller-Billing Profile name combination '" . $1 . "' already exists.", "Reseller-Billing Profile name combination already exists.");
}
$c->log->error($log_error); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $http_errors[0], $http_errors[1]);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $http_errors[0], $http_errors[1], $log_error);
last;
} catch($e) {
$c->log->error("failed to create billing profile: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create billing profile.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create billing profile.", $e);
last;
}

@ -173,8 +173,8 @@ sub DELETE :Allow {
terminate_timestamp => NGCP::Panel::Utils::DateTime::current_local
});
} catch($e) {
$c->log->error("Failed to terminate billingprofile with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to terminate billingprofile with id '$id'", $e);
last;
}
$guard->commit;

@ -140,8 +140,7 @@ sub POST :Allow {
try {
$zone = $profile->billing_zones->create($resource);
} catch($e) {
$c->log->error("failed to create billing zone: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create billing zone.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create billing zone.", $e);
last;
}

@ -146,8 +146,8 @@ sub DELETE :Allow {
$zone->billing_fees->delete_all;
$zone->delete;
} catch($e) {
$c->log->error("Failed to delete billing zone with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete billing zone with id '$id'", $e);
last;
}
$guard->commit;

@ -150,8 +150,8 @@ sub DELETE :Allow {
try {
$prov_subs->voip_cc_mappings->delete;
} catch($e) {
$c->log->error("Failed to delete ccmapentries with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete ccmapentries with id '$id'", $e);
last;
}
$guard->commit;

@ -84,8 +84,7 @@ sub create_item {
return $self->hal_from_item($c, $_bset); });
}
} catch($e) {
$c->log->error("failed to create cfbnumberset: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create cfbnumberset.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create cfbnumberset.", $e);
return;
}

@ -190,8 +190,7 @@ sub POST :Allow {
$dset->create_related("voip_cf_destinations", $d);
}
} catch($e) {
$c->log->error("failed to create cfdestinationset: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create cfdestinationset.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create cfdestinationset.", $e);
last;
}

@ -149,8 +149,8 @@ sub DELETE :Allow {
try {
$dset->delete;
} catch($e) {
$c->log->error("Failed to delete cfdestinationset with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete cfdestinationset with id '$id'", $e);
last;
}
$guard->commit;

@ -138,8 +138,7 @@ sub create_item {
return $self->hal_from_item($c, $_sset, "cfsourcesets");
});
} catch($e) {
$c->log->error("failed to create source_set: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create source_set.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create source_set.", $e);
return;
}

@ -149,8 +149,8 @@ sub DELETE :Allow {
try {
$sset->delete;
} catch($e) {
$c->log->error("Failed to delete cfsourceset with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete cfsourceset with id '$id'", $e);
last;
}
$guard->commit;

@ -162,8 +162,7 @@ sub POST :Allow {
$tset->create_related("voip_cf_periods", $t);
}
} catch($e) {
$c->log->error("failed to create cftimeset: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create cftimeset.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create cftimeset.", $e);
last;
}

@ -149,8 +149,8 @@ sub DELETE :Allow {
try {
$tset->delete;
} catch($e) {
$c->log->error("Failed to delete cftimeset with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete cftimeset with id '$id'", $e);
last;
}
$guard->commit;

@ -75,8 +75,8 @@ sub POST :Allow {
}
my $subscriber = $subscriber_rs->first;
unless($subscriber) {
$c->log->error("invalid subscriber id $$resource{subscriber_id} for outbound call");
$self->error($c, HTTP_NOT_FOUND, "Calling subscriber not found.");
$self->error($c, HTTP_NOT_FOUND, "Calling subscriber not found.",
"invalid subscriber id $$resource{subscriber_id} for outbound call");
last;
}
@ -87,8 +87,7 @@ sub POST :Allow {
NGCP::Panel::Utils::Sems::dial_out($c, $subscriber->provisioning_voip_subscriber,
$callee_user, $callee_domain);
} catch($e) {
$c->log->error("failed to dial out: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create call.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create call.", $e);
last;
}

@ -62,50 +62,6 @@ __PACKAGE__->set_config({
allowed_roles => [qw/admin reseller ccareadmin ccare subscriberadmin subscriber/],
});
sub GET :Allow {
my ($self, $c) = @_;
my $page = $c->request->params->{page} // 1;
my $rows = $c->request->params->{rows} // 10;
{
my $cfs = $self->item_rs($c, "callforwards");
(my $total_count, $cfs, my $cfs_rows) = $self->paginate_order_collection($c, $cfs);
my (@embedded, @links);
my $form = $self->get_form($c);
for my $cf (@$cfs_rows) {
try {
push @embedded, $self->hal_from_item($c, $cf, $form);
push @links, Data::HAL::Link->new(
relation => 'ngcp:'.$self->resource_name,
href => sprintf('%s%s', $self->dispatch_path, $cf->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/'),
$self->collection_nav_links($c, $page, $rows, $total_count, $c->request->path, $c->request->query_params);
my $hal = Data::HAL->new(
embedded => [@embedded],
links => [@links],
);
$hal->resource({
total_count => $total_count,
});
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:

@ -44,128 +44,23 @@ __PACKAGE__->set_config({
}
});
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, 'callforward' => $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 delete_item {
my ($self, $c, $item) = @_;
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',
ops => [qw/add replace remove copy/],
);
last unless $json;
my $item = $self->item_by_id($c, $id);
last unless $self->resource_exists($c, subs_for_callforwards => $item);
my $old_resource = $self->hal_from_item($c, $item)->resource;
my $resource = $self->apply_patch($c, $old_resource, $json);
last unless $resource;
my $id = $item->id;
try {
my $form = $self->get_form($c);
$item = $self->update_item($c, $item, $old_resource, $resource, $form);
last unless $item;
my $hal = $self->hal_from_item($c, $item);
last unless $self->add_update_journal_item_hal($c,{ hal => $hal, id => $id });
$guard->commit;
$self->return_representation($c, 'hal' => $hal, 'preference' => $preference );
}
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;
my $item = $self->item_by_id($c, $id);
last unless $self->resource_exists($c, subs_for_callforward => $item);
my $resource = $self->get_valid_put_data(
c => $c,
id => $id,
media_type => 'application/json',
);
last unless $resource;
my $old_resource = undef;
my $form = $self->get_form($c);
my $resource = {};
$item = $self->update_item($c, $item, $old_resource, $resource, $form);
last unless $item;
my $hal = $self->hal_from_item($c, $item);
last unless $self->add_update_journal_item_hal($c,{ hal => $hal, id => $id });
$guard->commit;
$self->return_representation($c, 'hal' => $hal, 'preference' => $preference );
return $item;
} catch($e) {
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete callforward with id '$id'", $e);
last;
}
return;
}
sub DELETE :Allow {
my ($self, $c, $id) = @_;
my $guard = $c->model('DB')->txn_scope_guard;
{
my $item = $self->item_by_id($c, $id);
last unless $self->resource_exists($c, subs_for_callforward => $item);
my $form = $self->get_form($c);
my $old_resource = undef;
my $resource = $self->get_valid_put_data(
c => $c,
id => $id,
media_type => 'application/json',
);
$resource //= {};
last unless $self->add_delete_journal_item_hal($c,{ hal_from_item => sub {
my $self = shift;
my ($c) = @_;
return $self->hal_from_item($c,$item); },
id => $id});
try {
$item = $self->update_item($c, $item, $old_resource, $resource, $form);
} catch($e) {
$c->log->error("Failed to delete callforward with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
last;
}
$guard->commit;
$c->response->status(HTTP_NO_CONTENT);
$c->response->body(q());
}
return;
}

@ -44,8 +44,7 @@ sub GET :Allow {
try {
$data = read_file($item->full_filename);
} catch($e) {
$c->log->error("Failed to read stream file: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to read stream file.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to read stream file.", $e);
last;
}
my $mime_type;

@ -65,8 +65,7 @@ sub DELETE :Allow {
unlink($item->full_filename);
$item->delete;
} catch($e) {
$c->log->error("Failed to delete stream: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete stream.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete stream.", $e);
last;
}
$guard->commit;

@ -26,8 +26,7 @@ sub delete_item {
force_delete => $c->request->params->{force_delete},
);
} catch($e) {
$c->log->error("failed to delete callrecording: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete callrecording.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete callrecording.", $e);
return;
}
return 1;

@ -134,119 +134,88 @@ sub GET :Allow {
return;
}
sub POST :Allow {
my ($self, $c) = @_;
sub create_item {
my ($self, $c, $resource, $form, $process_extras) = @_;
my $schema = $c->model('DB');
$c->model('DB')->set_transaction_isolation('READ COMMITTED');
my $guard = $c->model('DB')->txn_scope_guard;
{
my $schema = $c->model('DB');
my $resource = $self->get_valid_post_data(
c => $c,
media_type => 'application/json',
);
last unless $resource;
my $syscontact = $schema->resultset('contacts')
->search({
'me.status' => { '!=' => 'terminated' },
})->find($resource->{contact_id});
my $form = $self->get_form($c);
$resource->{contact_id} //= undef;
last unless $self->validate_form(
c => $c,
resource => $resource,
form => $form,
);
unless($syscontact) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'contact_id'");
return;
}
my $syscontact = $schema->resultset('contacts')
->search({
'me.status' => { '!=' => 'terminated' },
})->find($resource->{contact_id});
unless($syscontact) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'contact_id'");
last;
}
my $mappings_to_create = [];
last unless NGCP::Panel::Utils::BillingMappings::prepare_billing_mappings(
c => $c,
resource => $resource,
old_resource => undef,
mappings_to_create => $mappings_to_create,
err_code => sub {
my ($err) = @_;
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $err);
});
my $mappings_to_create = [];
last unless NGCP::Panel::Utils::BillingMappings::prepare_billing_mappings(
my $product_class = delete $resource->{type};
my $product = $schema->resultset('products')->search_rs({ class => $product_class })->first;
unless($product) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'type'.");
return;
}
$resource->{product_id} = $product->id;
if (
NGCP::Panel::Utils::Contract::is_peering_reseller_product( c => $c, product => $product )
&&
( my $prepaid_billing_profile_exist = NGCP::Panel::Utils::BillingMappings::check_prepaid_profiles_exist(
c => $c,
resource => $resource,
old_resource => undef,
mappings_to_create => $mappings_to_create,
err_code => sub {
my ($err) = @_;
#$c->log->error($err);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $err);
});
my $product_class = delete $resource->{type};
my $product = $schema->resultset('products')->search_rs({ class => $product_class })->first;
unless($product) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'type'.");
last;
}
$resource->{product_id} = $product->id;
if (
NGCP::Panel::Utils::Contract::is_peering_reseller_product( c => $c, product => $product )
&&
( my $prepaid_billing_profile_exist = NGCP::Panel::Utils::BillingMappings::check_prepaid_profiles_exist(
c => $c,
mappings_to_create => $mappings_to_create) )
) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Peering/reseller contract can't be connected to the prepaid billing profile $prepaid_billing_profile_exist.");
return;
}
if (NGCP::Panel::Utils::Contract::is_peering_product(
c => $c, product => $product) && defined $resource->{max_subscribers}) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Peering contract should not have 'max_subscribers' defined.");
return;
}
my $now = NGCP::Panel::Utils::DateTime::current_local;
$resource->{create_timestamp} = $now;
$resource->{modify_timestamp} = $now;
my $contract;
try {
$contract = $schema->resultset('contracts')->create($resource);
} catch($e) {
$c->log->error("failed to create contract: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create contract.");
last;
}
mappings_to_create => $mappings_to_create) )
) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Peering/reseller contract can't be connected to the prepaid billing profile $prepaid_billing_profile_exist.");
return;
}
if($contract->contact->reseller_id) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "The contact_id is not a valid ngcp:systemcontacts item, but an ngcp:customercontacts item");
last;
}
if (NGCP::Panel::Utils::Contract::is_peering_product(
c => $c, product => $product) && defined $resource->{max_subscribers}) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Peering contract should not have 'max_subscribers' defined.");
return;
}
try {
NGCP::Panel::Utils::BillingMappings::append_billing_mappings(c => $c,
contract => $contract,
mappings_to_create => $mappings_to_create,
);
my $now = NGCP::Panel::Utils::DateTime::current_local;
$resource->{create_timestamp} = $now;
$resource->{modify_timestamp} = $now;
my $contract;
$contract = $self->contract_by_id($c, $contract->id,1,$now);
NGCP::Panel::Utils::ProfilePackages::create_initial_contract_balances(c => $c,
contract => $contract,
);
} catch($e) {
$c->log->error("failed to create contract: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create contract.");
last;
}
try {
$contract = $schema->resultset('contracts')->create($resource);
} catch($e) {
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create contract.", $e);
return;
}
last unless $self->add_create_journal_item_hal($c,sub {
my $self = shift;
my ($c) = @_;
my $_contract = $self->contract_by_id($c, $contract->id, 1);
return $self->hal_from_contract($c,$_contract,$form,$now); });
if($contract->contact->reseller_id) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "The contact_id is not a valid ngcp:systemcontacts item, but an ngcp:customercontacts item");
return;
}
$guard->commit;
try {
NGCP::Panel::Utils::BillingMappings::append_billing_mappings(c => $c,
contract => $contract,
mappings_to_create => $mappings_to_create,
);
$c->response->status(HTTP_CREATED);
$c->response->header(Location => sprintf('/%s%d', $c->request->path, $contract->id));
$c->response->body(q());
$contract = $self->contract_by_id($c, $contract->id,1,$now);
NGCP::Panel::Utils::ProfilePackages::create_initial_contract_balances(c => $c,
contract => $contract,
);
} catch($e) {
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create contract.", $e);
return;
}
return;
return $contract;
}
1;

@ -150,8 +150,7 @@ sub POST :Allow {
try {
$contact = $c->model('DB')->resultset('contacts')->create($resource);
} catch($e) {
$c->log->error("failed to create contact: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create contact.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create contact.", $e);
last;
}

@ -189,8 +189,8 @@ sub DELETE :Allow {
});
$contact->discard_changes();
} catch($e) {
$c->log->error("Failed to terminate contact id '".$contact->id."': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error.",
"Failed to terminate contact id '".$contact->id."'", $e);
last;
};
my $form = $self->get_form($c);

@ -131,8 +131,7 @@ sub POST :Allow {
$cl->create_related('voip_contract_location_blocks', $block);
}
} catch($e) {
$c->log->error("failed to create customer location: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create customer location.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create customer location.", $e);
return;
};

@ -142,8 +142,8 @@ sub DELETE :Allow {
try {
$cl->delete;
} catch($e) {
$c->log->error("Failed to delete customre location with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete customre location with id '$id'", $e);
last;
}
$guard->commit;

@ -245,7 +245,6 @@ sub POST :Allow {
mappings_to_create => $mappings_to_create,
err_code => sub {
my ($err) = @_;
#$c->log->error($err);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $err);
});
@ -266,8 +265,8 @@ sub POST :Allow {
$customer = $schema->resultset('contracts')->create($resource);
$c->log->debug("customer id " . $customer->id . " created");
} catch($e) {
$c->log->error("failed to create customer contract: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create customer.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create customer.",
"failed to create customer contract", $e);
last;
}
@ -301,8 +300,8 @@ sub POST :Allow {
contract => $customer,
);
} catch($e) {
$c->log->error("failed to create customer contract: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create customer.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create customer.",
"failed to create customer contract", $e);
last;
}

@ -160,8 +160,7 @@ sub POST :Allow {
domain => $resource->{domain}
});
} catch($e) {
$c->log->error("failed to create domain: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create domain.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create domain.", $e);
last;
}
@ -177,8 +176,7 @@ sub POST :Allow {
$self->xmpp_domain_reload($c, $resource->{domain}) if $xmpp_reload;
NGCP::Panel::Utils::XMLDispatcher::sip_domain_reload($c, $resource->{domain}) if ($sip_reload);
} catch($e) {
$c->log->error("failed to activate domain: $e. Domain created"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to activate domain. Domain was created");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to activate domain. Domain was created", $e);
$c->response->header(Location => sprintf('/%s%d', $c->request->path, $billing_domain->id));
last;
}

@ -105,8 +105,7 @@ sub DELETE :Allow {
$self->xmpp_domain_disable($c, $domain->domain) if $xmpp_reload;
NGCP::Panel::Utils::XMLDispatcher::sip_domain_reload($c) if $sip_reload;
} catch($e) {
$c->log->error("failed to deactivate domain: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to deactivate domain.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to deactivate domain.", $e);
last;
}

@ -131,16 +131,16 @@ sub POST :Allow {
name => $resource->{name},
});
if($item) {
$c->log->error("email template with name '$$resource{name}' already exists for reseller_id '$$resource{reseller_id}'"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Email template with this name already exists for this reseller");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY,
"Email template with this name already exists for this reseller",
"email template with name '$$resource{name}' already exists for reseller_id '$$resource{reseller_id}'");
last;
}
try {
$item = $c->model('DB')->resultset('email_templates')->create($resource);
} catch($e) {
$c->log->error("failed to create email template: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create email template.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create email template.", $e);
last;
}

@ -126,8 +126,9 @@ sub POST :Allow {
name => $resource->{name},
});
if($dup_item) {
$c->log->error("emergency mapping container with name '$$resource{name}' already exists for this reseller");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "emergency mapping container with this name already exists for this reseller");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY,
"emergency mapping container with this name already exists for this reseller",
"emergency mapping container with name '$$resource{name}' already exists for this reseller");
return;
}
@ -135,8 +136,7 @@ sub POST :Allow {
try {
$item = $schema->resultset('emergency_containers')->create($resource);
} catch($e) {
$c->log->error("failed to create emergency mapping container: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create emergency mapping container.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create emergency mapping container.", $e);
last;
}

@ -124,8 +124,8 @@ sub DELETE :Allow {
last unless $self->resource_exists($c, emergencymappingcontainer => $item);
my $mapping_count = $item->emergency_mappings->count;
if ($mapping_count > 0) {
$c->log->error("failed to delete emergency mapping container, there are still $mapping_count emergency mappings linked to it.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete emergency mapping container.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete emergency mapping container.",
"failed to delete emergency mapping container, there are still $mapping_count emergency mappings linked to it.");
last;
}
$item->delete;

@ -168,12 +168,10 @@ sub POST :Allow {
$resource->{reseller_id} = $c->user->reseller_id;
} else {
unless(defined $resource->{reseller_id}) {
$c->log->error("Missing reseller_id");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "missing reseller_id parameter");
last;
}
unless($schema->resultset('resellers')->find($resource->{reseller_id})) {
$c->log->error("Invalid reseller_id '$$resource{reseller_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "invalid reseller_id '$$resource{reseller_id}'");
last;
}
@ -204,8 +202,8 @@ sub POST :Allow {
$c->response->body(q());
} catch($e) {
$c->log->error("failed to upload csv: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"failed to upload csv", $e);
last;
};
} else {
@ -220,16 +218,17 @@ sub POST :Allow {
my $container = $c->model('DB')->resultset('emergency_containers')->find($resource->{emergency_container_id});
unless($container) {
$c->log->error("invalid emergency container id '$$resource{emergency_container_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "emergency container id does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "emergency container id does not exist",
"invalid emergency container id '$$resource{emergency_container_id}'");
last;
}
if ($c->model('DB')->resultset('emergency_mappings')->search({
emergency_container_id => $container->id,
code => $resource->{code}
},undef)->count > 0) {
$c->log->error("Emergency mapping code '$$resource{code}' already defined for emergency container id '$$resource{emergency_container_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "emergency mapping code already exists for emergency container");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY,
"Emergency mapping code already exists for emergency container",
"Emergency mapping code '$$resource{code}' already defined for emergency container id '$$resource{emergency_container_id}'");
last;
}
@ -237,8 +236,7 @@ sub POST :Allow {
try {
$item = $c->model('DB')->resultset('emergency_mappings')->create($resource);
} catch($e) {
$c->log->error("failed to create emergency mapping: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create emergency mapping.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create emergency mapping.", $e);
last;
}

@ -94,23 +94,21 @@ sub create_item {
my ($self, $c, $resource, $form, $process_extras) = @_;
if (!$c->config->{features}->{faxserver}) {
$c->log->error("faxserver feature is not active.");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Faxserver feature is not active.");
return;
}
my $billing_subscriber = NGCP::Panel::Utils::API::Subscribers::get_active_subscriber($self, $c, $resource->{subscriber_id});
unless($billing_subscriber) {
$c->log->error("invalid subscriber id $$resource{subscriber_id} for fax send");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Fax subscriber not found.");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Fax subscriber not found.",
"invalid subscriber id $$resource{subscriber_id} for fax send");
return;
}
my $prov_subscriber = $billing_subscriber->provisioning_voip_subscriber;
return unless $prov_subscriber;
my $faxpref = $prov_subscriber->voip_fax_preference;
unless ($faxpref && $faxpref->active){
$c->log->error("invalid subscriber fax preferences");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid subscriber fax preferences");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid subscriber fax preferences");
return;
}
try {
@ -125,8 +123,7 @@ sub create_item {
$c->log->debug("faxserver output:\n");
$c->log->debug($output);
} catch($e) {
$c->log->error("failed to send fax: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error", "failed to send fax", $e);
return;
};
return;

@ -36,8 +36,8 @@ sub update_item_model {
my $billing_subscriber = NGCP::Panel::Utils::API::Subscribers::get_active_subscriber($self, $c, $item->id);
unless($billing_subscriber) {
$c->log->error("invalid subscriber id $item->id for fax send");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Fax subscriber not found.");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Fax subscriber not found.",
"invalid subscriber id $item->id for fax send");
return;
}
delete $resource->{id};
@ -67,8 +67,7 @@ sub update_item_model {
$destinations_rs->create($dest);
}
} catch($e) {
$c->log->error("Error Updating faxserversettings: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "faxserversettings could not be updated.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "faxserversettings could not be updated.", $e);
return;
};

@ -47,8 +47,7 @@ sub create_item {
c => $c, set_id => $item->rule->ruleset->id
);
} catch($e) {
$c->log->error("failed to create a header rule actions: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create a header rule actions.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create a header rule actions.", $e);
return;
}

@ -48,8 +48,7 @@ sub create_item {
c => $c, set_id => $item->rule->ruleset->id
);
} catch($e) {
$c->log->error("failed to create a header rule condition: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create a header rule condition.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create a header rule condition.", $e);
return;
}

@ -95,8 +95,7 @@ sub create_item {
);
}
} catch($e) {
$c->log->error("failed to create a header rule set: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create a header rule set.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create a header rule set.", $e);
return;
}

@ -82,8 +82,7 @@ sub create_item {
})->first;
if ($existing_item) {
$c->log->error("header rule with name '$$resource{name}' already exists");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Header rule with this name already exists");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Header rule with this name already exists", "name=$$resource{name}");
return;
}
@ -119,8 +118,7 @@ sub create_item {
c => $c, set_id => $item->ruleset->id
);
} catch($e) {
$c->log->error("failed to create a header rule: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create a header rule.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create a header rule.", $e);
return;
}

@ -139,8 +139,7 @@ sub POST :Allow {
my ($sub, $reseller, $voip_number) = NGCP::Panel::Utils::Interception::subresnum_from_number($c, $resource->{number}, sub {
my ($msg,$field,$response) = @_;
$c->log->error($msg);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $response);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $response, $msg);
return 0;
});
last unless($sub && $reseller);
@ -151,12 +150,10 @@ sub POST :Allow {
$resource->{sip_domain} = $sub->domain->domain;
if($resource->{x3_required} && (!defined $resource->{x3_host} || !defined $resource->{x3_port})) {
$c->log->error("Missing parameter 'x3_host' or 'x3_port' with 'x3_required' activated");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Missing parameter 'x3_host' or 'x3_port' with 'x3_required' activated");
last;
}
if (defined $resource->{x3_port} && !is_int($resource->{x3_port})) {
$c->log->error("Parameter 'x3_port' should be an integer");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Parameter 'x3_port' should be an integer");
last;
}
@ -191,8 +188,7 @@ sub POST :Allow {
});
die "Failed to populate capture agents\n" unless($res);
} catch($e) {
$c->log->error("failed to create interception: " . $c->qs($e)); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create interception");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create interception", $c->qs($e));
last;
}

@ -156,7 +156,6 @@ sub DELETE :Allow {
});
my $res = NGCP::Panel::Utils::Interception::request($c, 'DELETE', $uuid);
unless($res) {
$c->log->error("failed to update capture agents");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update capture agents");
last;
}

@ -116,8 +116,8 @@ sub POST :Allow {
name => $resource->{name},
});
if($dup_item) {
$c->log->error("lnp carrier with name '$$resource{name}' already exists"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "LNP carrier with this name already exists");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "LNP carrier with this name already exists",
"lnp carrier with name '$$resource{name}' already exists");
return;
}
@ -125,8 +125,7 @@ sub POST :Allow {
try {
$item = $schema->resultset('lnp_providers')->create($resource);
} catch($e) {
$c->log->error("failed to create lnp carrier: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create lnp carrier.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create lnp carrier.", $e);
last;
}

@ -123,8 +123,8 @@ sub DELETE :Allow {
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.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete lnp carrier.",
"failed to delete lnp carrier, there are still $number_count lnp numbers linked to it.");
last;
}
$item->delete;

@ -183,8 +183,8 @@ sub POST :Allow {
$c->response->body(q());
} catch($e) {
$c->log->error("failed to upload csv: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"failed to upload csv", $e);
last;
};
} else {
@ -208,8 +208,8 @@ 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}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "lnp carrier_id does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "lnp carrier_id does not exist",
"invalid carrier_id '$$resource{lnp_provider_id}'");
last;
}
# revert "MT#20027: the actual lnp number must be unique across lnp_providers"
@ -218,8 +218,7 @@ sub POST :Allow {
try {
$item = $c->model('DB')->resultset('lnp_numbers')->create($resource);
} catch($e) {
$c->log->error("failed to create lnp number: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create lnp number.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create lnp number.", $e);
last;
}
@ -240,7 +239,6 @@ sub DELETE :Allow {
my $guard = $c->model('DB')->txn_scope_guard;
{
unless (exists $c->req->query_params->{number}) {
$c->log->error("number query parameter required"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "number query parameter required.");
last;
}

@ -147,8 +147,8 @@ sub DELETE :Allow {
try {
$item = $self->update_item($c, $item, $old_resource, $resource, $form, $preference);
} catch($e) {
$c->log->error("Failed to delete manager secretary callforward with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete manager secretary callforward with id '$id'", $e);
last;
}

@ -133,8 +133,8 @@ sub POST :Allow {
level => $resource->{level},
});
if($item) {
$c->log->error("ncos level '$$resource{level}' already exists for reseller_id '$$resource{reseller_id}'"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "NCOS level already exists for this reseller");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "NCOS level already exists for this reseller",
"ncos level '$$resource{level}' already exists for reseller_id '$$resource{reseller_id}'");
last;
}
@ -145,7 +145,6 @@ sub POST :Allow {
});
if (!$time_set) {
my $err = "Time set with id '$resource->{time_set_id}' does not exist or does not belong to this reseller";
$c->log->error($err);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $err);
last;
}
@ -154,8 +153,7 @@ sub POST :Allow {
try {
$item = $c->model('DB')->resultset('ncos_levels')->create($resource);
} catch($e) {
$c->log->error("failed to create ncos level: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create ncos level.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create ncos level.", $e);
last;
}

@ -128,8 +128,8 @@ sub POST :Allow {
$resource->{ncos_level_id},
);
unless($level) {
$c->log->error("invalid ncos_level_id '$$resource{ncos_level_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid ncos_level_id, level does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid ncos_level_id, level does not exist",
"invalid ncos_level_id '$$resource{ncos_level_id}'");
return;
}
@ -137,8 +137,9 @@ sub POST :Allow {
lnp_provider_id => $resource->{lnp_provider_id},
})->first;
if($dup_item) {
$c->log->error("ncos lnp entry with carrier '$$resource{lnp_provider_id}' already exists for ncos_level_id '$$resource{ncos_level_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "NCOS lnp entry already exists for given ncos level");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY,
"NCOS lnp entry already exists for given ncos level",
"ncos lnp entry with carrier '$$resource{lnp_provider_id}' already exists for ncos_level_id '$$resource{ncos_level_id}'");
return;
}
@ -146,8 +147,7 @@ sub POST :Allow {
try {
$item = $level->ncos_lnp_lists->create($resource);
} catch($e) {
$c->log->error("failed to create ncos lnp entry: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create ncos lnp entry.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create ncos lnp entry.", $e);
last;
}

@ -111,15 +111,14 @@ sub create_item {
});
my $lnp_list = $lnp_list_rs->first;
unless($lnp_list) {
$c->log->error("invalid ncos_lnp_list_id '$$resource{ncos_lnp_list_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid ncos_lnp_list_id, lnp list does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid ncos_lnp_list_id, lnp list does not exist",
"invalid ncos_lnp_list_id '$$resource{ncos_lnp_list_id}'");
return;
}
$item = $lnp_list->ncos_lnp_pattern_lists->create($resource);
} catch($e) {
$c->log->error("failed to create a ncos lnp carrier pattern: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create a ncos lnp carrier pattern.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create a ncos lnp carrier pattern.", $e);
return;
}

@ -129,8 +129,8 @@ sub POST :Allow {
}
my $level = $level_rs->first;
unless($level) {
$c->log->error("invalid ncos_level_id '$$resource{ncos_level_id}' for reseller_id '$$resource{reseller_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid ncos_level_id, level does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid ncos_level_id, level does not exist",
"invalid ncos_level_id '$$resource{ncos_level_id}' for reseller_id '$$resource{reseller_id}'");
return;
}
@ -138,8 +138,8 @@ sub POST :Allow {
pattern => $resource->{pattern},
})->first;
if($dup_item) {
$c->log->error("ncos pattern '$$resource{pattern}' already exists for ncos_level_id '$$resource{ncos_level_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "NCOS pattern already exists for given ncos level");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "NCOS pattern already exists for given ncos level",
"ncos pattern '$$resource{pattern}' already exists for ncos_level_id '$$resource{ncos_level_id}'");
return;
}
@ -147,8 +147,7 @@ sub POST :Allow {
try {
$item = $level->ncos_pattern_lists->create($resource);
} catch($e) {
$c->log->error("failed to create ncos level: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create ncos level.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create ncos level.", $e);
last;
}

@ -174,8 +174,7 @@ sub update_item_model {
);
} catch($e) {
$c->log->error("failed to update number: " . $c->qs($e));
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update number.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update number.", $c->qs($e));
return;
}

@ -87,15 +87,13 @@ sub POST :Allow {
})->first;
}
} catch($e) {
$c->log->error("failed to handle a party call control request: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR,
"Failed to handle a party call control request.");
"Failed to handle a party call control request.", $e);
last;
}
unless($sms) {
$c->log->error("failed to find sms with id " . $c->qs($callid) . " and token $token");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY,
"Failed to find sms with callid " . $c->qs($callid) . " and given token");
"Failed to find sms with callid " . $c->qs($callid) . " and given token", $token);
last;
}
if($status eq "ACCEPT") {
@ -120,9 +118,8 @@ sub POST :Allow {
);
$sms->update({ pcc_status => "complete" });
} catch($e) {
$c->log->error("failed to handle a party call control request: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR,
"Failed to handle a party call control request.");
"Failed to handle a party call control request.", $e);
last;
}
} else {
@ -130,9 +127,8 @@ sub POST :Allow {
try {
$sms->update({ pcc_status => "complete" });
} catch($e) {
$c->log->error("failed to handle a party call control request: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR,
"Failed to handle a party call control request.");
"Failed to handle a party call control request.", $e);
last;
}
}

@ -75,9 +75,8 @@ sub POST :Allow {
unless($uuid_string && UUID::parse($uuid_string, $uuid_bin) != -1) {
$res = {success => 0};
$c->log->error("Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
$c->response->status(HTTP_FORBIDDEN);
$c->response->body(JSON::to_json($res));
$self->error($c, HTTP_FORBIDDEN, 'Forbidden',
"Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
return;
}
@ -88,9 +87,8 @@ sub POST :Allow {
);
unless ($redis) {
$res = {success => 0};
$c->log->error("Failed to connect to central redis url " . $c->config->{redis}->{central_url});
$c->response->status(HTTP_INTERNAL_SERVER_ERROR);
$c->response->body(JSON::to_json($res));
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error',
"Failed to connect to central redis url " . $c->config->{redis}->{central_url});
return;
}
$redis->select($c->config->{'Plugin::Session'}->{redis_db});
@ -100,17 +98,15 @@ sub POST :Allow {
my $administrator = $c->model('DB')->resultset('admins')->search({login => $admin})->first;
unless ($administrator) {
$res = {success => 0};
$c->log->error("Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
$c->response->status(HTTP_FORBIDDEN);
$c->response->body(JSON::to_json($res));
$self->error($c, HTTP_FORBIDDEN, 'Forbidden',
"Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
return;
}
my $ip = $redis->hget("password_reset:admin::$uuid_string", "ip");
if ($ip && $ip ne $c->req->address) {
$res = {success => 0};
$c->log->error("Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
$c->response->status(HTTP_FORBIDDEN);
$c->response->body(JSON::to_json($res));
$self->error($c, HTTP_FORBIDDEN, 'Forbidden',
"Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
return;
}
$c->log->debug("Updating administrator password.");
@ -130,9 +126,8 @@ sub POST :Allow {
my $subscriber = $rs->first ? $rs->first->voip_subscriber : undef;
unless($subscriber && $subscriber->provisioning_voip_subscriber) {
$res = {success => 0};
$c->log->error("Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
$c->response->status(HTTP_FORBIDDEN);
$c->response->body(JSON::to_json($res));
$self->error($c, HTTP_FORBIDDEN, 'Forbidden',
"Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
return;
}
$c->log->debug("Updating subscriber password.");

@ -146,8 +146,8 @@ sub POST :Allow {
}
my $model = $model_rs->first;
unless($model) {
$c->log->error("invalid device_id '$$resource{device_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Pbx device model does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Pbx device model does not exist",
"invalid device_id '$$resource{device_id}'");
last;
}
@ -158,8 +158,7 @@ sub POST :Allow {
try {
$item = $model->autoprov_configs->create($resource);
} catch($e) {
$c->log->error("failed to create pbxdeviceconfig: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create pbxdeviceconfig.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create pbxdeviceconfig.", $e);
last;
}

@ -147,8 +147,8 @@ sub POST :Allow {
}
my $model = $model_rs->first;
unless($model) {
$c->log->error("invalid device_id '$$resource{device_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Pbx device model does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Pbx device model does not exist",
"invalid device_id '$$resource{device_id}'");
last;
}
@ -163,8 +163,7 @@ sub POST :Allow {
);
}
} catch($e) {
$c->log->error("failed to create pbxdevicefirmware: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create pbxdevicefirmware.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create pbxdevicefirmware.", $e);
last;
}

@ -98,8 +98,8 @@ sub POST :Allow {
my ($self, $c) = @_;
if ($c->user->roles eq 'subscriberadmin') {
$c->log->error("role subscriberadmin cannot create pbxdeviceprofiles");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid role. Cannot create pbxdeviceprofile.");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid role. Cannot create pbxdeviceprofile.",
"role subscriberadmin cannot create pbxdeviceprofiles");
return;
}
@ -124,8 +124,9 @@ sub POST :Allow {
name => $resource->{name},
});
if($item) {
$c->log->error("Pbx device profile with name '$$resource{name}' already exists for config_id '$$resource{config_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Pbx device profile with this name already exists for this config");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY,
"Pbx device profile with this name already exists for this config",
"Pbx device profile with name '$$resource{name}' already exists for config_id '$$resource{config_id}'");
last;
}
my $config_rs = $c->model('DB')->resultset('autoprov_configs')->search({
@ -141,16 +142,15 @@ sub POST :Allow {
}
my $config = $config_rs->first;
unless($config) {
$c->log->error("Pbx device config with confg_id '$$resource{config_id}' does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Pbx device config does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Pbx device config does not exist",
"Pbx device config with confg_id '$$resource{config_id}' does not exist");
last;
}
try {
$item = $config->autoprov_profiles->create($resource);
} catch($e) {
$c->log->error("failed to create pbx device profile: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create pbx device profile.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create pbx device profile.", $e);
last;
}

@ -62,7 +62,6 @@ sub PATCH :Allow {
my ($self, $c, $id) = @_;
if ($c->user->roles eq 'subscriberadmin') {
$c->log->error("role subscriberadmin cannot edit pbxdeviceprofiles");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid role. Cannot edit pbxdeviceprofile.");
return;
}
@ -100,7 +99,6 @@ sub PUT :Allow {
my ($self, $c, $id) = @_;
if ($c->user->roles eq 'subscriberadmin') {
$c->log->error("role subscriberadmin cannot edit pbxdeviceprofiles");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid role. Cannot edit pbxdeviceprofile.");
return;
}

@ -281,8 +281,7 @@ sub POST :Allow {
$device->autoprov_field_device_lines->create($line);
}
} catch($e) {
$c->log->error("failed to create pbxdevice: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create pbxdevice.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create pbxdevice.", $e);
last;
};

@ -152,8 +152,8 @@ sub DELETE :Allow {
NGCP::Panel::Utils::DeviceBootstrap::dispatch($c, 'unregister', $device, $device->identifier);
$device->delete;
} catch($e) {
$c->log->error("Failed to delete pbx field device with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete pbx field device with id '$id'", $e);
last;
}
$guard->commit;

@ -12,6 +12,10 @@ use HTTP::Status qw(:constants);
use NGCP::Panel::Utils::Peering;
use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::PeeringGroups/;#Catalyst::Controller
__PACKAGE__->set_config({
own_transaction_control => { POST => 1 },
});
sub allowed_methods{
return [qw/GET POST OPTIONS HEAD/];
}
@ -81,55 +85,32 @@ sub GET :Allow {
return;
}
sub POST :Allow {
my ($self, $c) = @_;
sub create_item {
my ($self, $c, $resource, $form, $process_extras) = @_;
my $item;
my $guard = $c->model('DB')->txn_scope_guard;
{
my $resource = $self->get_valid_post_data(
c => $c,
media_type => 'application/json',
);
last unless $resource;
my $form = $self->get_form($c);
last unless $self->validate_form(
c => $c,
resource => $resource,
form => $form,
);
last unless $resource;
$resource = $self->process_form_resource($c, undef, undef, $resource, $form);
my $item;
try {
my $dup_item = $c->model('DB')->resultset('voip_peer_groups')->find({
name => $resource->{name},
});
if($dup_item) {
$c->log->error("peering group with name '$$resource{name}' already exists"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Peering group with this name already exists");
last;
}
try {
$item = $c->model('DB')->resultset('voip_peer_groups')->create($resource);
} catch($e){
$c->log->error("failed to create peering group: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering group.");
last;
if ($dup_item) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Peering group with this name already exists",
"peering group with name '$$resource{name}' already exists");
return;
}
$guard->commit;
$item = $c->model('DB')->resultset('voip_peer_groups')->create($resource);
NGCP::Panel::Utils::Peering::_sip_lcr_reload(c => $c);
$guard->commit;
$c->response->status(HTTP_CREATED);
$c->response->header(Location => sprintf('/%s%d', $c->request->path, $item->id));
$c->response->body(q());
} catch($e) {
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering group.", $e);
return;
}
return;
NGCP::Panel::Utils::Peering::_sip_lcr_reload(c => $c);
return $item;
}
1;

@ -129,7 +129,6 @@ sub POST :Allow {
form => $form,
);
unless($c->model('DB')->resultset('voip_peer_groups')->find($resource->{group_id})) {
$c->log->error("peering group $$resource{group_id} does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "peering group $$resource{group_id} does not exist");
last;
}
@ -143,7 +142,6 @@ sub POST :Allow {
priority => $resource->{priority},
});
if($dup_item) {
$c->log->error("peering rule already exists"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "peering rule already exists");
last;
}
@ -154,7 +152,6 @@ sub POST :Allow {
{}
);
if($prio_rs->count) {
$c->log->error("peering rule priority $$resource{priority} already exists for this group");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "peering rule priority $$resource{priority} already exists for this group");
last;
}
@ -165,8 +162,7 @@ sub POST :Allow {
has_inbound_rules => 1
});
} catch($e) {
$c->log->error("failed to create peering rule: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering rule.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering rule.", $e);
last;
}

@ -141,7 +141,6 @@ sub POST :Allow {
});
if ($dup_item) {
$c->log->error("peering rule already exists");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "peering rule already exists");
return;
}
@ -149,8 +148,7 @@ sub POST :Allow {
try {
$item = $c->model('DB')->resultset('voip_peer_rules')->create($resource);
} catch($e) {
$c->log->error("failed to create peering rule: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering rule.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering rule.", $e);
last;
}

@ -142,8 +142,8 @@ sub POST :Allow {
name => $resource->{name},
});
if($dup_item) {
$c->log->error("peering server with name '$$resource{name}' already exists"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "peering server with this name already exists");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "peering server with this name already exists",
"peering server with name '$$resource{name}' already exists");
return;
}
@ -153,8 +153,7 @@ sub POST :Allow {
NGCP::Panel::Utils::Peering::_sip_dispatcher_reload(c => $c);
}
} catch($e) {
$c->log->error("failed to create peering server: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering server.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering server.", $e);
last;
}
@ -167,8 +166,8 @@ sub POST :Allow {
NGCP::Panel::Utils::Peering::_sip_dispatcher_reload(c => $c);
}
} catch($e) {
$c->log->error("failed to reload kamailio cache: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering server.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering server.",
"failed to reload kamailio cache", $e);
last;
}

@ -94,8 +94,8 @@ sub PATCH :Allow {
}
NGCP::Panel::Utils::Peering::_sip_dispatcher_reload(c => $c);
} catch($e) {
$c->log->error("failed to reload kamailio cache: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering server.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering server.",
"failed to reload kamailio cache", $e);
last;
}
@ -152,8 +152,8 @@ sub PUT :Allow {
}
NGCP::Panel::Utils::Peering::_sip_dispatcher_reload(c => $c);
} catch($e) {
$c->log->error("failed to reload kamailio cache: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering server.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering server.",
"failed to reload kamailio cache", $e);
last;
}
@ -198,8 +198,8 @@ sub DELETE :Allow {
NGCP::Panel::Utils::Peering::_sip_dispatcher_reload(c => $c);
}
} catch($e) {
$c->log->error("failed to reload kamailio cache: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering server.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create peering server.",
"failed to reload kamailio cache", $e);
last;
}

@ -170,7 +170,6 @@ sub POST :Allow {
mappings_to_create => $mappings_to_create,
err_code => sub {
my ($err) = @_;
#$c->log->error($err);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $err);
});
@ -181,8 +180,7 @@ sub POST :Allow {
$profile_package->profiles->create($mapping);
}
} catch($e) {
$c->log->error("failed to create profile package: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create profile package.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create profile package.", $e);
last;
}

@ -372,11 +372,7 @@ sub post {
$c->response->header(Location => sprintf('%s%d', NGCP::Panel::Role::API::Subscribers::dispatch_path(), $context->{subscriber}->{id}));
} catch($e) {
NGCP::Panel::Utils::ProvisioningTemplates::provision_cleanup($c, $context);
$c->log->error(sprintf("Provisioning template '%s' failed: %s",
$id,
$e,
));
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, $e);
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Provisioning template '$id' failed", $e);
return;
}
} else {
@ -387,15 +383,15 @@ sub post {
purge => $purge,
);
if (scalar @$errors) {
$c->log->error(sprintf('CSV file (%d lines) processed, %d error(s).', $linecount, scalar @$errors));
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
sprintf('CSV file (%d lines) processed, %d error(s).', $linecount, scalar @$errors));
return;
} else {
$c->log->debug(sprintf('CSV file (%d lines) processed, %d error(s).', $linecount, 0));
}
} catch($e) {
$c->log->error("failed to process CSV file: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"failed to process CSV file", $e);
return;
}
}

@ -140,8 +140,8 @@ sub POST :Allow {
pref_list => ['reminder'],
);
unless ($allowed_prefs->{reminder}) {
$c->log->error("Not permitted to create reminder for this subscriber via subscriber profile");
$self->error($c, HTTP_FORBIDDEN, "Not permitted to create reminder");
$self->error($c, HTTP_FORBIDDEN, "Not permitted to create reminder",
"Not permitted to create reminder for this subscriber via subscriber profile");
return;
}
@ -150,16 +150,15 @@ sub POST :Allow {
subscriber_id => $resource->{subscriber_id},
});
if($item) {
$c->log->error("reminder already exists for subscriber_id '$$resource{subscriber_id}'"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Reminder already exists for this subscriber");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Reminder already exists for this subscriber",
"reminder already exists for subscriber_id '$$resource{subscriber_id}'");
last;
}
try {
$item = $c->model('DB')->resultset('voip_reminder')->create($resource);
} catch($e) {
$c->log->error("failed to create reminder: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create reminder.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create reminder.", $e);
last;
}

@ -163,8 +163,7 @@ sub POST :Allow {
});
NGCP::Panel::Utils::Reseller::create_email_templates( c => $c, reseller => $reseller );
} catch($e) {
$c->log->error("failed to create reseller: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create reseller.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create reseller.", $e);
last;
}

@ -45,21 +45,19 @@ sub create_item {
my $schema = $c->model('DB');
my $item;
my $guard = $schema->txn_scope_guard;
{
try {
my $rewriterules = delete $resource->{rewriterules};
try {
$item = $schema->resultset('voip_rewrite_rule_sets')->create($resource);
} catch($e) {
$c->log->error("failed to create rewriteruleset: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create rewriteruleset.");
return;
}
$item = $schema->resultset('voip_rewrite_rule_sets')->create($resource);
if ($rewriterules) {
$self->update_rewriterules( $c, $item, $form, $rewriterules );
}
$guard->commit;
NGCP::Panel::Utils::Rewrite::sip_dialplan_reload($c);
} catch($e) {
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create rewriteruleset.", $e);
return;
}
$guard->commit;
NGCP::Panel::Utils::Rewrite::sip_dialplan_reload($c);
return $item;
}

@ -24,8 +24,8 @@ sub delete_item {
$item->voip_rewrite_rules->delete;
$item->delete;
} catch($e) {
$c->log->error("Failed to delete rewriteruleset with id '".$item->id."': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete rewriteruleset with id '".$item->id."'", $e);
last;
}
$guard->commit;
@ -48,8 +48,8 @@ sub update_item_model {
$self->update_rewriterules( $c, $item, $form, $rewriterules );
}
} catch($e) {
$c->log->error("Failed to update rewriterule with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to update rewriterule with id '$id'", $e);
die;
}
$guard->commit;

@ -80,8 +80,7 @@ sub create_item {
}
$item = $schema->resultset('voip_rewrite_rules')->create($resource);
} catch($e) {
$c->log->error("failed to create rewriterule: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create rewriterule.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create rewriterule.", $e);
return;
}
$guard->commit;

@ -21,8 +21,8 @@ sub delete_item {
try {
$item->delete;
} catch($e) {
$c->log->error("Failed to delete rewriterule with id '".$item->id."': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to delete rewriterule with id '".$item->id."'", $e);
return;
}
$guard->commit;
@ -41,8 +41,8 @@ sub update_item_model {
try {
$item->update($resource);
} catch($e) {
$c->log->error("Failed to update rewriterule with id '$id': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to update rewriterule with id '$id'", $e);
die;
}
$guard->commit;

@ -167,12 +167,11 @@ sub create_item {
die $session->{reason}."\n";
}
} catch($e) {
$c->log->error($e);
if ($session && $session->{reason} eq 'insufficient credit') {
$self->error($c, HTTP_PAYMENT_REQUIRED, "Not enough credit to send the sms");
$self->error($c, HTTP_PAYMENT_REQUIRED, "Not enough credit to send the sms", $e);
} else {
$self->error($c, HTTP_INTERNAL_SERVER_ERROR,
"An internal error has occurred when sending the sms, please contact the platform administrator or try again later");
"An internal error has occurred when sending the sms, please contact the platform administrator or try again later", $e);
}
}

@ -78,8 +78,7 @@ sub create_item {
);
}
} catch($e) {
$c->log->error("failed to create soundset: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create soundset.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create soundset.", $e);
return;
}

@ -66,8 +66,8 @@ sub delete_item {
if ($c->user->roles eq 'subscriberadmin' &&
(!$item->contract_id || $item->contract_id != $c->user->account_id)) {
$c->log->error("Cannot modify read-only sound set that does not belong to this subscriberadmin");
$self->error($c, HTTP_FORBIDDEN, "Cannot modify read-only sound set");
$self->error($c, HTTP_FORBIDDEN, "Cannot modify read-only sound set",
"does not belong to this subscriberadmin");
return;
}

@ -130,8 +130,8 @@ sub POST :Allow {
}
my $sub = $sub_rs->first;
unless($sub && $sub->provisioning_voip_subscriber) {
$c->log->error("invalid subscriber_id '$$resource{subscriber_id}'"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Subscriber does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Subscriber does not exist",
"invalid subscriber_id '$$resource{subscriber_id}'");
last;
}
@ -144,8 +144,7 @@ sub POST :Allow {
try {
$item = $c->model('DB')->resultset('voip_subscriber_location_mappings')->create($resource);
} catch($e) {
$c->log->error("failed to create location mapping: " . $c->qs($e)); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create location mapping.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create location mapping.", $c->qs($e));
last;
}

@ -110,8 +110,8 @@ sub POST :Allow {
}
if($c->user->roles eq "reseller" && !$c->config->{profile_sets}->{reseller_edit}) {
$c->log->error("profile set creation by reseller forbidden via config");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile set creation forbidden for resellers.");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile set creation forbidden for resellers.",
"profile set creation by reseller forbidden via config");
return;
}
@ -141,16 +141,16 @@ sub POST :Allow {
name => $resource->{name},
});
if($item) {
$c->log->error("subscriber profile set with name '$$resource{name}' already exists for reseller_id '$$resource{reseller_id}'"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Subscriber profile set with this name already exists for this reseller");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY,
"Subscriber profile set with this name already exists for this reseller",
"subscriber profile set with name '$$resource{name}' already exists for reseller_id '$$resource{reseller_id}'");
last;
}
try {
$item = $c->model('DB')->resultset('voip_subscriber_profile_sets')->create($resource);
} catch($e) {
$c->log->error("failed to create subscriber profile set: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create subscriber profile set.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create subscriber profile set.", $e);
last;
}

@ -72,8 +72,8 @@ sub PATCH :Allow {
}
if($c->user->roles eq "reseller" && !$c->config->{profile_sets}->{reseller_edit}) {
$c->log->error("profile set modification by reseller forbidden via config");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile set modification forbidden for resellers.");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile set modification forbidden for resellers.",
"profile set modification by reseller forbidden via config");
return;
}
@ -118,8 +118,8 @@ sub PUT :Allow {
}
if($c->user->roles eq "reseller" && !$c->config->{profile_sets}->{reseller_edit}) {
$c->log->error("profile set modification by reseller forbidden via config");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile set modification forbidden for resellers.");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile set modification forbidden for resellers.",
"profile set modification by reseller forbidden via config");
return;
}
@ -160,8 +160,8 @@ sub DELETE :Allow {
}
if($c->user->roles eq "reseller" && !$c->config->{profile_sets}->{reseller_edit}) {
$c->log->error("profile set deletion by reseller forbidden via config");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile set deletion forbidden for resellers.");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile set deletion forbidden for resellers.",
"profile set deletion by reseller forbidden via config");
return;
}

@ -111,8 +111,8 @@ sub POST :Allow {
}
if($c->user->roles eq "reseller" && !$c->config->{profile_sets}->{reseller_edit}) {
$c->log->error("profile creation by reseller forbidden via config");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile creation forbidden for resellers.");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile creation forbidden for resellers.",
"profile creation by reseller forbidden via config");
return;
}
@ -146,8 +146,8 @@ sub POST :Allow {
}
$set = $set->find($resource->{set_id});
unless($set) {
$c->log->error("subscriber profile set with id '$$resource{set_id}' does not exist"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'profile_set_id', does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'profile_set_id', does not exist",
"subscriber profile set with id '$$resource{set_id}' does not exist");
last;
}
@ -156,8 +156,9 @@ sub POST :Allow {
name => $resource->{name},
});
if($item) {
$c->log->error("subscriber profile with name '$$resource{name}' already exists for profile_set_id '$$resource{set_id}'"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Subscriber profile with this name already exists for this profile set");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY,
"Subscriber profile with this name already exists for this profile set",
"subscriber profile with name '$$resource{name}' already exists for profile_set_id '$$resource{set_id}'");
last;
}
if($resource->{set_default}) {
@ -188,8 +189,7 @@ sub POST :Allow {
$item->profile_attributes->create({ attribute_id => $meta->id });
}
} catch($e) {
$c->log->error("failed to create subscriber profile: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create subscriber profile.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create subscriber profile.", $e);
last;
}

@ -148,8 +148,8 @@ sub DELETE :Allow {
}
if($c->user->roles eq "reseller" && !$c->config->{profile_sets}->{reseller_edit}) {
$c->log->error("profile deletion by reseller forbidden via config");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile deletion forbidden for resellers.");
$self->error($c, HTTP_FORBIDDEN, "Subscriber profile deletion forbidden for resellers.",
"profile deletion by reseller forbidden via config");
return;
}

@ -129,42 +129,16 @@ sub GET :Allow {
return;
}
sub POST :Allow {
my ($self, $c) = @_;
{
my ($item, $resource);
$resource = $self->get_valid_post_data(
c => $c,
media_type => 'application/json',
);
last unless $resource;
my $form = $self->get_form($c);
my $create = 1;
sub create_item {
my ($self, $c, $resource, $form, $process_extras) = @_;
my ($guard, $txn_ok) = ($c->model('DB')->txn_scope_guard, 0);
{
last unless $self->update_item($c, "new", undef, $resource, $form, $create);
my $item;
$guard->commit;
$txn_ok = 1;
}
last unless $txn_ok;
my $create = 1;
$item = $self->fetch_item($c, $resource, $form, $item);
return unless $self->update_item($c, "new", undef, $resource, $form, $create);
if ($item) {
$c->response->status(HTTP_CREATED);
$c->response->header(Location => sprintf('/%s%s', $c->request->path, $item->id));
$c->response->body(q());
} else {
$c->response->status(HTTP_CREATED);
$c->response->body(q());
}
}
return;
return $self->fetch_item($c, $resource, $form, $item);
}
1;

@ -445,17 +445,17 @@ sub POST :Allow {
$log_error = "failed to create subscriber, webusername-domain combination " . $c->qs($1) . " already exists";
@http_errors = ("Webusername-Domain combination '" . $1 . "' already exists.", "Webusername-Domain combination already exists.");
}
$c->log->error($log_error); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $http_errors[0], $http_errors[1]);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $http_errors[0], $http_errors[1], $log_error);
last;
} catch($e) {
if (ref $error_info->{extended} eq 'HASH' && $error_info->{extended}->{response_code}) {
$c->log->error($error_info->{extended}->{error}); # TODO: user, message, trace, ...
$self->error($c, $error_info->{extended}->{response_code}, $error_info->{extended}->{description});
$self->error($c,
$error_info->{extended}->{response_code},
$error_info->{extended}->{description},
$error_info->{extended}->{error});
last;
} else {
$c->log->error("failed to create subscriber: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create subscriber: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create subscriber", $e);
last;
}
}

@ -121,8 +121,7 @@ sub POST :Allow {
try {
$contact = $c->model('DB')->resultset('contacts')->create($resource);
} catch($e) {
$c->log->error("failed to create contact: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create contact.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create contact.", $e);
last;
}

@ -165,8 +165,8 @@ sub DELETE :Allow {
});
$contact->discard_changes();
} catch($e) {
$c->log->error("Failed to terminate contact id '".$contact->id."': $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
"Failed to terminate contact id '".$contact->id."'", $e);
last;
};
my $form = $self->get_form($c);

@ -55,8 +55,7 @@ sub create_item {
resource => $resource,
);
} catch($e) {
$c->log->error("failed to create timeset: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create timeset.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create timeset.", $e);
return;
}

@ -58,8 +58,8 @@ sub POST :Allow {
my $guard = $c->model('DB')->txn_scope_guard;
{
unless($c->user->billing_data) {
$c->log->error("user does not have billing data rights");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to create voucher");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to create voucher",
"user does not have billing data rights");
last;
}
$resource = $self->get_valid_post_data(
@ -84,9 +84,8 @@ sub POST :Allow {
resource => $resource,
entities => $entities,
err_code => sub {
my ($err) = @_;
#$c->log->error($err);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $err);
my ($err) = @_;
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $err);
},
);
@ -102,8 +101,7 @@ sub POST :Allow {
subscriber => $entities->{subscriber},
);
} catch($e) {
$c->log->error("failed to perform cash topup: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to perform cash topup.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to perform cash topup.", $e);
last;
}
@ -127,7 +125,7 @@ sub POST :Allow {
is_success => $success
);
} catch($e) {
$c->log->error("failed to create topup log record: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create topup log record.", $e);
last;
}
$guard->commit;

@ -58,8 +58,8 @@ sub POST :Allow {
my $guard = $c->model('DB')->txn_scope_guard;
{
unless($c->user->billing_data) {
$c->log->error("user does not have billing data rights");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to create voucher");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to create voucher",
"user does not have billing data rights");
last;
}
@ -83,9 +83,8 @@ sub POST :Allow {
resource => $resource,
entities => $entities,
err_code => sub {
my ($err) = @_;
#$c->log->error($err);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $err);
my ($err) = @_;
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $err);
},
);
@ -104,8 +103,7 @@ sub POST :Allow {
used_at => $now,
});
} catch($e) {
$c->log->error("failed to create voucher topup: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create voucher topup.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create voucher topup.", $e);
last;
}
@ -129,7 +127,7 @@ sub POST :Allow {
is_success => $success
);
} catch($e) {
$c->log->error("failed to create topup log record: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create voucher topup.", $e);
last;
}
$guard->commit;

@ -129,8 +129,8 @@ sub POST :Allow {
}
my $sub = $sub_rs->first;
unless($sub && $sub->provisioning_voip_subscriber) {
$c->log->error("invalid subscriber_id '$$resource{subscriber_id}'"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Subscriber does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Subscriber does not exist",
"invalid subscriber_id '$$resource{subscriber_id}'");
last;
}
@ -140,8 +140,7 @@ sub POST :Allow {
try {
$item = $c->model('DB')->resultset('voip_trusted_sources')->create($resource);
} catch($e) {
$c->log->error("failed to create trusted source: " . $c->qs($e)); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create trusted source.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create trusted source.", $c->qs($e));
last;
}
@ -159,8 +158,7 @@ sub POST :Allow {
die "XMLRPC failed";
}
} catch($e) {
$c->log->error("failed to reload kamailio: $e. Trusted source created");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to reload kamailio. Trusted source was created");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to reload kamailio. Trusted source was created", $e);
$c->response->header(Location => sprintf('/%s%d', $c->request->path, $item->id));
last;
}

@ -98,8 +98,7 @@ sub PATCH :Allow {
die "XMLRPC failed";
}
} catch($e) {
$c->log->error("failed to reload kamailio: $e. Trusted source modified.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to reload kamailio. Trusted source was modified.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to reload kamailio. Trusted source was modified.", $e);
last;
}
@ -152,8 +151,7 @@ sub PUT :Allow {
die "XMLRPC failed";
}
} catch($e) {
$c->log->error("failed to reload kamailio: $e. Trusted source modified.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to reload kamailio. Trusted source was modified.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to reload kamailio. Trusted source was modified.", $e);
# TODO: do we still want to return the modified item here?
last;
}
@ -199,8 +197,7 @@ sub DELETE :Allow {
die "XMLRPC failed";
}
} catch($e) {
$c->log->error("failed to reload kamailio: $e. Trusted source deleted.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to reload kamailio. Trusted source was deleted.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to reload kamailio. Trusted source was deleted.", $e);
last;
}

@ -129,8 +129,8 @@ sub POST :Allow {
my $sub = $sub_rs->first;
unless($sub && $sub->provisioning_voip_subscriber) {
my $debug_sid = $resource->{subscriber_id} // '(undef)';
$c->log->error("invalid subscriber_id '$debug_sid'"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Subscriber does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Subscriber does not exist",
"invalid subscriber_id '$debug_sid'");
last;
}
@ -149,8 +149,7 @@ sub POST :Allow {
prov_subscriber => $sub->provisioning_voip_subscriber);
$upnr_pref_rs->create({ value => $item->id });
} catch($e) {
$c->log->error("failed to create UPN rewrite set: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create UPN rewrite set.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create UPN rewrite set.", $e);
last;
}

@ -111,8 +111,8 @@ sub POST :Allow {
my ($self, $c) = @_;
unless($c->user->billing_data) {
$c->log->error("user does not have billing data rights");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to create voucher");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to create voucher",
"user does not have billing data rights");
return;
}
@ -142,8 +142,8 @@ sub POST :Allow {
code => $code,
});
if($item) {
$c->log->error("voucher with code '$$resource{code}' already exists for reseller_id '$$resource{reseller_id}'"); # TODO: user, message, trace, ...
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Voucher with this code already exists for this reseller");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Voucher with this code already exists for this reseller",
"voucher with code '$$resource{code}' already exists for reseller_id '$$resource{reseller_id}'");
last;
}
$resource->{code} = $code;
@ -153,8 +153,7 @@ sub POST :Allow {
try {
$item = $c->model('DB')->resultset('vouchers')->create($resource);
} catch($e) {
$c->log->error("failed to create voucher: $e"); # TODO: user, message, trace, ...
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create voucher.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create voucher.", $e);
last;
}

@ -58,8 +58,8 @@ sub GET :Allow {
sub PATCH :Allow {
my ($self, $c, $id) = @_;
unless($c->user->billing_data) {
$c->log->error("user does not have billing data rights");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to edit voucher");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to edit voucher",
"user does not have billing data rights");
return;
}
my $guard = $c->model('DB')->txn_scope_guard;
@ -94,8 +94,8 @@ sub PATCH :Allow {
sub PUT :Allow {
my ($self, $c, $id) = @_;
unless($c->user->billing_data) {
$c->log->error("user does not have billing data rights");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to edit voucher");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to edit voucher",
"user does not have billing data rights");
return;
}
my $guard = $c->model('DB')->txn_scope_guard;
@ -127,8 +127,8 @@ sub PUT :Allow {
sub DELETE :Allow {
my ($self, $c, $id) = @_;
unless($c->user->billing_data) {
$c->log->error("user does not have billing data rights");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to delete voucher");
$self->error($c, HTTP_FORBIDDEN, "Insufficient rights to delete voucher",
"user does not have billing data rights");
return;
}
my $guard = $c->model('DB')->txn_scope_guard;

@ -348,15 +348,18 @@ sub validate_fields {
}
sub error {
my ($self, $c, $code, $message, $insensitive_message) = @_;
my ($self, $c, $code, $message, @errors) = @_;
my $msg = $insensitive_message // $message;
$c->log->error("error $code - $msg"); # TODO: user, trace etc
# code -> returned as HTTP code in the reply
# message -> returned as HTTP message in the reply
# errors -> contain errors for internal logging, last element often contains a DBIx exception
$c->error(['', @errors]);
$c->response->content_type('application/json');
$c->response->status($code);
$c->response->body(JSON::to_json({ code => $code, message => $message })."\n");
$c->stash(api_error_message => $message);
return;
}
@ -1057,14 +1060,15 @@ sub log_response {
$c->response->content_type('')
if $c->response->content_type =~ qr'text/html'; # stupid RenderView getting in the way
my $rc = '';
if (@{ $c->error }) {
my $msg = join ', ', @{ $c->error };
$rc = NGCP::Panel::Utils::Message::error(
c => $c,
type => 'api_response',
log => $msg,
);
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error");
if ($c->has_errors) {
my $msg = join ', ', splice @{$c->error}, 1;
if ($msg) {
$rc = NGCP::Panel::Utils::Message::error(
c => $c,
type => 'api_response',
log => $msg,
);
}
$c->clear_errors;
}
my ($response_body, $params_data) = $self->filter_log_response(
@ -1641,8 +1645,8 @@ sub validate_request {
#------ /dummy & default accessors methods
sub check_transaction_control{
my ($self, $c, $action, $step, %params) = @_;
sub check_transaction_control {
my ($self, $c, $action, $step) = @_;
my $res = 1;
my $transaction_config = $self->get_config('own_transaction_control');
if (!$transaction_config) {
@ -1658,13 +1662,12 @@ sub check_transaction_control{
return $res;
}
sub get_transaction_control{
my $self = shift;
my($c, $action, $step, %params) = @_;
my $schema = $params{schema} // $c->model('DB');
$action //= uc $c->request->method;
$step //= 'init';
if($self->check_transaction_control($c, $action, $step, %params)){
sub start_transaction {
my ($self, $c) = @_;
my $schema = $c->model('DB');
my $action = uc $c->request->method;
my $step = 'start';
if ($self->check_transaction_control($c, $action, $step)) {
#todo: put it into class variables?
my $til_config = $self->get_config('set_transaction_isolation');
if ($til_config) {
@ -1675,22 +1678,18 @@ sub get_transaction_control{
: 'READ COMMITTED';
$c->model('DB')->set_transaction_isolation($transaction_isolation_level);
}
$c->stash->{transaction_quard} = $schema->txn_scope_guard;
return $c->stash->{transaction_quard};
return $schema->txn_scope_guard;
}
return;
}
sub complete_transaction{
my $self = shift;
my($c, $action, $step, %params) = @_;
my $schema = $params{schema} // $c->model('DB');
my $guard = $params{guard} // $c->stash->{transaction_quard};
$action //= uc $c->request->method;
$step //= 'commit';
if($self->check_transaction_control($c, $action, $step, %params)){
sub commit_transaction {
my ($self, $c, $guard) = @_;
my $schema = $c->model('DB');
my $action = uc $c->request->method;
my $step = 'commit';
if ($self->check_transaction_control($c, $action, $step)) {
$guard->commit;
$c->stash->{transaction_quard} = undef;
}
return;
}
@ -2011,5 +2010,27 @@ sub check_wildcard_search {
}
sub check_deadlock {
my ($self, $c, $error) = @_;
my $max_attempts = 2;
return 0 unless $error;
#my $lock_retry = $error =~ /Lock wait timeout exceeded; try restarting transaction/;
my $deadlock_retry = $error =~ /Deadlock found when trying to get lock; try restarting transaction/;
return 0 unless $deadlock_retry;
my $attempt = $c->stash->{deadlock_retry_attempt} //= 1;
return 0 if $attempt > $max_attempts;
NGCP::Panel::Utils::Message::info(
c => $c,
type => 'api_retry',
log => "deadlock detected, retry transaction attempt=$attempt/$max_attempts",
);
$c->stash->{deadlock_retry_attempt} = $attempt+1;
return 1;
}
1;
# vim: set tabstop=4 expandtab:

@ -131,13 +131,13 @@ sub check_duplicate{
});
}
if ($existing_item && (!$item || $item->id != $existing_item->id)) {
$c->log->error("admin with login '$$resource{login}' already exists");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Admin with this login already exists");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Admin with this login already exists",
"admin with login '$$resource{login}' already exists");
return;
}
elsif ($existing_email && (!$item || $item->id != $existing_email->id)) {
$c->log->error("admin with email '$$resource{email}' already exists");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Admin with this email already exists");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Admin with this email already exists",
"admin with email '$$resource{email}' already exists");
return;
}
return 1;

@ -126,8 +126,7 @@ sub update_item {
});
}
} catch($e) {
$c->log->error("failed to update autoattendants: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update autoattendants.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update autoattendants.", $e);
return;
};

@ -136,8 +136,7 @@ sub update_item {
}
$item->discard_changes;
} catch($e) {
#$c->log->error("failed to create billingnetwork: $e");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create billingnetwork.");
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create billingnetwork.", $e);
return;
};
@ -155,7 +154,6 @@ sub prepare_blocks_resource {
}
return NGCP::Panel::Utils::BillingNetworks::set_blocks_from_to($resource->{blocks},sub {
my ($err) = @_;
#$c->log->error($err);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $err);
});
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save