diff --git a/lib/NGCP/Panel/Controller/API/PbxDevicePreferenceDefs.pm b/lib/NGCP/Panel/Controller/API/PbxDevicePreferenceDefs.pm
new file mode 100644
index 0000000000..81cde82b62
--- /dev/null
+++ b/lib/NGCP/Panel/Controller/API/PbxDevicePreferenceDefs.pm
@@ -0,0 +1,115 @@
+package NGCP::Panel::Controller::API::PbxDevicePreferenceDefs;
+use NGCP::Panel::Utils::Generic qw(:all);
+
+use Sipwise::Base;
+
+use boolean qw(true);
+use Data::HAL qw();
+use Data::HAL::Link qw();
+use HTTP::Headers qw();
+use HTTP::Status qw(:constants);
+
+use NGCP::Panel::Utils::DateTime;
+use NGCP::Panel::Utils::Preferences;
+use Path::Tiny qw(path);
+use Safe::Isa qw($_isa);
+use JSON::Types qw();
+require Catalyst::ActionRole::ACL;
+require Catalyst::ActionRole::CheckTrailingSlash;
+require NGCP::Panel::Role::HTTPMethods;
+require Catalyst::ActionRole::RequireSSL;
+
+sub allowed_methods{
+ return [qw/GET OPTIONS HEAD/];
+}
+
+use parent qw/Catalyst::Controller NGCP::Panel::Role::API/;
+
+sub resource_name{
+ return 'pbxdevicepreferencedefs';
+}
+sub dispatch_path{
+ return '/api/pbxdevicepreferencedefs/';
+}
+sub relation{
+ return 'http://purl.org/sipwise/ngcp-api/#rel-pbxdevicepreferencedefs';
+}
+
+__PACKAGE__->config(
+ action => {
+ map { $_ => {
+ ACLDetachTo => '/api/root/invalid_user',
+ AllowedRole => [qw/admin reseller/],
+ Args => 0,
+ Does => [qw(ACL CheckTrailingSlash RequireSSL)],
+ Method => $_,
+ Path => __PACKAGE__->dispatch_path,
+ } } @{ __PACKAGE__->allowed_methods }
+ },
+ action_roles => [qw(+NGCP::Panel::Role::HTTPMethods)],
+);
+
+sub auto :Private {
+ my ($self, $c) = @_;
+
+ $self->set_body($c);
+ $self->log_request($c);
+}
+
+sub GET :Allow {
+ my ($self, $c) = @_;
+ {
+ my @links;
+ push @links,
+ Data::HAL::Link->new(
+ relation => 'curies',
+ href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
+ name => 'ngcp',
+ templated => true,
+ ),
+ Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
+ Data::HAL::Link->new(relation => 'self', href => sprintf('%s', $self->dispatch_path));
+
+ my $hal = Data::HAL->new(
+ links => [@links],
+ );
+ my $resource = NGCP::Panel::Utils::Preferences::api_preferences_defs( c => $c, preferences_group => 'dev_pref' );
+ $hal->resource($resource);
+
+ my $response = HTTP::Response->new(HTTP_OK, undef,
+ HTTP::Headers->new($hal->http_headers(skip_links => 1)), $hal->as_json);
+ $c->response->headers($response->headers);
+ $c->response->body($response->content);
+ return;
+ }
+ return;
+}
+
+sub HEAD :Allow {
+ my ($self, $c) = @_;
+ $c->forward(qw(GET));
+ $c->response->body(q());
+ return;
+}
+
+sub OPTIONS :Allow {
+ my ($self, $c) = @_;
+ my $allowed_methods = $self->allowed_methods_filtered($c);
+ $c->response->headers(HTTP::Headers->new(
+ Allow => join(', ', @{ $allowed_methods }),
+ Accept_Post => 'application/hal+json; profile=http://purl.org/sipwise/ngcp-api/#rel-'.$self->resource_name,
+ ));
+ $c->response->content_type('application/json');
+ $c->response->body(JSON::to_json({ methods => $allowed_methods })."\n");
+ return;
+}
+
+sub end : Private {
+ my ($self, $c) = @_;
+
+ $self->log_response($c);
+}
+
+1;
+
+# vim: set tabstop=4 expandtab:
diff --git a/lib/NGCP/Panel/Controller/API/PbxDevicePreferences.pm b/lib/NGCP/Panel/Controller/API/PbxDevicePreferences.pm
new file mode 100644
index 0000000000..6b98b08f9b
--- /dev/null
+++ b/lib/NGCP/Panel/Controller/API/PbxDevicePreferences.pm
@@ -0,0 +1,136 @@
+package NGCP::Panel::Controller::API::PbxDevicePreferences;
+use NGCP::Panel::Utils::Generic qw(:all);
+
+use Sipwise::Base;
+
+use boolean qw(true);
+use Data::HAL qw();
+use Data::HAL::Link qw();
+use HTTP::Headers qw();
+use HTTP::Status qw(:constants);
+
+use NGCP::Panel::Utils::DateTime;
+use Path::Tiny qw(path);
+use Safe::Isa qw($_isa);
+require Catalyst::ActionRole::ACL;
+require Catalyst::ActionRole::CheckTrailingSlash;
+require NGCP::Panel::Role::HTTPMethods;
+require Catalyst::ActionRole::RequireSSL;
+
+sub allowed_methods{
+ return [qw/GET OPTIONS HEAD/];
+}
+
+sub api_description {
+ return 'Specifies certain properties (preferences) for a PBX Device Models. The full list of properties can be obtained via PbxDevicePreferenceDefs.';
+};
+
+use parent qw/Catalyst::Controller NGCP::Panel::Role::API::Preferences/;
+
+sub resource_name{
+ return 'pbxdevicepreferences';
+}
+sub dispatch_path{
+ return '/api/pbxdevicepreferences/';
+}
+sub relation{
+ return 'http://purl.org/sipwise/ngcp-api/#rel-pbxdevicepreferences';
+}
+
+__PACKAGE__->config(
+ action => {
+ map { $_ => {
+ ACLDetachTo => '/api/root/invalid_user',
+ AllowedRole => [qw/admin reseller/],
+ Args => 0,
+ Does => [qw(ACL CheckTrailingSlash RequireSSL)],
+ Method => $_,
+ Path => __PACKAGE__->dispatch_path,
+ } } @{ __PACKAGE__->allowed_methods }
+ },
+ action_roles => [qw(+NGCP::Panel::Role::HTTPMethods)],
+);
+
+sub auto :Private {
+ my ($self, $c) = @_;
+
+ $self->set_body($c);
+ $self->log_request($c);
+}
+
+sub GET :Allow {
+ my ($self, $c) = @_;
+ my $container_type = 'pbxdevicemodels';
+ my $page = $c->request->params->{page} // 1;
+ my $rows = $c->request->params->{rows} // 10;
+ {
+ my $container_items = $self->item_rs($c, $container_type);
+ (my $total_count, $container_items) = $self->paginate_order_collection($c, $container_items);
+ my (@embedded, @links);
+ for my $container_item ($container_items->all) {
+ push @embedded, $self->hal_from_item($c, $container_item, $container_type);
+ push @links, Data::HAL::Link->new(
+ relation => 'ngcp:'.$self->resource_name,
+ href => sprintf('%s%d', $self->dispatch_path, $container_item->id),
+ );
+ }
+ push @links,
+ Data::HAL::Link->new(
+ relation => 'curies',
+ href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
+ name => 'ngcp',
+ templated => true,
+ ),
+ Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
+ Data::HAL::Link->new(relation => 'self', href => sprintf('%s?page=%s&rows=%s', $self->dispatch_path, $page, $rows));
+ if(($total_count / $rows) > $page ) {
+ push @links, Data::HAL::Link->new(relation => 'next', href => sprintf('%s?page=%d&rows=%d', $self->dispatch_path, $page + 1, $rows));
+ }
+ if($page > 1) {
+ push @links, Data::HAL::Link->new(relation => 'prev', href => sprintf('%s?page=%d&rows=%d', $self->dispatch_path, $page - 1, $rows));
+ }
+
+ my $hal = Data::HAL->new(
+ embedded => [@embedded],
+ links => [@links],
+ );
+ $hal->resource({
+ total_count => $total_count,
+ });
+ my $response = HTTP::Response->new(HTTP_OK, undef,
+ HTTP::Headers->new($hal->http_headers(skip_links => 1)), $hal->as_json);
+ $c->response->headers($response->headers);
+ $c->response->body($response->content);
+ return;
+ }
+ return;
+}
+
+sub HEAD :Allow {
+ my ($self, $c) = @_;
+ $c->forward(qw(GET));
+ $c->response->body(q());
+ return;
+}
+
+sub OPTIONS :Allow {
+ my ($self, $c) = @_;
+ my $allowed_methods = $self->allowed_methods_filtered($c);
+ $c->response->headers(HTTP::Headers->new(
+ Allow => join(', ', @{ $allowed_methods }),
+ Accept_Post => 'application/hal+json; profile=http://purl.org/sipwise/ngcp-api/#rel-'.$self->resource_name,
+ ));
+ $c->response->content_type('application/json');
+ $c->response->body(JSON::to_json({ methods => $allowed_methods })."\n");
+ return;
+}
+
+sub end : Private {
+ my ($self, $c) = @_;
+
+ $self->log_response($c);
+}
+
+1;
+
+# vim: set tabstop=4 expandtab:
diff --git a/lib/NGCP/Panel/Controller/API/PbxDevicePreferencesItem.pm b/lib/NGCP/Panel/Controller/API/PbxDevicePreferencesItem.pm
new file mode 100644
index 0000000000..8929e40bc7
--- /dev/null
+++ b/lib/NGCP/Panel/Controller/API/PbxDevicePreferencesItem.pm
@@ -0,0 +1,220 @@
+package NGCP::Panel::Controller::API::PbxDevicePreferencesItem;
+use NGCP::Panel::Utils::Generic qw(:all);
+
+use Sipwise::Base;
+
+use boolean qw(true);
+use Data::HAL qw();
+use Data::HAL::Link qw();
+use HTTP::Headers qw();
+use HTTP::Status qw(:constants);
+
+use NGCP::Panel::Utils::ValidateJSON qw();
+use NGCP::Panel::Utils::DateTime;
+use Path::Tiny qw(path);
+use Safe::Isa qw($_isa);
+require Catalyst::ActionRole::ACL;
+require NGCP::Panel::Role::HTTPMethods;
+require Catalyst::ActionRole::RequireSSL;
+
+sub allowed_methods{
+ return [qw/GET OPTIONS HEAD PATCH PUT/];
+}
+
+use parent qw/Catalyst::Controller NGCP::Panel::Role::API::Preferences/;
+
+sub resource_name{
+ return 'pbxdevicepreferences';
+}
+sub dispatch_path{
+ return '/api/pbxdevicepreferences/';
+}
+sub relation{
+ return 'http://purl.org/sipwise/ngcp-api/#rel-pbxdevicepreferences';
+}
+
+sub journal_query_params {
+ my($self,$query_params) = @_;
+ return $self->get_journal_query_params($query_params);
+}
+
+__PACKAGE__->config(
+ action => {
+ (map { $_ => {
+ ACLDetachTo => '/api/root/invalid_user',
+ AllowedRole => [qw/admin reseller/],
+ Args => 1,
+ Does => [qw(ACL RequireSSL)],
+ Method => $_,
+ Path => __PACKAGE__->dispatch_path,
+ } } @{ __PACKAGE__->allowed_methods }),
+ @{ __PACKAGE__->get_journal_action_config(__PACKAGE__->resource_name,{
+ ACLDetachTo => '/api/root/invalid_user',
+ AllowedRole => [qw/admin reseller/],
+ Does => [qw(ACL RequireSSL)],
+ }) }
+ },
+ action_roles => [qw(+NGCP::Panel::Role::HTTPMethods)],
+);
+
+sub auto :Private {
+ my ($self, $c) = @_;
+
+ $self->set_body($c);
+ $self->log_request($c);
+}
+
+sub GET :Allow {
+ my ($self, $c, $id) = @_;
+ {
+ last unless $self->valid_id($c, $id);
+ my $container_type = "pbxdevicemodels";
+ my $preferences_type = "pbxdevicepreference";
+ my $container_item = $self->item_by_id($c, $id, $container_type);
+ last unless $self->resource_exists($c, $preferences_type => $container_item);
+
+ my $hal = $self->hal_from_item($c, $container_item, $container_type);
+
+ my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new(
+ (map { # XXX Data::HAL must be able to generate links with multiple relations
+ s|rel="(http://purl.org/sipwise/ngcp-api/#rel-resellers)"|rel="item $1"|;
+ s/rel=self/rel="item self"/;
+ $_
+ } $hal->http_headers),
+ ), $hal->as_json);
+ $c->response->headers($response->headers);
+ $c->response->body($response->content);
+ return;
+ }
+ return;
+}
+
+sub HEAD :Allow {
+ my ($self, $c, $id) = @_;
+ $c->forward(qw(GET));
+ $c->response->body(q());
+ return;
+}
+
+sub OPTIONS :Allow {
+ my ($self, $c, $id) = @_;
+ my $allowed_methods = $self->allowed_methods_filtered($c);
+ $c->response->headers(HTTP::Headers->new(
+ Allow => join(', ', @{ $allowed_methods }),
+ Accept_Patch => 'application/json-patch+json',
+ ));
+ $c->response->content_type('application/json');
+ $c->response->body(JSON::to_json({ methods => $allowed_methods })."\n");
+ return;
+}
+
+sub PATCH :Allow {
+ my ($self, $c, $id) = @_;
+ my $guard = $c->model('DB')->txn_scope_guard;
+ {
+ my $preference = $self->require_preference($c);
+ last unless $preference;
+
+ my $json = $self->get_valid_patch_data(
+ c => $c,
+ id => $id,
+ media_type => 'application/json-patch+json',
+ ops => [qw/add replace remove copy/],
+ );
+ last unless $json;
+
+ my $container_type = "pbxdevicemodels";
+ my $preferences_type = "pbxdevicepreference";
+ my $container_item = $self->item_by_id($c, $id, $container_type);
+ last unless $self->resource_exists($c, $preferences_type => $container_item);
+ my $old_resource = $self->get_resource($c, $container_item, $container_type);
+ my $resource = $self->apply_patch($c, $old_resource, $json);
+ last unless $resource;
+
+ # last param is "no replace" to NOT delete existing prefs
+ # for proper PATCH behavior
+ $container_item = $self->update_item($c, $container_item, $old_resource, $resource, 0, $container_type);
+ last unless $container_item;
+
+ my $hal = $self->hal_from_item($c, $container_item, $container_type);
+ last unless $self->add_update_journal_item_hal($c,$hal);
+
+ $guard->commit;
+
+ if ('minimal' eq $preference) {
+ $c->response->status(HTTP_NO_CONTENT);
+ $c->response->header(Preference_Applied => 'return=minimal');
+ $c->response->body(q());
+ } else {
+ #my $hal = $self->hal_from_item($c, $container_item, $container_type);
+ my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new(
+ $hal->http_headers,
+ ), $hal->as_json);
+ $c->response->headers($response->headers);
+ $c->response->header(Preference_Applied => 'return=representation');
+ $c->response->body($response->content);
+ }
+ }
+ return;
+}
+
+sub PUT :Allow {
+ my ($self, $c, $id) = @_;
+ my $guard = $c->model('DB')->txn_scope_guard;
+ {
+ my $preference = $self->require_preference($c);
+ last unless $preference;
+
+ my $container_type = "pbxdevicemodels";
+ my $preferences_type = "pbxdevicepreference";
+ my $container_item = $self->item_by_id($c, $id, $container_type);
+ # TODO: systemcontact?
+ last unless $self->resource_exists($c, $preferences_type => $container_item);
+ my $resource = $self->get_valid_put_data(
+ c => $c,
+ id => $id,
+ media_type => 'application/json',
+ );
+ last unless $resource;
+ my $old_resource = $self->get_resource($c, $container_item, $container_type);
+
+ # last param is "replace" to delete all existing prefs
+ # for proper PUT behavior
+ $container_item = $self->update_item($c, $container_item, $old_resource, $resource, 1, $container_type);
+ last unless $container_item;
+
+ my $hal = $self->hal_from_item($c, $container_item, $container_type);
+ last unless $self->add_update_journal_item_hal($c,$hal);
+
+ $guard->commit;
+
+ if ('minimal' eq $preference) {
+ $c->response->status(HTTP_NO_CONTENT);
+ $c->response->header(Preference_Applied => 'return=minimal');
+ $c->response->body(q());
+ } else {
+ #my $hal = $self->hal_from_item($c, $container_item, $container_type);
+ my $response = HTTP::Response->new(HTTP_OK, undef, HTTP::Headers->new(
+ $hal->http_headers,
+ ), $hal->as_json);
+ $c->response->headers($response->headers);
+ $c->response->header(Preference_Applied => 'return=representation');
+ $c->response->body($response->content);
+ }
+ }
+ return;
+}
+
+sub get_journal_methods{
+ return [qw/handle_item_base_journal handle_journals_get handle_journalsitem_get handle_journals_options handle_journalsitem_options handle_journals_head handle_journalsitem_head/];
+}
+
+sub end : Private {
+ my ($self, $c) = @_;
+
+ $self->log_response($c);
+}
+
+1;
+
+# vim: set tabstop=4 expandtab:
diff --git a/lib/NGCP/Panel/Controller/API/Root.pm b/lib/NGCP/Panel/Controller/API/Root.pm
index 201b264193..acc30d6f9c 100644
--- a/lib/NGCP/Panel/Controller/API/Root.pm
+++ b/lib/NGCP/Panel/Controller/API/Root.pm
@@ -57,6 +57,7 @@ sub GET : Allow {
"CustomerPreferenceDefs" => 1,
"ProfilePreferenceDefs" => 1,
"PeeringServerPreferenceDefs" => 1,
+ "PbxDevicePreferenceDefs" => 1,
};
my @colls = $self->get_collections;
diff --git a/lib/NGCP/Panel/Controller/Device.pm b/lib/NGCP/Panel/Controller/Device.pm
index 79489b0389..b0b254efa5 100644
--- a/lib/NGCP/Panel/Controller/Device.pm
+++ b/lib/NGCP/Panel/Controller/Device.pm
@@ -1036,7 +1036,6 @@ sub get_annotated_info :Privat {
foreach(qw/front_image mac_image/){
delete $device_info->{$_};
}
- use Data::Dumper;
my $gather_ranges_info = sub {
my $rs = shift;
return [ map {
@@ -1335,9 +1334,10 @@ sub dev_field_config :Chained('/') :PathPart('device/autoprov/config') :Args() {
cc => '',
ac => '',
);
- my $pref_rs = NGCP::Panel::Utils::Preferences::get_usr_preferences_rs(
+ my $pref_rs = NGCP::Panel::Utils::Preferences::get_preferences_rs(
c => $c,
- prov_subscriber => $sub,
+ id => $sub->id,
+ type => 'usr',
#attribute => [keys %sub_preferences_vars],
);
my $preferences = get_inflated_columns_all($pref_rs, 'hash' => 'attribute', 'column' => 'value' );
@@ -1876,7 +1876,7 @@ sub dev_field_firmware_next :Chained('dev_field_firmware_version_base') :PathPar
$q = $c->req->params->{q};
}
if(defined $q) {
- $q=~s/\.rom$//i; #yealink v > 80 needs filename at the end of the link.
+ $q=~s/\.rom$//i; #yealink v > 80 needs filename at the end of the link.
$rs = $rs->search({
version => { 'like' => $q . '%' },
});
@@ -1908,7 +1908,7 @@ sub dev_field_firmware_latest :Chained('dev_field_firmware_version_base') :PathP
$q = $c->req->params->{q};
}
if(defined $q) {
- $q=~s/\.rom$//i; #yealink v > 80 needs filename at the end of the link.
+ $q=~s/\.rom$//i; #yealink v > 80 needs filename at the end of the link.
$rs = $rs->search({
version => { 'like' => $q . '%' },
});
@@ -1928,6 +1928,88 @@ sub dev_field_firmware_latest :Chained('dev_field_firmware_version_base') :PathP
}
+sub devices_preferences_list :Chained('devmod_base') :PathPart('preferences') :CaptureArgs(0) {
+ my ($self, $c) = @_;
+
+ my $dev_pref_rs = $c->model('DB')
+ ->resultset('voip_preferences')
+ ->search({
+ 'device.id' => $c->stash->{devmod}->id,
+ },{
+ prefetch => {'voip_dev_preferences' => 'device'},
+ });
+ my %pref_values;
+ foreach my $value($dev_pref_rs->all) {
+ $pref_values{$value->attribute} =
+ [ map {$_->value} $value->voip_dev_preferences->all ];
+ }
+ my $pref_values = \%pref_values;
+
+ #my $dev_pref_rs = NGCP::Panel::Utils::Preferences::get_preferences_rs(
+ # c => $c,
+ # type => 'dev',
+ # id => $c->stash->{devmod}->id,
+ #);
+ #my $pref_values = get_inflated_columns_all($dev_pref_rs,'hash' => 'attribute', 'column' => 'value', 'force_array' => 1);
+ #use Data::Dumper;
+ #$c->log->debug(Dumper(["pref_values",$pref_values]));
+
+ NGCP::Panel::Utils::Preferences::load_preference_list(
+ c => $c,
+ pref_values => $pref_values,
+ dev_pref => 1,
+ );
+
+ $c->stash(template => 'device/preferences.tt');
+ return;
+}
+
+sub devices_preferences_root :Chained('devices_preferences_list') :PathPart('') :Args(0) {
+ return;
+}
+
+sub devices_preferences_base :Chained('devices_preferences_list') :PathPart('') :CaptureArgs(1) {
+ my ($self, $c, $pref_id) = @_;
+
+ $c->stash->{preference_meta} = $c->model('DB')
+ ->resultset('voip_preferences')
+ ->search({
+ -or => ['voip_preferences_enums.dev_pref' => 1,
+ 'voip_preferences_enums.dev_pref' => undef],
+ },{
+ prefetch => 'voip_preferences_enums',
+ })
+ ->find({id => $pref_id});
+
+ $c->stash->{preference} = $c->model('DB')
+ ->resultset('voip_dev_preferences')
+ ->search({
+ 'attribute_id' => $pref_id,
+ 'device_id' => $c->stash->{devmod}->id,
+ });
+ return;
+}
+
+sub devices_preferences_edit :Chained('devices_preferences_base') :PathPart('edit') :Args(0) {
+ my ($self, $c) = @_;
+
+ $c->stash(edit_preference => 1);
+
+ my @enums = $c->stash->{preference_meta}
+ ->voip_preferences_enums
+ ->all;
+
+ my $pref_rs = $c->stash->{devmod}->voip_dev_preferences;
+ NGCP::Panel::Utils::Preferences::create_preference_form(
+ c => $c,
+ pref_rs => $pref_rs,
+ enums => \@enums,
+ base_uri => $c->uri_for_action('/device/devices_preferences_root', [@{ $c->req->captures }[0]] ),
+ edit_uri => $c->uri_for_action('/device/devices_preferences_edit', $c->req->captures ),
+ );
+ return;
+}
+
__PACKAGE__->meta->make_immutable;
1;
diff --git a/lib/NGCP/Panel/Role/API/Preferences.pm b/lib/NGCP/Panel/Role/API/Preferences.pm
index 6454b9f8ea..f568702f01 100644
--- a/lib/NGCP/Panel/Role/API/Preferences.pm
+++ b/lib/NGCP/Panel/Role/API/Preferences.pm
@@ -78,6 +78,8 @@ sub get_resource {
$prefs = $item->voip_contract_preferences->search(
{ location_id => $c->request->param('location_id') || undef },
undef);
+ } elsif($type eq "pbxdevicemodels") {
+ $prefs = $item->voip_dev_preferences;
}
$prefs = $prefs->search({
}, {
@@ -231,6 +233,9 @@ sub get_resource {
} elsif($type eq "peerings") {
$resource->{peering_id} = int($item->id);
$resource->{id} = int($item->id);
+ } elsif($type eq "pbxdevicemodels") {
+ $resource->{device_id} = int($item->id);
+ $resource->{id} = int($item->id);
} elsif($type eq "contracts") {
$resource->{customer_id} = int($item->id);
$resource->{id} = int($item->id);
@@ -289,6 +294,20 @@ sub _item_rs {
} else {
return;
}
+ } elsif($type eq "pbxdevicemodels") {
+ if($c->user->roles eq "admin") {
+ $item_rs = $c->model('DB')->resultset('autoprov_devices');
+ #don't select images
+ #$item_rs = $c->model('DB')->resultset('autoprov_devices')->search_rs(
+ # undef,
+ # {
+ # 'columns'
+ # => [qw/id reseller_id type vendor model front_image_type mac_image_type num_lines bootstrap_method bootstrap_uri extensions_num/]
+ # }
+ #);
+ } else {
+ $item_rs = $c->model('DB')->resultset('autoprov_devices')->search({'reseller_id' => $c->user->reseller_id});
+ }
} elsif($type eq "contracts") {
if($c->user->roles eq "admin") {
$item_rs = $c->model('DB')->resultset('contracts')->search({
@@ -345,6 +364,12 @@ sub get_preference_rs {
attribute => $attr,
peer_host => $elem,
);
+ } elsif($type eq "pbxdevicemodels") {
+ $rs = NGCP::Panel::Utils::Preferences::get_dev_preference_rs(
+ c => $c,
+ attribute => $attr,
+ device => $elem,
+ );
} elsif($type eq "contracts") {
$rs = NGCP::Panel::Utils::Preferences::get_contract_preference_rs(
c => $c,
@@ -419,6 +444,16 @@ sub update_item {
undef);
$pref_type = 'contract_pref';
$reseller_id = $item->contact->reseller_id;
+ } elsif($type eq "pbxdevicemodels") {
+ delete $resource->{device_id};
+ delete $old_resource->{device_id};
+ delete $resource->{pbxdevicepreferences_id};
+ delete $old_resource->{pbxdevicepreferences_id};
+ $accessor = $item->id;
+ $elem = $item;
+ $full_rs = $elem->voip_dev_preferences->search_rs();
+ $pref_type = 'dev_pref';
+ $reseller_id = $item->reseller_id;
} else {
return;
}
diff --git a/lib/NGCP/Panel/Utils/Generic.pm b/lib/NGCP/Panel/Utils/Generic.pm
index df01fc680f..b177dae2cd 100644
--- a/lib/NGCP/Panel/Utils/Generic.pm
+++ b/lib/NGCP/Panel/Utils/Generic.pm
@@ -69,13 +69,18 @@ sub compare {
sub get_inflated_columns_all{
my ($rs,%params) = @_;
+ #params = {
+ # hash => result will be hash, with key, taken from the column with name, stored in this param,
+ # column => if hash param exists, value of the hash will be taken from the column with, stored in the param "column"
+ # force_array => hash values always will be an array ref
+ #}
my ($res);
$rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
if(my $hashkey_column = $params{hash}){
my %lres;
my $register_value = sub {
my($hash,$key,$value) = @_;
- if(exists $hash->{$key}){
+ if(exists $hash->{$key} || $params{force_array}){
if('ARRAY' eq ref $hash->{$key}){
push @{$hash->{$key}}, $value;
}else{
diff --git a/lib/NGCP/Panel/Utils/Preferences.pm b/lib/NGCP/Panel/Utils/Preferences.pm
index 0f7f680b7b..bda0f30887 100644
--- a/lib/NGCP/Panel/Utils/Preferences.pm
+++ b/lib/NGCP/Panel/Utils/Preferences.pm
@@ -36,6 +36,7 @@ sub load_preference_list {
my $pref_values = $params{pref_values};
my $peer_pref = $params{peer_pref};
my $dom_pref = $params{dom_pref};
+ my $dev_pref = $params{dev_pref};
my $prof_pref = $params{prof_pref};
my $usr_pref = $params{usr_pref};
my $contract_pref = $params{contract_pref};
@@ -60,6 +61,9 @@ sub load_preference_list {
$dom_pref ? ('voip_preferences.dom_pref' => 1,
-or => ['voip_preferences_enums.dom_pref' => 1,
'voip_preferences_enums.dom_pref' => undef]) : (),
+ $dev_pref ? ('voip_preferences.dev_pref' => 1,
+ -or => ['voip_preferences_enums.dev_pref' => 1,
+ 'voip_preferences_enums.dev_pref' => undef]) : (),
$prof_pref ? ('voip_preferences.prof_pref' => 1,
-or => ['voip_preferences_enums.prof_pref' => 1,
'voip_preferences_enums.prof_pref' => undef]) : (),
@@ -376,6 +380,14 @@ sub create_preference_form {
peer_host_id => $c->stash->{server}{id},
peer_host_name => $c->stash->{server}{name},
);
+ } elsif ($c->stash->{devmod}) {
+ %log_data = ( %log_data,
+ type => 'dev',
+ device_id => $c->stash->{devmod}->{id},
+ device_vendor => $c->stash->{devmod}->{vendor},
+ device_model => $c->stash->{devmod}->{model},
+ reseller_id => $c->stash->{devmod}->{reseller_id},
+ );
}
if($posted && $form->validated) {
@@ -442,7 +454,7 @@ sub create_preference_form {
$c->response->redirect($base_uri);
return 1;
}
- } elsif ($attribute eq "man_allowed_ips") {
+ } elsif ($attribute eq "man_allowed_ips") {
unless(validate_ipnet($form->field($attribute))) {
goto OUT;
}
@@ -847,6 +859,37 @@ sub get_usr_preferences_rs {
return $pref_rs;
}
+sub get_preferences_rs {
+ my %params = @_;
+
+ my $c = $params{c};
+ my $preferences_type = $params{type};
+ my $attribute = $params{attribute};
+ my $item_id = $params{id};
+ my $schema = $params{schema} // $c->model('DB');
+
+ my %config = (
+ 'usr' => [qw/voip_usr_preferences usr_pref subscriber_id/],
+ 'dom' => [qw/voip_dom_preferences dom_pref domain_id/],
+ 'prof' => [qw/voip_prof_preferences prof_pref profile_id/],
+ 'peer' => [qw/voip_peer_preferences peer_pref peer_host_id/],
+ 'dev' => [qw/voip_dev_preferences dev_pref device_id/],
+ 'contract' => [qw/voip_contract_preferences contract_pref contract_id/],
+ 'contract_location' => [qw/voip_contract_preferences contract_location_pref location_id/],
+ );
+ my $pref_rs = $schema->resultset($config{$preferences_type}->[0])->search({
+ 'attribute.'.$config{$preferences_type}->[1] => 1,
+ $attribute ? ( 'attribute.attribute' => (('ARRAY' eq ref $attribute) ? { '-in' => $attribute } : $attribute ) ) : () ,
+ $item_id ? ('me.'.$config{$preferences_type}->[2] => $item_id) : (),
+ },{
+ '+select' => ['attribute.attribute'],
+ '+as' => ['attribute'],
+ 'join' => 'attribute',
+ });
+
+ return $pref_rs;
+}
+
sub get_usr_preference_rs {
my %params = @_;
@@ -921,7 +964,21 @@ sub get_peer_preference_rs {
peer_host_id => $host->id,
});
}
+sub get_dev_preference_rs {
+ my %params = @_;
+
+ my $c = $params{c};
+ my $attribute = $params{attribute};
+ my $device = $params{device};
+ my $preference = $c->model('DB')->resultset('voip_preferences')->find({
+ attribute => $attribute, 'dev_pref' => 1,
+ });
+ return unless($preference);
+ return $preference->voip_dev_preferences->search_rs({
+ device_id => $device->id,
+ });
+}
sub get_contract_preference_rs {
my %params = @_;
diff --git a/share/templates/device/list.tt b/share/templates/device/list.tt
index cc8e78baa0..610a323b2b 100644
--- a/share/templates/device/list.tt
+++ b/share/templates/device/list.tt
@@ -122,6 +122,7 @@ $( document ).ready(function() {
helper.dt_buttons = helper.dt_buttons.merge([
{ name = c.loc('Delete'), uri = "/device/model/'+full.id+'/delete", class = 'btn-small btn-secondary', icon = 'icon-trash' },
{ name = c.loc('Edit'), uri = "/device/model/'+full.id+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' },
+ { name = c.loc('Preferences'), uri = "/device/model/'+full.id+'/preferences", class = 'btn-small btn-primary', icon = 'icon-list' },
]);
END;
diff --git a/share/templates/device/preferences.tt b/share/templates/device/preferences.tt
new file mode 100644
index 0000000000..538a06d2a4
--- /dev/null
+++ b/share/templates/device/preferences.tt
@@ -0,0 +1,22 @@
+[% site_config.title = c.loc('Device model "[_1]" for reseller #[_2] - Preferences', devmod.vendor _ " " _ devmod.model, devmod.reseller_id) -%]
+
+[%
+ helper.messages = messages;
+
+ helper.edit_preference = edit_preference;
+ helper.preference = preference;
+ helper.preference_meta = preference_meta;
+ helper.preference_values = preference_values;
+ helper.pref_groups = pref_groups;
+ helper.form = form;
+ helper.base_uri = c.uri_for_action("/device/devices_preferences_root", [c.req.captures.0]);
+
+ helper.top_buttons = [
+ { name = c.loc('Back'), uri = c.uri_for(""), icon = 'icon-arrow-left' },
+ ];
+
+ PROCESS 'helpers/pref_table.tt';
+%]
+
+
+[% # vim: set tabstop=4 syntax=html expandtab: -%]
diff --git a/t/api-rest/api-preferences.t b/t/api-rest/api-preferences.t
index 00c7360aee..365abbf179 100644
--- a/t/api-rest/api-preferences.t
+++ b/t/api-rest/api-preferences.t
@@ -23,6 +23,7 @@ $fake_data->set_data_from_script({
subscriber_id => sub { return shift->get_id('subscribers',@_); },
domain_id => sub { return shift->get_id('domains',@_); },
profile_id => sub { return shift->get_id('subscriberprofiles',@_); },
+ pbxdevice_id => sub { return shift->get_id('pbxdevicemodels',@_); },
rewriteruleset_id => sub { return shift->get_id('rewriterulesets',@_); },
soundset_id => sub { return shift->get_id('soundsets',@_); },
@@ -35,8 +36,8 @@ $fake_data->set_data_from_script({
$test_machine->DATA_ITEM_STORE($fake_data->process('preferences'));
$test_machine->form_data_item( );
-my @apis = qw/subscriber domain peeringserver customer profile/;
-#my @apis = qw/peeringserver/;
+my @apis = qw/subscriber domain peeringserver customer profile pbxdevice/;
+#my @apis = qw/pbxdevice/;
foreach my $api (@apis){
my $preferences_old;
diff --git a/t/api-rest/api-root.t b/t/api-rest/api-root.t
index 4d7f3062a4..758c150f8e 100644
--- a/t/api-rest/api-root.t
+++ b/t/api-rest/api-root.t
@@ -95,6 +95,8 @@ $ua->credentials($netloc, "api_admin_http", $user, $pass);
pbxdevicefirmwares => 1,
pbxdevicemodelimages => 1,
pbxdevicemodels => 1,
+ pbxdevicepreferencedefs => 1,
+ pbxdevicepreferences => 1,
pbxdeviceprofiles => 1,
pbxdevices => 1,
peeringgroups => 1,