package NGCP::Panel::Controller::Sound; use NGCP::Panel::Utils::Generic qw(:all); use Sipwise::Base; use parent 'Catalyst::Controller'; use NGCP::Panel::Form; use File::Type; use NGCP::Panel::Utils::Sounds; use NGCP::Panel::Utils::Navigation; use NGCP::Panel::Utils::Sems; use List::Util qw(any); sub auto :Private { my ($self, $c) = @_; $c->log->debug(__PACKAGE__ . '::auto'); NGCP::Panel::Utils::Navigation::check_redirect_chain(c => $c); # only allow access to admin/reseller if cloudpbx is not enabled if((!$c->license('pbx') || !$c->config->{features}->{cloudpbx}) && $c->user->roles ne "admin" && $c->user->roles ne "reseller") { $c->detach('/denied_page'); } # even for pbx, it's only for admin/reseller/subscriberadmins if($c->user->roles eq "subscriber") { $c->detach('/denied_page'); } # and then again, it's only for subscriberadmins with pbxaccount product if($c->user->roles eq "subscriberadmin") { my $contract_id = $c->user->account_id; my $contract_select_rs = NGCP::Panel::Utils::Contract::get_contract_rs(schema => $c->model('DB'))->search_rs({ 'me.id' => $contract_id, }); my $product_id = $contract_select_rs->first ? $contract_select_rs->first->product->id : undef; unless($product_id) { NGCP::Panel::Utils::Message::error( c => $c, error => "No product for customer contract id $contract_id found", desc => $c->loc('No product for this customer contract found.'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/sound')); } my $product = $c->model('DB')->resultset('products')->search_rs({ id => $product_id, class => 'pbxaccount', })->first; unless($product) { $c->detach('/denied_page'); } $c->stash->{contract_rs} = $contract_select_rs; } return 1; } sub sets_list :Chained('/') :PathPart('sound') :CaptureArgs(0) { my ( $self, $c ) = @_; if($c->stash->{contract_rs}) { NGCP::Panel::Utils::Sounds::stash_soundset_list( c => $c, contract => $c->stash->{contract_rs}->first, ); } else { NGCP::Panel::Utils::Sounds::stash_soundset_list(c => $c); } $c->stash(template => 'sound/list.tt'); return; } sub parent_sets_list :Chained('/') :PathPart('sound_parent') :CaptureArgs(0) { my ( $self, $c ) = @_; if($c->stash->{contract_rs}) { NGCP::Panel::Utils::Sounds::stash_soundset_list( c => $c, fetch_parents => 1, contract => $c->stash->{contract_rs}->first, ); } else { NGCP::Panel::Utils::Sounds::stash_soundset_list( c => $c, fetch_parents => 1, ); } $c->stash(template => 'sound/list.tt'); return; } sub contract_sets_list :Chained('/') :PathPart('sound/contract') :CaptureArgs(1) { my ( $self, $c, $contract_id ) = @_; unless($contract_id && is_int($contract_id)) { NGCP::Panel::Utils::Message::error( c => $c, error => "Invalid contract id $contract_id found", desc => $c->loc('Invalid contract id found'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/sound')); } if($c->user->roles eq "subscriberadmin" && $c->user->account_id != $contract_id) { NGCP::Panel::Utils::Message::error( c => $c, error => "access violation, subscriberadmin ".$c->qs($c->user->uuid)." with contract id ".$c->user->account_id." tries to access foreign contract id $contract_id", desc => $c->loc('Invalid contract id found'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/sound')); } my $contract = $c->model('DB')->resultset('contracts')->find($contract_id); unless($contract) { NGCP::Panel::Utils::Message::error( c => $c, error => "Contract id $contract_id not found", desc => $c->loc('Invalid contract id detected'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/sound')); } NGCP::Panel::Utils::Sounds::stash_soundset_list( c => $c, contract => $contract, ); $c->stash(template => 'sound/list.tt'); return; } sub root :Chained('sets_list') :PathPart('') :Args(0) { my ($self, $c) = @_; return; } sub ajax :Chained('sets_list') :PathPart('ajax') :Args(0) { my ($self, $c) = @_; my $resultset = $c->stash->{sets_rs}; NGCP::Panel::Utils::Datatables::process($c, $resultset, $c->stash->{soundset_dt_columns}); $c->detach( $c->view("JSON") ); return; } sub parent_ajax :Chained('parent_sets_list') :PathPart('ajax') :Args(0) { my ($self, $c) = @_; my $resultset = $c->stash->{sets_rs}; my $parents_rs = $resultset->search({ 'me.id' => { '!=' => $c->session->{edit_sound_set_id} }, }); NGCP::Panel::Utils::Datatables::process($c, $parents_rs, $c->stash->{soundset_dt_columns}); $c->detach( $c->view("JSON") ); return; } sub contract_ajax :Chained('contract_sets_list') :PathPart('ajax') :Args(0) { my ($self, $c) = @_; my $resultset = $c->stash->{sets_rs}; NGCP::Panel::Utils::Datatables::process($c, $resultset, $c->stash->{soundset_dt_columns}); $c->detach( $c->view("JSON") ); return; } sub base :Chained('sets_list') :PathPart('') :CaptureArgs(1) { my ($self, $c, $set_id) = @_; unless($set_id && is_int($set_id)) { NGCP::Panel::Utils::Message::error( c => $c, log => 'Invalid sound set id detected', desc => $c->loc('Invalid sound set id detected'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/sound')); } delete $c->session->{edit_sound_set_id}; my $res = $c->stash->{sets_rs}->find($set_id); unless(defined($res)) { NGCP::Panel::Utils::Message::error( c => $c, log => 'Sound set does not exist', desc => $c->loc('Sound set does not exist'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/sound')); } $c->stash(set_result => $res); return; } sub edit :Chained('base') :PathPart('edit') { my ($self, $c) = @_; $self->check_subadmin_set_edit_access($c, $c->stash->{set_result}); my $posted = ($c->request->method eq 'POST'); my $form; my $params = { $c->stash->{set_result}->get_inflated_columns }; $params->{reseller}{id} = delete $params->{reseller_id}; $params->{contract}{id} = delete $params->{contract_id}; $params->{parent}{id} = delete $params->{parent_id}; $params = merge($params, $c->session->{created_objects}); $c->session->{edit_sound_set_id} = $c->stash->{set_result}->id; $self->check_subadmin_set_edit_access($c, $c->stash->{set_result}); if ($c->user->roles eq "admin") { $form = NGCP::Panel::Form::get("NGCP::Panel::Form::Sound::AdminSet", $c); } elsif ($c->user->roles eq "reseller") { $form = NGCP::Panel::Form::get("NGCP::Panel::Form::Sound::ResellerSet", $c); } else { $form = NGCP::Panel::Form::get("NGCP::Panel::Form::Sound::CustomerSet", $c); } unless (($c->license('pbx') && $c->config->{features}->{cloudpbx}) || $params->{contract}{id} ) { my $form_render_list = $form->block('fields')->render_list; $form->block('fields')->render_list([ grep {$_ !~ m/^contract(_default)?/} @{ $form_render_list } ]); } $form->process( posted => $posted, params => $c->request->params, item => $params, ); NGCP::Panel::Utils::Navigation::check_form_buttons( c => $c, form => $form, fields => { 'reseller.create' => $c->uri_for('/reseller/create'), }, back_uri => $c->req->uri, ); if ($posted && $form->validated) { my $parent_loop_err; try { my $own_id = $c->stash->{set_result}->id; my $old_parent_id = $c->stash->{set_result}->parent_id; my $parent_id = $form->values->{parent_id} = $form->values->{parent}{id} // undef; if ($c->user->roles eq "admin") { $form->values->{reseller_id} = $form->values->{reseller}{id}; $form->values->{contract_id} = $form->values->{contract}{id} // undef; if (defined $form->values->{contract_id}) { $form->values->{contract_default} //= 0; } else { $form->values->{contract_default} = 0; } } elsif ($c->user->roles eq "reseller") { if(defined $c->stash->{set_result}->contract_id) { $form->values->{contract_default} //= 0; } else { $form->values->{contract_default} = 0; } } else { $form->values->{contract_default} //= 0; } delete $form->values->{reseller}; delete $form->values->{contract}; delete $form->values->{parent}; if (NGCP::Panel::Utils::Sounds::check_parent_chain_for_loop( $c, $own_id, $parent_id) ) { $parent_loop_err = $c->loc("one of the parent sound sets refers to this one as a parent"); die $parent_loop_err; } if ($c->user->roles eq 'subscriberadmin' && $c->stash->{set_result}->contract_id != $c->user->account_id) { die "an attempt to edit a sound set that does not belong to the subscriberadmin"; } $c->model('DB')->set_transaction_isolation('READ COMMITTED'); $c->model('DB')->txn_do(sub { if ($c->stash->{set_result}->expose_to_customer == 1 && $form->values->{expose_to_customer} == 0) { # remove this sound set from all parents/prefs on subscriberadmin NGCP::Panel::Utils::Sounds::revoke_exposed_sound_set($c, $own_id); } # if contract default is set, clear old ones first if ($c->stash->{set_result}->contract_id && $form->values->{contract_default} == 1) { $c->stash->{sets_rs}->search({ reseller_id => $c->stash->{set_result}->reseller_id, contract_id => $c->stash->{set_result}->contract_id, contract_default => 1, })->update_all({ contract_default => 0 }); } $c->stash->{set_result}->update($form->values); if ($c->stash->{set_result}->contract && $c->stash->{set_result}->contract_default == 1) { NGCP::Panel::Utils::Sounds::contract_sound_set_propagate( $c, $c->stash->{set_result}->contract, $c->stash->{set_result}->id); } # invalidate cache of this sound set if parent is changed if ((!$old_parent_id && $parent_id) || ($old_parent_id && !$parent_id) || ($old_parent_id && $parent_id && $old_parent_id != $parent_id)) { NGCP::Panel::Utils::Sems::clear_audio_cache($c, $own_id); } }); delete $c->session->{created_objects}->{reseller}; delete $c->session->{created_objects}->{contract}; NGCP::Panel::Utils::Message::info( c => $c, desc => $c->loc('Sound set successfully updated'), ); } catch ($e) { NGCP::Panel::Utils::Message::error( c => $c, error => $e, desc => $c->loc('Failed to update sound set' . ($parent_loop_err ? " ($parent_loop_err)" : '') ), ); }; NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/sound')); } $c->stash( form => $form, edit_flag => 1, ); return; } sub delete_sound :Chained('base') :PathPart('delete') { my ($self, $c) = @_; $self->check_subadmin_set_edit_access($c, $c->stash->{set_result}); try { my $schema = $c->model('DB'); $schema->set_transaction_isolation('READ COMMITTED'); $schema->txn_do(sub { my $own_id = $c->stash->{set_result}->id; # remove all usr_preferenes where this set is assigned if($c->stash->{set_result}->contract_id) { my $pref_rs = NGCP::Panel::Utils::Preferences::get_usr_preference_rs( c => $c, attribute => 'contract_sound_set', ); $pref_rs->search({ value => $c->stash->{set_result}->id })->delete; } foreach my $p(qw/usr dom peer/) { $schema->resultset("voip_".$p."_preferences")->search({ 'attribute.attribute' => 'sound_set', value => $c->stash->{set_result}->id, },{ join => 'attribute', })->delete_all; # explicit delete_all, otherwise query fails } # clear audio cache of the current sound set and # all potentially affected children sets NGCP::Panel::Utils::Sems::clear_audio_cache($c, $own_id); $c->stash->{set_result}->delete; }); NGCP::Panel::Utils::Message::info( c => $c, data => { $c->stash->{set_result}->get_inflated_columns }, desc => $c->loc('Sound set successfully deleted'), ); } catch($e) { NGCP::Panel::Utils::Message::error( c => $c, error => $e, desc => $c->loc('Failed to delete sound set'), ); }; NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/sound')); return; } sub create :Chained('sets_list') :PathPart('create') :Args() { my ($self, $c, $contract_id) = @_; delete $c->session->{edit_sound_set_id}; my $posted = ($c->request->method eq 'POST'); my $form; my $params = {}; $params = merge($params, $c->session->{created_objects}); if($c->user->roles eq "admin") { $form = NGCP::Panel::Form::get("NGCP::Panel::Form::Sound::AdminSet", $c); if($contract_id) { my $contract = $c->model('DB')->resultset('contracts')->find($contract_id); if($contract) { $params->{contract}{id} = $contract->id; $params->{reseller}{id} = $contract->contact->reseller_id; } } } elsif($c->user->roles eq "reseller") { $form = NGCP::Panel::Form::get("NGCP::Panel::Form::Sound::ResellerSet", $c); if($contract_id) { my $contract = $c->model('DB')->resultset('contracts')->find($contract_id); if($contract && $contract->contact->reseller_id == $c->user->reseller_id) { $params->{contract}{id} = $contract->id; } } } else { $form = NGCP::Panel::Form::get("NGCP::Panel::Form::Sound::CustomerSet", $c); } unless ($c->license('pbx') && $c->config->{features}->{cloudpbx}) { my $form_render_list = $form->block('fields')->render_list; $form->block('fields')->render_list([ grep {$_ !~ m/^contract(_default)?/} @{ $form_render_list } ]); } $form->process( posted => $posted, params => $c->request->params, item => $params, ); NGCP::Panel::Utils::Navigation::check_form_buttons( c => $c, form => $form, fields => { 'reseller.create' => $c->uri_for('/reseller/create'), 'contract.create' => $c->uri_for_action('/customer/create'), }, back_uri => $c->req->uri, ); if($posted && $form->validated) { try { $form->values->{parent_id} = $form->values->{parent}{id}; if($c->user->roles eq "admin") { $form->values->{reseller_id} = $form->values->{reseller}{id}; $form->values->{contract_id} = $form->values->{contract}{id} // undef; if(defined $form->values->{contract_id}) { $form->values->{contract_default} //= 0; } else { $form->values->{contract_default} = 0; } } elsif($c->user->roles eq "reseller") { $form->values->{reseller_id} = $c->user->reseller_id; $form->values->{contract_id} = $form->values->{contract}{id} // undef; if(defined $form->values->{contract_id}) { $form->values->{contract_default} //= 0; } else { $form->values->{contract_default} = 0; } } else { $form->values->{reseller_id} = $c->user->contract->contact->reseller_id; $form->values->{contract_id} = $c->user->account_id; $form->values->{contract_default} //= 0; } delete $form->values->{reseller}; delete $form->values->{contract}; delete $form->values->{parent}; my $schema = $c->model('DB'); $schema->set_transaction_isolation('READ COMMITTED'); $schema->txn_do(sub { # if a new contract default is set, clear old ones first if($form->values->{contract_id} && $form->values->{contract_default} == 1) { $c->stash->{sets_rs}->search({ reseller_id => $form->values->{reseller_id}, contract_id => $form->values->{contract_id}, contract_default => 1, })->update({ contract_default => 0 }); } my $set = $c->stash->{sets_rs}->create($form->values); if($set->contract && $set->contract_default == 1) { NGCP::Panel::Utils::Sounds::contract_sound_set_propagate( $c, $set->contract, $set->id); } }); delete $c->session->{created_objects}->{reseller}; NGCP::Panel::Utils::Message::info( c => $c, desc => $c->loc('Sound set successfully created'), ); } catch($e) { NGCP::Panel::Utils::Message::error( c => $c, error => $e, desc => $c->loc('Failed to create sound set'), ); } NGCP::Panel::Utils::Navigation::back_or($c, $c->uri_for('/sound')); } $c->stash( form => $form, create_flag => 1, ); return; } sub handles_list :Chained('base') :PathPart('handles') :CaptureArgs(0) { my ( $self, $c ) = @_; my $files_rs = $c->stash->{set_result}->voip_sound_files; $c->stash(files_rs => $files_rs); $c->stash(handles_base_uri => $c->uri_for_action("/sound/handles_root", [$c->req->captures->[0]])); my $set_id = $c->stash->{set_result}->id; my $file_handles = NGCP::Panel::Utils::Sounds::get_file_handles(c => $c, set_id => $set_id); my %groups; for my $handle (@{$file_handles}) { my $group_name = $handle->{group_name}; my $group = $groups{$group_name} //= []; push @{$group}, $handle; } $c->stash(sound_groups => \%groups); $c->stash(file_handles => $file_handles); $c->stash(has_edit => 1); $c->stash(has_delete => 1); $c->stash(template => 'sound/handles_list.tt'); return; } sub handles_root :Chained('handles_list') :PathPart('') :Args(0) { my ($self, $c) = @_; } sub handles_base :Chained('handles_list') :PathPart('') :CaptureArgs(1) { my ($self, $c, $handle_id) = @_; unless($handle_id && is_int($handle_id)) { NGCP::Panel::Utils::Message::error( c => $c, log => 'Invalid sound handle id detected', desc => $c->loc('Invalid sound handle id detected'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); } my $file_handles = $c->stash->{file_handles}; my $handle_exists = any { $_->{handle_id} == $handle_id } @{$file_handles}; unless ($handle_exists) { NGCP::Panel::Utils::Message::error( c => $c, log => 'Sound handle id does not exist', desc => $c->loc('Sound handle id does not exist'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); } my $res = $c->stash->{files_rs}->find_or_new(handle_id => $handle_id); unless(defined $res ) { NGCP::Panel::Utils::Message::error( c => $c, log => 'Sound handle not found', desc => $c->loc('Sound handle not found'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); } $c->stash(file_result => $res); return; } sub handles_edit :Chained('handles_base') :PathPart('edit') { my ($self, $c) = @_; $self->check_subadmin_handle_edit_access($c, $c->stash->{file_result}); my $posted = ($c->request->method eq 'POST'); my $upload = $c->req->upload('soundfile'); $c->request->params->{soundfile} = $posted ? $upload : undef; my $file_result = $c->stash->{file_result}; my $params = { loopplay => $file_result->loopplay // 0, use_parent => $file_result->use_parent // 0, }; $params = merge($params, $c->session->{created_objects}); my $form = NGCP::Panel::Form::get("NGCP::Panel::Form::Sound::File", $c); $form->process( posted => $posted, params => $c->request->params, item => $params, ); NGCP::Panel::Utils::Navigation::check_form_buttons( c => $c, form => $form, fields => {}, back_uri => $c->req->uri, ); if($posted && $form->validated) { # only if the form is validated and a POST is issued, insert the sound file in the db if (defined $upload) { my $soundfile = eval { $upload->slurp }; my $filename = eval { $upload->filename }; my $ft = File::Type->new(); unless ($ft->checktype_contents($soundfile) eq 'audio/x-wav') { NGCP::Panel::Utils::Message::error( c => $c, log => 'Invalid file type detected, only WAV supported', desc => $c->loc('Invalid file type detected, only WAV supported'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); } my $target_codec = 'WAV'; try { $soundfile = NGCP::Panel::Utils::Sounds::transcode_file( $upload->tempname, 'WAV', $target_codec); } catch ($e) { NGCP::Panel::Utils::Message::error( c => $c, log => 'Transcoding audio file failed', desc => $c->loc('Transcoding audio file failed'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); } try { my $schema = $c->model('DB'); $schema->set_transaction_isolation('READ COMMITTED'); $schema->txn_do(sub { $file_result->insert(); $file_result->update({ loopplay => $form->values->{loopplay}, use_parent => $form->values->{use_parent}, filename => $filename, data => $soundfile, codec => $target_codec, }); }); NGCP::Panel::Utils::Message::info( c => $c, desc => $c->loc('Sound handle successfully uploaded'), ); } catch($e) { NGCP::Panel::Utils::Message::error( c => $c, error => $e, desc => $c->loc('Failed to update uploaded sound handle'), ); } } else { try { my $schema = $c->model('DB'); $schema->set_transaction_isolation('READ COMMITTED'); $schema->txn_do(sub { $file_result->insert(); $file_result->update({ loopplay => $form->values->{loopplay}, use_parent => $form->values->{use_parent}, }); }); NGCP::Panel::Utils::Message::info( c => $c, desc => $c->loc('Sound handle successfully updated'), ); } catch($e) { NGCP::Panel::Utils::Message::error( c => $c, error => $e, desc => $c->loc('Failed to update sound handle'), ); } } # clear audio caches my $group_name = $file_result->handle->group->name; try { NGCP::Panel::Utils::Sems::clear_audio_cache($c, $file_result->set_id, $file_result->handle->name, $group_name); } catch ($e) { NGCP::Panel::Utils::Message::error( c => $c, error => "Failed to clear audio cache for " . $group_name . " at appserver", desc => $c->loc('Failed to clear audio cache.'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); } NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); } $c->stash(form => $form); $c->stash(edit_flag => 1); return; } sub handles_delete :Chained('handles_base') :PathPart('delete') { my ($self, $c) = @_; $self->check_subadmin_handle_edit_access($c, $c->stash->{file_result}); try { my $schema = $c->model('DB'); $schema->set_transaction_isolation('READ COMMITTED'); $schema->txn_do(sub { $c->stash->{file_result}->delete; }); NGCP::Panel::Utils::Message::info( c => $c, data => { $c->stash->{file_result}->get_inflated_columns }, desc => $c->loc('Sound handle successfully deleted'), ); } catch($e) { NGCP::Panel::Utils::Message::error( c => $c, error => $e, desc => $c->loc('Failed to delete sound handle'), ); }; # clear audio caches my $handle = $c->stash->{file_result}->handle; my $group_name = $handle->group->name; try { NGCP::Panel::Utils::Sems::clear_audio_cache($c, $c->stash->{file_result}->set_id, $handle->name, $group_name); } catch ($e) { $c->log->warn("Failed to clear audio cache for group " . $group_name); } NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); return; } sub handles_download :Chained('handles_base') :PathPart('download') :Args(0) { my ($self, $c) = @_; $self->check_subadmin_handle_download_access($c, $c->stash->{file_result}); my $file = $c->stash->{file_result}; my $filename = $file->filename; $filename =~ s/\.\w+$/.wav/; my $data_ref; if($file->codec ne 'WAV') { try { $data_ref = NGCP::Panel::Utils::Sounds::transcode_data( \$file->data, $file->codec, 'WAV'); } catch($e) { NGCP::Panel::Utils::Message::error( c => $c, error => $e, desc => $c->loc('Failed to transcode audio file'), ); NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); } } else { $data_ref = \$file->data; } $c->response->header ('Content-Disposition' => 'attachment; filename="' . $filename . '"'); $c->response->content_type('audio/x-wav'); $c->response->body($$data_ref); return; } sub handles_load_default :Chained('handles_list') :PathPart('loaddefault') :Args(0) { my ($self, $c) = @_; my $posted = ($c->request->method eq 'POST'); my $form = NGCP::Panel::Form::get("NGCP::Panel::Form::Sound::LoadDefault", $c); my $error; $form->process( posted => $posted, params => $c->request->params, item => {}, ); NGCP::Panel::Utils::Navigation::check_form_buttons( c => $c, form => $form, fields => {}, back_uri => $c->req->uri, ); if($posted && $form->validated) { try { my $schema = $c->model('DB'); $schema->txn_do(sub { NGCP::Panel::Utils::Sounds::apply_default_soundset_files( c => $c, lang => $form->params->{language}, set_id => $c->stash->{set_result}->id, file_handles => $c->stash->{file_handles}, loopplay => $form->params->{loopplay}, override => $form->params->{replace_existing}, error_ref => \$error, ); }); NGCP::Panel::Utils::Message::info( c => $c, desc => $c->loc('Sound set successfully loaded with default files.'), ); } catch($e) { NGCP::Panel::Utils::Message::error( c => $c, $error ? (desc => $c->loc($error)) : (error => $e, desc => $c->loc('Failed to load default sound files.')), ); } NGCP::Panel::Utils::Navigation::back_or($c, $c->stash->{handles_base_uri}); return; } $c->stash(form => $form); $c->stash(edit_default_flag => 1); return; } sub check_subadmin_set_edit_access { my ($self, $c, $set) = @_; if ($c->user->roles eq 'subscriberadmin') { if ($set->contract_id && $set->contract_id == $c->user->account_id) { return 1; } $c->detach('/denied_page'); } return 1; } sub check_subadmin_handle_edit_access { my ($self, $c, $file_result) = @_; if ($c->user->roles eq 'subscriberadmin') { my $set = $file_result->set; if ($set->contract_id && $set->contract_id == $c->user->account_id) { return 1; } $c->detach('/denied_page'); } return 1; } sub check_subadmin_handle_download_access { my ($self, $c, $file_result) = @_; if ($c->user->roles eq 'subscriberadmin') { my $set = $file_result->set; my $contract_rs = $c->stash->{contract_rs} // NGCP::Panel::Utils::Contract::get_contract_rs(schema => $c->model('DB'))->search_rs({ 'me.id' => $c->user->account_id, }); my $contract = $contract_rs->first; if (!$set->contract_id && $set->expose_to_customer == 1 && $set->reseller_id == $contract->contact->reseller_id) { return 1; } elsif ($set->contract_id && $set->contract_id == $c->user->account_id) { return 1; } $c->detach('/denied_page'); } return 1; } 1; # vim: set tabstop=4 expandtab: