MT#10537 API: own/other logic for calllist item

changes/55/555/6
Andreas Granig 11 years ago
parent e28726c1c3
commit 266e8e7f3e

@ -47,6 +47,15 @@ class_has 'query_params' => (
},
},
},
{
param => 'alias_field',
description => 'Set this parameter for example to "gpp0" if you store alias numbers in the gpp0 preference and want to have that value shown as other CLI for calls from or to such a local subscriber.',
query => {
# handled directly in role
first => sub {},
second => sub {},
},
},
{
param => 'status',
description => 'Filter for calls with a specific status. One of "ok", "busy", "noanswer", "cancel", "offline", "timeout", "other".',
@ -153,26 +162,8 @@ sub GET :Allow {
my $rows = $c->request->params->{rows} // 10;
my $schema = $c->model('DB');
{
my $sub;
if($c->user->roles ne "subscriber") {
unless($c->req->param('subscriber_id')) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Mandatory parameter 'subscriber_id' missing in request");
last;
}
$sub = $schema->resultset('voip_subscribers')->find($c->req->param('subscriber_id'));
unless($sub) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
last;
}
if(($c->user->roles eq "subscriberadmin" && $sub->contract_id != $c->user->account_id) ||
($c->user->roles eq "reseller" && $sub->contract->contact->reseller_id != $c->user->reseller_id)) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
last;
}
} else {
$sub = $c->user->voip_subscriber;
}
my $sub = $self->get_subscriber($c, $schema);
last unless $sub;
my $items = $self->item_rs($c);
(my $total_count, $items) = $self->paginate_order_collection($c, $items);
my (@embedded, @links);
@ -181,7 +172,7 @@ sub GET :Allow {
push @embedded, $self->hal_from_item($c, $item, $sub, $form);
push @links, Data::HAL::Link->new(
relation => 'ngcp:'.$self->resource_name,
href => sprintf('/%s%d', $c->request->path, $item->id),
href => sprintf('/%s%d?subscriber_id=%d', $c->request->path, $item->id, $sub->id),
);
}
push @links,
@ -192,7 +183,7 @@ sub GET :Allow {
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', $c->request->path, $page, $rows));
Data::HAL::Link->new(relation => 'self', href => sprintf('/%s?page=%s&rows=%s&subscriber_id=%d', $c->request->path, $page, $rows, $sub->id));
if(($total_count / $rows) > $page ) {
push @links, Data::HAL::Link->new(relation => 'next', href => sprintf('/%s?page=%d&rows=%d', $c->request->path, $page + 1, $rows));
}

@ -0,0 +1,94 @@
package NGCP::Panel::Controller::API::CallListsItem;
use Sipwise::Base;
use namespace::sweep;
use HTTP::Headers qw();
use HTTP::Status qw(:constants);
use MooseX::ClassAttribute qw(class_has);
use NGCP::Panel::Utils::DateTime;
use NGCP::Panel::Utils::ValidateJSON qw();
use Path::Tiny qw(path);
use Safe::Isa qw($_isa);
BEGIN { extends 'Catalyst::Controller::ActionRole'; }
require Catalyst::ActionRole::ACL;
require Catalyst::ActionRole::HTTPMethods;
require Catalyst::ActionRole::RequireSSL;
with 'NGCP::Panel::Role::API::CallLists';
class_has('resource_name', is => 'ro', default => 'calllists');
class_has('dispatch_path', is => 'ro', default => '/api/calllists/');
class_has('relation', is => 'ro', default => 'http://purl.org/sipwise/ngcp-api/#rel-calllists');
__PACKAGE__->config(
action => {
map { $_ => {
ACLDetachTo => '/api/root/invalid_user',
AllowedRole => [qw/admin reseller subscriberadmin subscriber/],
Args => 1,
Does => [qw(ACL RequireSSL)],
Method => $_,
Path => __PACKAGE__->dispatch_path,
} } @{ __PACKAGE__->allowed_methods }
},
action_roles => [qw(HTTPMethods)],
);
sub auto :Private {
my ($self, $c) = @_;
$self->set_body($c);
$self->log_request($c);
}
sub GET :Allow {
my ($self, $c, $id) = @_;
{
my $schema = $c->model('DB');
last unless $self->valid_id($c, $id);
my $sub = $self->get_subscriber($c, $schema);
last unless $sub;
my $item = $self->item_by_id($c, $id);
last unless $self->resource_exists($c, calllist => $item);
my $hal = $self->hal_from_item($c, $item, $sub);
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 => $allowed_methods->join(', '),
Accept_Patch => 'application/json-patch+json',
));
$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);
}
# vim: set tabstop=4 expandtab:

@ -22,6 +22,15 @@ has_field 'direction' => (
},
);
has_field 'own_cli' => (
type => 'Text',
required => 1,
element_attr => {
rel => ['tooltip'],
title => ['The CLI of the own party.']
},
);
has_field 'other_cli' => (
type => 'Text',
required => 1,
@ -101,6 +110,15 @@ has_field 'customer_free_time' => (
},
);
has_field 'intra_customer' => (
type => 'Boolean',
required => 1,
element_attr => {
rel => ['tooltip'],
title => ['Whether it is a call between subscribers of one single customer.']
},
);
1;
# vim: set tabstop=4 expandtab:

@ -74,7 +74,7 @@ sub hal_from_item {
),
Data::HAL::Link->new(relation => 'collection', href => sprintf("/api/%s/", $self->resource_name)),
Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
Data::HAL::Link->new(relation => 'self', href => sprintf("%s%d", $self->dispatch_path, $item->id)),
Data::HAL::Link->new(relation => 'self', href => sprintf("%s%d?subscriber_id=%d", $self->dispatch_path, $item->id, $sub->id)),
# todo: customer can be in source_account_id or destination_account_id
# Data::HAL::Link->new(relation => 'ngcp:customers', href => sprintf("/api/customers/%d", $item->source_customer_id)),
],
@ -103,15 +103,86 @@ sub resource_from_item {
pattern => '%F %T',
);
my $intra = 0;
if($item->source_user_id && $item->source_account_id == $item->destination_account_id) {
$resource->{intra_customer} = JSON::true;
$intra = 1;
} else {
$resource->{intra_customer} = JSON::false;
$intra = 0;
}
$resource->{direction} = $sub->uuid eq $item->source_user_id ?
"out" : "in";
$resource->{other_cli} = $resource->{direction} eq "out" ?
$item->destination_user_in : $item->source_cli;
my ($src_sub, $dst_sub);
if($item->source_subscriber && $item->source_subscriber->provisioning_voip_subscriber) {
$src_sub = $item->source_subscriber->provisioning_voip_subscriber;
}
if($item->destination_subscriber && $item->destination_subscriber->provisioning_voip_subscriber) {
$dst_sub = $item->destination_subscriber->provisioning_voip_subscriber;
}
my ($own_normalize, $other_normalize);
if($resource->{direction} eq "out") {
# for pbx out calls, use extension as own cli
if($src_sub && $src_sub->pbx_extension) {
$resource->{own_cli} = $src_sub->pbx_extension;
} else {
$resource->{own_cli} = $item->source_cli;
$own_normalize = 1;
}
# for intra pbx out calls, use extension as other cli
if($intra && $dst_sub && $dst_sub->pbx_extension) {
$resource->{other_cli} = $dst_sub->pbx_extension;
# if there is an alias field (e.g. gpp0), use this
} elsif($item->destination_account_id && $c->req->param('alias_field')) {
my $alias = $item->get_column('destination_'.$c->req->param('alias_field'));
$c->log->error("+++++++++++++++++ alias_field=".$c->req->param('alias_field'));
$c->log->error("+++++++++++++++++ destination_alias_field=".($alias // '<null>'));
$resource->{other_cli} = $alias // $item->destination_user_in;
$other_normalize = 1;
} else {
$resource->{other_cli} = $item->destination_user_in;
$other_normalize = 1;
}
} else {
# for pbx in calls, use extension as own cli
if($dst_sub && $dst_sub->pbx_extension) {
$resource->{own_cli} = $dst_sub->pbx_extension;
} else {
$resource->{own_cli} = $item->destination_user_in;
$own_normalize = 1;
}
# for intra pbx in calls, use extension as other cli
if($intra && $src_sub && $src_sub->pbx_extension) {
$resource->{other_cli} = $src_sub->pbx_extension;
# if there is an alias field (e.g. gpp0), use this
} elsif($item->source_account_id && $c->req->param('alias_field')) {
my $alias = $item->get_column('source_'.$c->req->param('alias_field'));
$resource->{other_cli} = $alias // $item->source_cli;
$other_normalize = 1;
} else {
$resource->{other_cli} = $item->source_cli;
$other_normalize = 1;
}
}
if($resource->{own_cli} !~ /^\d+$/) {
$resource->{own_cli} .= '@'.$sub->domain->domain;
} elsif($own_normalize) {
$resource->{own_cli} = NGCP::Panel::Utils::Subscriber::apply_rewrite(
c => $c, subscriber => $sub,
number => $resource->{own_cli}, direction => "caller_out"
);
}
if($resource->{direction} eq "in" && $item->source_clir) {
$resource->{other_cli} = undef;
} elsif($resource->{other_cli} !~ /^\d+$/) {
$resource->{other_cli} .= '@'.$item->destination_domain_in;
} else {
$resource->{other_cli} .= '@'. ($resource->{direction} eq "in" ? $item->destination_domain_in : $sub->domain->domain);
} elsif($other_normalize) {
$resource->{other_cli} = NGCP::Panel::Utils::Subscriber::apply_rewrite(
c => $c, subscriber => $sub,
number => $resource->{other_cli}, direction => "caller_out"
@ -136,5 +207,30 @@ sub item_by_id {
return $item_rs->find($id);
}
sub get_subscriber {
my ($self, $c, $schema) = @_;
my $sub;
if($c->user->roles ne "subscriber") {
unless($c->req->param('subscriber_id')) {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Mandatory parameter 'subscriber_id' missing in request");
return;
}
$sub = $schema->resultset('voip_subscribers')->find($c->req->param('subscriber_id'));
unless($sub) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
if(($c->user->roles eq "subscriberadmin" && $sub->contract_id != $c->user->account_id) ||
($c->user->roles eq "reseller" && $sub->contract->contact->reseller_id != $c->user->reseller_id)) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
} else {
$sub = $c->user->voip_subscriber;
}
return $sub;
}
1;
# vim: set tabstop=4 expandtab:

@ -44,6 +44,19 @@ sub new_local {
);
}
# convert seconds to 'HH:MM:SS' format
sub sec_to_hms
{
use integer;
local $_ = shift;
my ($h, $m, $s);
$s = sprintf("%02d", $_ % 60); $_ /= 60;
$m = sprintf("%02d", $_ % 60); $_ /= 60;
$h = $_;
return "$h:$m:$s";
}
1;
# vim: set tabstop=4 expandtab:

Loading…
Cancel
Save