From a39484f629a8e853c1263132283d2964945fd1af Mon Sep 17 00:00:00 2001 From: Kirill Solomko Date: Fri, 5 Apr 2019 10:37:19 +0200 Subject: [PATCH] TT#45484 Add "force_delete" option to callrecordings Change-Id: I3f2a77548c07c686aee2aa771a8b84f4b91650af (cherry picked from commit cd7e2311bb04332370ad2205f39fb18dc1958df1) --- .../Panel/Controller/API/CallRecordings.pm | 6 +++ .../Controller/API/CallRecordingsItem.pm | 7 ++- lib/NGCP/Panel/Controller/Subscriber.pm | 54 ++++++++++++------- .../Form/Subscriber/CallRecordingDelete.pm | 46 ++++++++++++++++ lib/NGCP/Panel/Utils/Subscriber.pm | 10 +++- share/templates/subscriber/master.tt | 3 +- 6 files changed, 103 insertions(+), 23 deletions(-) create mode 100644 lib/NGCP/Panel/Form/Subscriber/CallRecordingDelete.pm diff --git a/lib/NGCP/Panel/Controller/API/CallRecordings.pm b/lib/NGCP/Panel/Controller/API/CallRecordings.pm index cf29f45566..a63b1586c4 100644 --- a/lib/NGCP/Panel/Controller/API/CallRecordings.pm +++ b/lib/NGCP/Panel/Controller/API/CallRecordings.pm @@ -55,6 +55,12 @@ sub query_params { param => 'tz', description => 'Format start_time according to the optional time zone provided here, e.g. Europe/Berlin.', }, + { + param => 'force_delete', + type => 'item_params', + apply_to => {'item' => {DELETE => 1}}, + description => 'Force callrecording info deletion from database despite callrecording files deletion errors.', + }, ]; } diff --git a/lib/NGCP/Panel/Controller/API/CallRecordingsItem.pm b/lib/NGCP/Panel/Controller/API/CallRecordingsItem.pm index ca4591388a..0982efe9c5 100644 --- a/lib/NGCP/Panel/Controller/API/CallRecordingsItem.pm +++ b/lib/NGCP/Panel/Controller/API/CallRecordingsItem.pm @@ -66,7 +66,12 @@ sub DELETE :Allow { last unless $self->resource_exists($c, callrecording => $item); try { - NGCP::Panel::Utils::Subscriber::delete_callrecording( c => $c, recording => $item ); + NGCP::Panel::Utils::Subscriber::delete_callrecording( + c => $c, + recording => $item, + #TODO: Now we don't use any way to document such parameters, need to be created + force_delete => $c->request->params->{force_delete}, + ); } catch($e) { $c->log->error("Failed to delete recording: $e"); $self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to delete recording."); diff --git a/lib/NGCP/Panel/Controller/Subscriber.pm b/lib/NGCP/Panel/Controller/Subscriber.pm index 68717ce79e..38ca7fe109 100644 --- a/lib/NGCP/Panel/Controller/Subscriber.pm +++ b/lib/NGCP/Panel/Controller/Subscriber.pm @@ -4150,26 +4150,42 @@ sub delete_recording :Chained('recording') :PathPart('delete') :Args(0) { $c->detach('/denied_page') if(($c->user->roles eq "admin" || $c->user->roles eq "reseller") && $c->user->read_only); - try { - my $recording = $c->stash->{recording}; - my $data = { $recording->get_inflated_columns }; - $c->model('DB')->schema->txn_do( sub { - NGCP::Panel::Utils::Subscriber::delete_callrecording( c => $c, recording => $recording ); - }); - NGCP::Panel::Utils::Message::info( - c => $c, - data => $data, - desc => $c->loc('Successfully deleted recording'), - ); - } catch($e) { - NGCP::Panel::Utils::Message::error( - c => $c, - error => $e, - desc => $c->loc('Failed to delete recording'), - ); + my $posted = ($c->request->method eq 'POST'); + my $form = NGCP::Panel::Form::get("NGCP::Panel::Form::Subscriber::CallRecordingDelete", $c); + $form->process( + posted => $posted, + params => $c->request->params, + ); + if($posted && $form->validated) { + try { + my $recording = $c->stash->{recording}; + my $data = { $recording->get_inflated_columns }; + $c->model('DB')->schema->txn_do( sub { + NGCP::Panel::Utils::Subscriber::delete_callrecording( + c => $c, + recording => $recording, + force_delete => $form->values->{force_delete} + ); + }); + NGCP::Panel::Utils::Message::info( + c => $c, + data => $data, + desc => $c->loc('Successfully deleted recording'), + ); + } catch($e) { + NGCP::Panel::Utils::Message::error( + c => $c, + error => $e, + desc => $c->loc('Failed to delete recording'), + ); + } + NGCP::Panel::Utils::Navigation::back_or($c, + $c->uri_for_action('/subscriber/details', [$c->req->captures->[0]])); } - NGCP::Panel::Utils::Navigation::back_or($c, - $c->uri_for_action('/subscriber/details', [$c->req->captures->[0]])); + + $c->stash(form => $form); + $c->stash(edit_flag => 1); + return; } diff --git a/lib/NGCP/Panel/Form/Subscriber/CallRecordingDelete.pm b/lib/NGCP/Panel/Form/Subscriber/CallRecordingDelete.pm new file mode 100644 index 0000000000..e8fc4a61a5 --- /dev/null +++ b/lib/NGCP/Panel/Form/Subscriber/CallRecordingDelete.pm @@ -0,0 +1,46 @@ +package NGCP::Panel::Form::Subscriber::CallRecordingDelete; +use Sipwise::Base; +use HTML::FormHandler::Moose; +extends 'HTML::FormHandler'; + +use HTML::FormHandler::Widget::Block::Bootstrap; + +has '+widget_wrapper' => ( default => 'Bootstrap' ); +has_field 'submitid' => ( type => 'Hidden' ); +sub build_render_list {[qw/submitid fields actions/]} +sub build_form_element_class { [qw/form-horizontal/] } + + +has_field 'force_delete' => ( + type => 'Boolean', + label => 'Force delete', + element_attr => { + rel => ['tooltip'], + title => ['Call recording infromation will be removed from database even in case of recording files absence or other impossibility to remove recording files.'] + }, + +); + +has_field 'save' => ( + type => 'Submit', + value => 'Delete', + element_class => [qw/btn btn-primary/], + do_label => 0, +); + +has_block 'fields' => ( + tag => 'div', + class => [qw/modal-body/], + render_list => [qw/force_delete/], +); + +has_block 'actions' => ( + tag => 'div', + class => [qw/modal-footer/], + render_list => [qw/save/], +); + +1; + +# vim: set tabstop=4 expandtab: + diff --git a/lib/NGCP/Panel/Utils/Subscriber.pm b/lib/NGCP/Panel/Utils/Subscriber.pm index bc9fc35f9a..2cf1c231a7 100644 --- a/lib/NGCP/Panel/Utils/Subscriber.pm +++ b/lib/NGCP/Panel/Utils/Subscriber.pm @@ -2017,11 +2017,17 @@ sub get_voicemail_content_type { sub delete_callrecording { my %params = @_; - my($recording) = @params{qw/recording/}; + my($recording, $force_delete) = @params{qw/recording force_delete/}; foreach my $stream($recording->recording_streams->all) { #if we met some error deleting file - we will fail and transaction will be rollbacked - unlink($stream->full_filename); + if (! -e $stream->full_filename) { + if ( !$force_delete ) { + die("Callrecording file ".$stream->full_filename." is absent"); + } + } elsif( !unlink($stream->full_filename) && !$force_delete ) { + die($!); + } } $recording->recording_streams->delete; $recording->recording_metakeys->delete; diff --git a/share/templates/subscriber/master.tt b/share/templates/subscriber/master.tt index e120adfaba..f898d0589e 100644 --- a/share/templates/subscriber/master.tt +++ b/share/templates/subscriber/master.tt @@ -245,7 +245,8 @@ function process_pbx_items(moveId,direction){ helper.dt_buttons = [ { name = c.loc('Call Details'), uri = "/subscriber/" _ subscriber.id _ "/calls?callid=' + encodeURIComponent(full.call_id_url) + '", class = 'btn-small btn-tertiary', icon = 'icon-search' }, { name = c.loc('Recorded Files'), uri = "details/recording/'+full.id+'/streams", class = 'btn-small btn-tertiary', icon = 'icon-play' }, - { name = c.loc('Delete'), uri = "details/recording/'+full.id+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' }, +#we will confirm deletion in the form + { name = c.loc('Delete recording'), uri = "details/recording/'+full.id+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' }, ]; ELSE; helper.dt_buttons = [