diff --git a/lib/NGCP/Panel/Role/API/Preferences.pm b/lib/NGCP/Panel/Role/API/Preferences.pm index 9145d4ce0f..fa613e1ae9 100644 --- a/lib/NGCP/Panel/Role/API/Preferences.pm +++ b/lib/NGCP/Panel/Role/API/Preferences.pm @@ -274,6 +274,13 @@ sub get_resource { # default $value = $pref->value; } # SWITCH + eval { + $value = NGCP::Panel::Utils::Preferences::api_transform_out($c, $pref->attribute, $pref->value); + }; + if ($@) { + $c->log->error("Failed to transform pref value - $@"); + # let it slip through + } if($pref->attribute->max_occur != 1) { $resource->{$pref->attribute->attribute} = [] unless(exists $resource->{$pref->attribute->attribute}); @@ -754,7 +761,7 @@ sub update_item { } } - if($meta->data_type eq "boolean" && JSON::is_bool($resource->{$pref})) { + if (($meta->data_type eq "boolean" or NGCP::Panel::Utils::Preferences::exists_api_transform_in($c, $pref)) and JSON::is_bool($resource->{$pref})) { $vtype = ""; } if($meta->max_occur == 1 && $vtype ne "") { @@ -935,6 +942,14 @@ sub update_item { $pref_rs->delete; foreach my $v(@{ $resource->{$pref} }) { return unless $self->check_pref_value($c, $meta, $v, $pref_type); + eval { + $v = NGCP::Panel::Utils::Preferences::api_transform_in($c, $meta, $v); + }; + if ($@) { + $c->log->error("Failed to transform pref value - $@"); + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Internal Server Error."); # TODO? + return; + } if(JSON::is_bool($v)){ $v = $v ? 1 : 0 ; } @@ -942,12 +957,28 @@ sub update_item { } } elsif($pref_rs->first) { return unless $self->check_pref_value($c, $meta, $resource->{$pref}, $pref_type); + eval { + $resource->{$pref} = NGCP::Panel::Utils::Preferences::api_transform_in($c, $meta, $resource->{$pref}); + }; + if ($@) { + $c->log->error("Failed to transform pref value - $@"); + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Internal Server Error."); # TODO? + return; + } if(JSON::is_bool($resource->{$pref})){ $resource->{$pref} = $resource->{$pref} ? 1 : 0 ; } $pref_rs->first->update({ value => $resource->{$pref} }); } else { return unless $self->check_pref_value($c, $meta, $resource->{$pref}, $pref_type); + eval { + $resource->{$pref} = NGCP::Panel::Utils::Preferences::api_transform_in($c, $meta, $resource->{$pref}); + }; + if ($@) { + $c->log->error("Failed to transform pref value - $@"); + $self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Internal Server Error."); # TODO? + return; + } if(JSON::is_bool($resource->{$pref})){ $resource->{$pref} = $resource->{$pref} ? 1 : 0 ; } @@ -992,6 +1023,8 @@ sub check_pref_value { my ($self, $c, $meta, $value, $pref_type) = @_; my $err; + return 1 if NGCP::Panel::Utils::Preferences::exists_api_transform_in($c,$meta->attribute); + my $vtype = ref $value; if($meta->data_type eq "boolean" && JSON::is_bool($value)) { $vtype = ""; diff --git a/lib/NGCP/Panel/Utils/Preferences.pm b/lib/NGCP/Panel/Utils/Preferences.pm index 71fcbb43c9..6a48f405dc 100644 --- a/lib/NGCP/Panel/Utils/Preferences.pm +++ b/lib/NGCP/Panel/Utils/Preferences.pm @@ -10,6 +10,10 @@ use NGCP::Panel::Utils::Sems; use constant _DYNAMIC_PREFERENCE_PREFIX => '__'; +my $API_TRANSFORM_OUT; +my $API_TRANSFORM_IN; +my $CODE_SUFFIX_FNAME = '_code'; + sub validate_ipnet { my ($field) = @_; if ( !$field->value ) { @@ -36,6 +40,87 @@ sub validate_ipnet { return 1; } +sub _init_transform { + my ($transform,$conf) = @_; + unless (defined $transform) { + $transform = {}; + if (defined $conf) { + foreach my $p (keys %$conf) { + $transform->{$p} = {}; + foreach my $v (keys %{$conf->{$p}}) { + if ($v =~ /^([a-z0-9_]+)$CODE_SUFFIX_FNAME$/) { + ## no critic (BuiltinFunctions::ProhibitStringyEval) + $transform->{$p}->{$1} = eval($conf->{$p}->{$v}); + die("$p '$v': " . $@) if $@; + } else { + $transform->{$p}->{$v} = $conf->{$p}->{$v}; + } + } + } + } + } + return $transform; +} + +sub exists_api_transform_in { + my ($c, $pref) = @_; + if ($c->request and $c->request->path =~/^api\//i) { + $API_TRANSFORM_IN = _init_transform($API_TRANSFORM_IN,$c->config->{preference_in_transformations}); + if (exists $API_TRANSFORM_IN->{$pref}) { + return 1; + } + } + return 0; +} + +sub api_transform_in { + my ($c, $meta, $value) = @_; + if ($c->request and $c->request->path =~/^api\//i) { + $API_TRANSFORM_IN = _init_transform($API_TRANSFORM_IN,$c->config->{preference_in_transformations}); + if (exists $API_TRANSFORM_IN->{$meta->attribute}) { + if (defined $value) { + my $v = $value; + if (JSON::is_bool($v)) { + $v = $v ? 1 : 0 ; + } + if (exists $API_TRANSFORM_IN->{$meta->attribute}->{$v}) { + $value = $API_TRANSFORM_IN->{$meta->attribute}->{$v}; + if ('CODE' eq ref $value) { + eval { + $value = $value->($meta,$value); + }; + if ($@) { + die($meta->attribute . ": " . $@); + } + } + } + } + } + } + return $value; +} + +sub api_transform_out { + my ($c, $meta, $value) = @_; + if ($c->request and $c->request->path =~/^api\//i) { + $API_TRANSFORM_OUT = _init_transform($API_TRANSFORM_OUT,$c->config->{preference_out_transformations}); + if (exists $API_TRANSFORM_OUT->{$meta->attribute}) { + if (defined $value and exists $API_TRANSFORM_OUT->{$meta->attribute}->{$value}) { + $value = $API_TRANSFORM_OUT->{$meta->attribute}->{$value}; + if ('CODE' eq ref $value) { + eval { + $value = $value->($meta,$value); + }; + if ($@) { + die($meta->attribute . ": " . $@); + } + } + } + } + } + return $value; +} + sub load_preference_list { my %params = @_; @@ -1431,7 +1516,7 @@ sub get_provisoning_voip_subscriber_first_int_attr_value { } } -sub api_preferences_defs{ +sub api_preferences_defs { my %params = @_; my $c = $params{c};