From a8d5e4bc191c82d4cbc96330680505337d74eb4e Mon Sep 17 00:00:00 2001 From: Marco Capetta Date: Wed, 5 Aug 2026 18:14:50 +0200 Subject: [PATCH] MT#65665 return redirect credentials on pbxdevicemodels on GET API The bootstrap_config_redirect_*_user and _password values are stored in provisioning.autoprov_redirect_credentials, while _profile is a sync parameter in provisioning.autoprov_sync. resource_from_item only called devmod_sync_parameters_prefetch_api, so GET returned the profile but silently dropped the credentialsm. Add devmod_sync_credentials_prefetch_api, mirroring the read-back the web UI already does in Controller::Device, and call it from resource_from_item for the admin and reseller roles only, which are the roles allowed to write these fields. Subscriber and subscriberadmin GETs keep them hidden. Change-Id: I02a8975fbf9fe60796832cf281d054e634ce6c00 (cherry picked from commit 8042d9f4d1607bf1ab74f4ad5367b041b9837630) (cherry picked from commit bea08fb66a9e0b17ec55d6611a04a2de3f9679b4) --- lib/NGCP/Panel/Role/API/PbxDeviceModels.pm | 5 +++ lib/NGCP/Panel/Utils/DeviceBootstrap.pm | 17 ++++++++ t/api-rest/api-pbxdevicemodels.t | 50 ++++++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/lib/NGCP/Panel/Role/API/PbxDeviceModels.pm b/lib/NGCP/Panel/Role/API/PbxDeviceModels.pm index d7f7491457..0b0f489c65 100644 --- a/lib/NGCP/Panel/Role/API/PbxDeviceModels.pm +++ b/lib/NGCP/Panel/Role/API/PbxDeviceModels.pm @@ -99,6 +99,11 @@ sub resource_from_item { NGCP::Panel::Utils::DeviceBootstrap::devmod_sync_parameters_prefetch_api($c, $item,\%resource); + #redirect server credentials are only exposed to the roles allowed to write them + if($c->user && ($c->user->roles eq "admin" || $c->user->roles eq "reseller")){ + NGCP::Panel::Utils::DeviceBootstrap::devmod_sync_credentials_prefetch_api($c, $item,\%resource); + } + if('extension' eq $item->type){ # show possible devices for extension $resource{connectable_models} = [map {$_->device->id} ($item->autoprov_extension_device_link->all) ]; diff --git a/lib/NGCP/Panel/Utils/DeviceBootstrap.pm b/lib/NGCP/Panel/Utils/DeviceBootstrap.pm index 4a2c53173a..8b483c168d 100644 --- a/lib/NGCP/Panel/Utils/DeviceBootstrap.pm +++ b/lib/NGCP/Panel/Utils/DeviceBootstrap.pm @@ -160,6 +160,23 @@ sub devmod_sync_parameters_prefetch_api{ return $resource; } +sub devmod_sync_credentials_prefetch_api{ + my($c,$item,$resource) = @_; + $resource //= {}; + my $bootstrap_method = $item->get_column('bootstrap_method'); + #only redirect_* methods have user/password fields in the form + return $resource unless $bootstrap_method && $bootstrap_method =~ /^redirect_/; + my $schema = $c->model('DB'); + my $credentials = $schema->resultset('autoprov_redirect_credentials')->search_rs({ + 'me.device_id' => $item->id, + })->first; + return $resource unless $credentials; + foreach (qw/user password/){ + $resource->{'bootstrap_config_'.$bootstrap_method.'_'.$_} = $credentials->get_column($_); + } + return $resource; +} + sub devmod_sync_credentials_prefetch{ my($c,$devmod,$params) = @_; my $schema = $c->model('DB'); diff --git a/t/api-rest/api-pbxdevicemodels.t b/t/api-rest/api-pbxdevicemodels.t index f9ca6f3efe..bf9b0b3020 100644 --- a/t/api-rest/api-pbxdevicemodels.t +++ b/t/api-rest/api-pbxdevicemodels.t @@ -169,6 +169,56 @@ foreach my $type(qw/extension phone/){ is($res->code, 422, "check patched invalid reseller"); } } +# redirect server credentials are stored in autoprov_redirect_credentials, while the +# profile is a sync parameter. GET has to return all of them, not just the profile. +{ + my $t = time; + my %polycom = ( + bootstrap_config_redirect_polycom_user => 'polycom_user_'.$t, + bootstrap_config_redirect_polycom_password => 'polycom_pass_'.$t, + bootstrap_config_redirect_polycom_profile => 'polycom_profile_'.$t, + ); + my ($res) = $test_machine->check_item_post(sub{ + my $data = shift; + $data->{json}->{model} = 'api_test polycom_redirect_'.$t; + $data->{json}->{type} = 'phone'; + $data->{json}->{bootstrap_method} = 'redirect_polycom'; + @{$data->{json}}{keys %polycom} = values %polycom; + }); + is($res->code, 201, "create redirect_polycom model"); + my $location = $res->header('Location'); + ok($location, "check location of the created redirect_polycom model"); + if($location){ + my (undef, $item) = $test_machine->check_item_get($location); + foreach my $field(sort keys %polycom){ + is($item->{$field}, $polycom{$field}, "check $field returned by GET"); + } + # patching an unrelated field must not drop the redirect credentials + my $patched_model = 'api_test polycom_redirect_patched_'.$t; + my ($patch_res) = $test_machine->request_patch( + [ { op => 'replace', path => '/model', value => $patched_model } ], + $location, + ); + is($patch_res->code, 200, "patch model of the redirect_polycom model"); + (undef, $item) = $test_machine->check_item_get($location); + is($item->{model}, $patched_model, "check patched model"); + foreach my $field(sort keys %polycom){ + is($item->{$field}, $polycom{$field}, "check $field preserved after PATCH"); + } + $test_machine->request_delete($location); + } +} +# bootstrap methods other than redirect_* have no credentials fields at all +{ + my $location = $connactable_devices->{phone}->{data}->[0]->{location}; + if($location){ + my (undef, $item) = $test_machine->check_item_get($location); + is($item->{bootstrap_method}, 'http', "check bootstrap_method of the http model"); + foreach my $field(qw/bootstrap_config_http_user bootstrap_config_http_password/){ + ok(!exists $item->{$field}, "check absence of $field"); + } + } +} #pbxdevicemodels doesn't have DELETE method #`echo 'delete from autoprov_devices where model like "%api_test %" or model like "patched model%";'|mysql -u root provisioning`; done_testing;