From ded942b740fe67bc7bcfa5f26dafad4686143d64 Mon Sep 17 00:00:00 2001 From: Flaviu Mates Date: Tue, 27 Oct 2020 11:39:57 +0200 Subject: [PATCH] TT#96502 Introduce duplicate check for /api/cfsourcesets * Due to DB unique name constraint, enpoint was returning 500 on duplicate source sets * Proper 422 is now returned Change-Id: I883fbe71aa77364645467941206ea6b272523c03 --- lib/NGCP/Panel/Controller/API/CFSourceSets.pm | 96 +++++-------------- lib/NGCP/Panel/Role/API/CFSourceSets.pm | 75 +++++++++++++++ 2 files changed, 100 insertions(+), 71 deletions(-) diff --git a/lib/NGCP/Panel/Controller/API/CFSourceSets.pm b/lib/NGCP/Panel/Controller/API/CFSourceSets.pm index 06e87322f4..d62af18be5 100644 --- a/lib/NGCP/Panel/Controller/API/CFSourceSets.pm +++ b/lib/NGCP/Panel/Controller/API/CFSourceSets.pm @@ -116,86 +116,40 @@ sub GET :Allow { return; } -sub POST :Allow { - my ($self, $c) = @_; - - 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 $form = $self->get_form($c); - last unless $self->validate_form( - c => $c, - resource => $resource, - form => $form, - ); - - my $sset; - - if($c->user->roles eq "subscriberadmin" || $c->user->roles eq "subscriber") { - $resource->{subscriber_id} = $c->user->voip_subscriber->id; - } elsif(!defined $resource->{subscriber_id}) { - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Missing mandatory field 'subscriber_id'"); - last; - } +sub create_item { + my ($self, $c, $resource, $form, $process_extras) = @_; + my $schema = $c->model('DB'); + my $sset; + try { my $b_subscriber = $schema->resultset('voip_subscribers')->find({ - id => $resource->{subscriber_id}, - }); - unless($b_subscriber) { - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'subscriber_id'."); - last; - } + id => $resource->{subscriber_id}, + }); my $subscriber = $b_subscriber->provisioning_voip_subscriber; - unless($subscriber) { - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid subscriber."); - last; - } - if (! exists $resource->{sources} ) { - $resource->{sources} = []; - } - if (ref $resource->{sources} ne "ARRAY") { - $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid field 'sources'. Must be an array."); - last; - } - try { - my $domain = $subscriber->domain->domain // ''; - - $sset = $schema->resultset('voip_cf_source_sets')->create({ - name => $resource->{name}, - mode => $resource->{mode}, - is_regex => $resource->{is_regex} // 0, - subscriber_id => $subscriber->id, - }); - for my $s ( @{$resource->{sources}} ) { - $sset->create_related("voip_cf_sources", { - source => $s->{source}, - }); - } - } catch($e) { - $c->log->error("failed to create cfsourceset: $e"); - $self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to create cfsourceset."); - last; + $sset = $schema->resultset('voip_cf_source_sets')->create({ + name => $resource->{name}, + mode => $resource->{mode}, + is_regex => $resource->{is_regex} // 0, + subscriber_id => $subscriber->id, + }); + for my $s ( @{$resource->{sources}} ) { + $sset->create_related("voip_cf_sources", { + source => $s->{source}, + }); } - last unless $self->add_create_journal_item_hal($c,sub { my $self = shift; my ($c) = @_; my $_sset = $self->item_by_id($c, $sset->id); - return $self->hal_from_item($c, $_sset, "cfsourcesets"); }); - - $guard->commit; - - $c->response->status(HTTP_CREATED); - $c->response->header(Location => sprintf('/%s%d', $c->request->path, $sset->id)); - $c->response->body(q()); + 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."); + return; } - return; + + return $sset; } 1; diff --git a/lib/NGCP/Panel/Role/API/CFSourceSets.pm b/lib/NGCP/Panel/Role/API/CFSourceSets.pm index 00d8a06a2d..7a9384fb77 100644 --- a/lib/NGCP/Panel/Role/API/CFSourceSets.pm +++ b/lib/NGCP/Panel/Role/API/CFSourceSets.pm @@ -143,6 +143,10 @@ sub update_item { # last; #} + return unless $self->process_form_resource($c, $item, $old_resource, $resource, $form); + return unless $self->check_duplicate($c, $item, $old_resource, $resource, $form); + return unless $self->check_resource($c, $item, $old_resource, $resource, $form); + try { $item->update({ name => $resource->{name}, @@ -166,5 +170,76 @@ sub update_item { return $item; } +sub process_form_resource{ + my($self,$c, $item, $old_resource, $resource, $form, $process_extras) = @_; + + if($c->user->roles eq "subscriberadmin" || $c->user->roles eq "subscriber") { + $resource->{subscriber_id} = $c->user->voip_subscriber->id; + } elsif(!defined $resource->{subscriber_id}) { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Missing mandatory field 'subscriber_id'"); + return; + } + + return $resource; +} + +sub check_resource { + my($self, $c, $item, $old_resource, $resource, $form) = @_; + + my $schema = $c->model('DB'); + + my $b_subscriber = $schema->resultset('voip_subscribers')->find({ + id => $resource->{subscriber_id}, + }); + unless($b_subscriber) { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'subscriber_id'."); + return; + } + my $subscriber = $b_subscriber->provisioning_voip_subscriber; + unless($subscriber) { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid subscriber."); + return; + } + if (! exists $resource->{sources} ) { + $resource->{sources} = []; + } + if (ref $resource->{sources} ne "ARRAY") { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid field 'sources'. Must be an array."); + return; + } + + return 1; # all good +} + +sub check_duplicate { + my($self, $c, $item, $old_resource, $resource, $form, $process_extras) = @_; + + my $schema = $c->model('DB'); + + my $b_subscriber = $schema->resultset('voip_subscribers')->find({ + id => $resource->{subscriber_id}, + }); + unless($b_subscriber) { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid 'subscriber_id'."); + return; + } + my $subscriber = $b_subscriber->provisioning_voip_subscriber; + unless($subscriber) { + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid subscriber."); + return; + } + + my $existing_item = $schema->resultset('voip_cf_source_sets')->search({ + name => $resource->{name}, + subscriber_id => $subscriber->id + })->first; + if ($existing_item && (!$item || $item->id != $existing_item->id)) { + $c->log->error("source_set name '$$resource{name}' already exists"); + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "A Sourceset with this name already exists"); + return; + } + return 1; +} + 1; # vim: set tabstop=4 expandtab: