You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ngcp-panel/lib/NGCP/Panel/Role/API/PbxDeviceModels.pm

253 lines
8.5 KiB

package NGCP::Panel::Role::API::PbxDeviceModels;
use parent qw/NGCP::Panel::Role::API/;
use Sipwise::Base;
use NGCP::Panel::Utils::Generic qw(:all);
use HTTP::Status qw(:constants);
use NGCP::Panel::Form;
use NGCP::Panel::Utils::Device;
use NGCP::Panel::Utils::DeviceBootstrap;
use Data::Dumper;
use boolean qw(true);
use JSON qw();
use File::Type;
sub item_name{
return 'pbxdevicemodels';
}
sub resource_name{
return 'pbxdevicemodels';
}
sub dispatch_path{
return '/api/pbxdevicemodels/';
}
sub relation{
return 'http://purl.org/sipwise/ngcp-api/#rel-pbxdevicemodels';
}
sub config_allowed_roles {
return {
'Default' => [qw/admin reseller subscriberadmin subscriber/],
#GET will use default
'POST' => [qw/admin reseller/],
'PUT' => [qw/admin reseller/],
'PATCH' => [qw/admin reseller/],
};
}
sub hal_links{
my($self, $c, $item, $resource, $form) = @_;
return [
NGCP::Panel::Utils::DataHalLink->new(relation => "ngcp:pbxdevicefirmwares", href => sprintf("/api/pbxdevicefirmwares/?device_id=%d", $item->id)),
];
}
sub get_form {
my ($self, $c) = @_;
#use_fields_for_input_without_param
return (NGCP::Panel::Form::get("NGCP::Panel::Form::Device::ModelAPI", $c));
}
sub _item_rs {
my ($self, $c) = @_;
my $item_rs = $c->model('DB')->resultset('autoprov_devices')
->search_rs(undef,{ prefetch => {autoprov_device_line_ranges => 'annotations'} });
if ($c->user->roles eq "admin") {
} elsif ($c->user->roles eq "reseller") {
$item_rs = $item_rs->search({ reseller_id => $c->user->reseller_id });
} elsif ($c->user->roles eq "subscriberadmin" || $c->user->roles eq "subscriber") {
my $reseller_id = $c->user->contract->contact->reseller_id;
return unless $reseller_id;
$item_rs = $item_rs->search({
reseller_id => $reseller_id,
});
}
return $item_rs;
}
sub resource_from_item {
my ($self, $c, $item) = @_;
my %resource = $item->get_inflated_columns;
delete $resource{front_image};
delete $resource{mac_image};
my ($form,$form_exceptions) = $self->get_form($c);
return unless $self->validate_form(
c => $c,
form => $form,
resource => \%resource,
run => 0,
exceptions => $form_exceptions,
);
foreach my $field (qw/reseller_id id extensions_num/){
$resource{$field} = int($item->$field // 0);
}
foreach my $field (qw/linerange connectable_models/){
$resource{$field} = [];
}
foreach my $range($item->autoprov_device_line_ranges->all) {
$self->process_range( \%resource, $range );
}
NGCP::Panel::Utils::DeviceBootstrap::devmod_sync_parameters_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) ];
}else{
# we don't need show possible extensions - we will show their ranges
# add ranges of the possible extensions
foreach my $extension_link ($item->autoprov_extensions_link->all){
my $extension = $extension_link->extension;
push @{$resource{connectable_models}}, $extension->id;
foreach my $range($extension->autoprov_device_line_ranges->all) {
$self->process_range( \%resource, $range, sub {
my $r = shift;
$r->{extension_range} = $extension->id;
} );#
}
}
}
return \%resource;
}
sub pre_process_form_resource{
my($self,$c, $item, $old_resource, $resource, $form, $process_extras) = @_;
#API form doesn't consider default value somehow
$resource->{type} //= 'phone';
}
sub process_form_resource{
my($self,$c, $item, $old_resource, $resource, $form, $process_extras) = @_;
$resource->{type} //= 'phone';
my $reseller_id = delete $resource->{reseller_id};
if($c->user->roles eq "admin") {
} elsif($c->user->roles eq "reseller") {
$reseller_id = $c->user->reseller_id;
}
$resource->{reseller_id} = $reseller_id;
my $ft = File::Type->new();
if($resource->{front_image}) {
my $front_image = delete $resource->{front_image};
$resource->{front_image} = $front_image->slurp;
$resource->{front_image_type} = $ft->mime_type($resource->{front_image});
}
if($resource->{mac_image}) {
my $front_image = delete $resource->{mac_image};
$resource->{mac_image} = $front_image->slurp;
$resource->{mac_image_type} = $ft->mime_type($resource->{mac_image});
}
return $resource;
}
sub check_resource{
my($self, $c, $item, $old_resource, $resource, $form, $process_extras) = @_;
my $schema = $c->model('DB');
my $reseller = $c->model('DB')->resultset('resellers')->find($resource->{reseller_id});
unless($reseller) {
$c->log->error("invalid reseller_id '".((defined $resource->{reseller_id})?$resource->{reseller_id} : "undefined")."', does not exist");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid reseller_id, does not exist");
return;
}
my $linerange = $resource->{linerange};
unless(ref $linerange eq "ARRAY") {
$c->log->error("linerange must be array");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid linerange parameter, must be array");
return;
}
foreach my $range(@{ $linerange }) {
unless(ref $range eq "HASH") {
$c->log->error("all elements in linerange must be hashes, but this is " . ref $range . ": " . Dumper $range);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid range definition inside linerange parameter, all must be hash");
return;
}
foreach my $elem(qw/can_private can_shared can_blf keys/) {
unless(exists $range->{$elem}) {
$c->log->error("missing mandatory attribute '$elem' in a linerange element");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid range definition inside linerange parameter, missing attribute '$elem'");
return;
}
}
unless(ref $range->{keys} eq "ARRAY") {
$c->log->error("linerange.keys must be array");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid linerange.keys parameter, must be array");
#last? not next?
return;
}
foreach my $label(@{ $range->{keys} }) {
unless(ref $label eq "HASH") {
$c->log->error("all elements in linerange must be hashes, but this is " . ref $range . ": " . Dumper $range);
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid range definition inside linerange parameter, all must be hash");
return;
}
}
}
return 1;
}
sub check_duplicate{
my($self, $c, $item, $old_resource, $resource, $form, $process_extras) = @_;
my $schema = $c->model('DB');
my $existing_item = $c->model('DB')->resultset('autoprov_devices')->find({
reseller_id => $resource->{reseller_id},
vendor => $resource->{vendor},
model => $resource->{model},
});
if($existing_item && (!$item || $item->id != $existing_item->id)) {
$c->log->error("device model with vendor '$$resource{vendor}' and model '$$resource{model}'already exists for reseller_id '$$resource{reseller_id}'");
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Device model already exists for this reseller");
return;
}
return 1;
}
sub update_item_model {
my ($self, $c, $item, $old_resource, $resource, $form, $process_extras) = @_;
NGCP::Panel::Utils::Device::store_and_process_device_model($c, $item, $resource);
return $item;
}
sub process_range {
my($self, $resource, $range, $process_range_cb ) = @_;
my $r = { $range->get_inflated_columns };
foreach my $f(qw/device_id num_lines/) {
delete $r->{$f};
}
$r->{id} = int($r->{id});
foreach my $f(qw/can_private can_shared can_blf/) {
$r->{$f} = $r->{$f} ? JSON::true : JSON::false;
}
$r->{keys} = [];
foreach my $key($range->annotations->all) {
push @{ $r->{keys} }, {
x => int($key->x),
y => int($key->y),
labelpos => $key->position,
};
}
$r->{num_lines} = @{ $r->{keys} };
( ( defined $process_range_cb ) && ( 'CODE' eq ref $process_range_cb ) ) and $process_range_cb->($r);
push @{ $resource->{linerange} }, $r;
}
1;
# vim: set tabstop=4 expandtab: