* rtcengine related logic and apps is now removed * remove /api/rtcapps endpoint * remove /api/rtcnetworks endpoint * remove rtcengine relations from resellers such as enable_rtc flags * remove rtcengine related API tests * remove rtcengine and comx related libraries * remove csc webphone ui app * remove webrtc related selenium tests * remove rtcengine flags from /api/capabilities Change-Id: I83a4b0457fac2e0df23d267f8dbc82841dfb3001mr11.0
parent
9d7990ef47
commit
d3dc152cdc
@ -1,86 +0,0 @@
|
|||||||
package NGCP::Panel::Controller::API::RtcApps;
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
sub allowed_methods{
|
|
||||||
return [qw/GET OPTIONS HEAD/];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub api_description {
|
|
||||||
return 'Show a collection of RTC apps, belonging to a specific reseller.';
|
|
||||||
};
|
|
||||||
|
|
||||||
sub query_params {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::RtcApps/;
|
|
||||||
|
|
||||||
sub resource_name{
|
|
||||||
return 'rtcapps';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub dispatch_path{
|
|
||||||
return '/api/rtcapps/';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub relation{
|
|
||||||
return 'http://purl.org/sipwise/ngcp-api/#rel-rtcapps';
|
|
||||||
}
|
|
||||||
|
|
||||||
__PACKAGE__->set_config({
|
|
||||||
allowed_roles => [qw/admin reseller/],
|
|
||||||
});
|
|
||||||
|
|
||||||
sub GET :Allow {
|
|
||||||
my ($self, $c) = @_;
|
|
||||||
my $page = $c->request->params->{page} // 1;
|
|
||||||
my $rows = $c->request->params->{rows} // 10;
|
|
||||||
{
|
|
||||||
my $resellers = $self->item_rs($c);
|
|
||||||
(my $total_count, $resellers, my $resellers_rows) = $self->paginate_order_collection($c, $resellers);
|
|
||||||
my (@embedded, @links);
|
|
||||||
for my $reseller (@$resellers_rows) {
|
|
||||||
push @embedded, $self->hal_from_item($c, $reseller);
|
|
||||||
push @links, Data::HAL::Link->new(
|
|
||||||
relation => 'ngcp:'.$self->resource_name,
|
|
||||||
href => sprintf('%s%d', $self->dispatch_path, $reseller->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/'),
|
|
||||||
$self->collection_nav_links($c, $page, $rows, $total_count, $c->request->path, $c->request->query_params);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,194 +0,0 @@
|
|||||||
package NGCP::Panel::Controller::API::RtcAppsItem;
|
|
||||||
use NGCP::Panel::Utils::Generic qw(:all);
|
|
||||||
|
|
||||||
use Sipwise::Base;
|
|
||||||
|
|
||||||
use Data::HAL qw();
|
|
||||||
use Data::HAL::Link qw();
|
|
||||||
use HTTP::Headers qw();
|
|
||||||
use HTTP::Status qw(:constants);
|
|
||||||
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/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::RtcApps/;
|
|
||||||
|
|
||||||
sub resource_name{
|
|
||||||
return 'rtcapps';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub dispatch_path{
|
|
||||||
return '/api/rtcapps/';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub relation{
|
|
||||||
return 'http://purl.org/sipwise/ngcp-api/#rel-rtcapps';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journal_query_params {
|
|
||||||
my($self,$query_params) = @_;
|
|
||||||
return $self->get_journal_query_params($query_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
__PACKAGE__->set_config({
|
|
||||||
allowed_roles => {
|
|
||||||
Default => [qw/admin reseller/],
|
|
||||||
Journal => [qw/admin reseller/],
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sub GET :Allow {
|
|
||||||
my ($self, $c, $id) = @_;
|
|
||||||
{
|
|
||||||
last unless $self->valid_id($c, $id);
|
|
||||||
my $item = $self->item_by_id($c, $id);
|
|
||||||
last unless $self->resource_exists($c, reseller => $item);
|
|
||||||
|
|
||||||
my $hal = $self->hal_from_item($c, $item);
|
|
||||||
|
|
||||||
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"|r
|
|
||||||
=~ s/rel=self/rel="item self"/r;
|
|
||||||
} $hal->http_headers),
|
|
||||||
), $hal->as_json);
|
|
||||||
$c->response->headers($response->headers);
|
|
||||||
$c->response->body($response->content);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub PUT :Allow {
|
|
||||||
my ($self, $c, $id) = @_;
|
|
||||||
my $schema = $c->model('DB');
|
|
||||||
my $guard = $schema->txn_scope_guard;
|
|
||||||
{
|
|
||||||
my $preference = $self->require_preference($c);
|
|
||||||
last unless $preference;
|
|
||||||
|
|
||||||
my $reseller = $self->item_by_id($c, $id);
|
|
||||||
last unless $self->resource_exists($c, reseller => $reseller);
|
|
||||||
my $resource = $self->get_valid_put_data(
|
|
||||||
c => $c,
|
|
||||||
id => $id,
|
|
||||||
media_type => 'application/json',
|
|
||||||
);
|
|
||||||
last unless $resource;
|
|
||||||
|
|
||||||
my $form = $self->get_form($c);
|
|
||||||
my $old_resource = $self->hal_from_item($c, $reseller, 1)->resource;
|
|
||||||
$reseller = $self->update_item($c, $reseller, $old_resource, $resource, $form);
|
|
||||||
last unless $reseller;
|
|
||||||
|
|
||||||
my $hal = $self->hal_from_item($c, $reseller);
|
|
||||||
last unless $self->add_update_journal_item_hal($c,{ hal => $hal, id => $reseller->id });
|
|
||||||
|
|
||||||
$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, $reseller);
|
|
||||||
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 PATCH :Allow {
|
|
||||||
my ($self, $c, $id) = @_;
|
|
||||||
my $schema = $c->model('DB');
|
|
||||||
my $guard = $schema->txn_scope_guard;
|
|
||||||
{
|
|
||||||
my $preference = $self->require_preference($c);
|
|
||||||
last unless $preference;
|
|
||||||
|
|
||||||
my $reseller = $self->item_by_id($c, $id);
|
|
||||||
last unless $self->resource_exists($c, reseller => $reseller);
|
|
||||||
my $json = $self->get_valid_patch_data(
|
|
||||||
c => $c,
|
|
||||||
id => $id,
|
|
||||||
media_type => 'application/json-patch+json',
|
|
||||||
ops => ["add", "replace", "copy", "remove"],
|
|
||||||
);
|
|
||||||
last unless $json;
|
|
||||||
|
|
||||||
my $form = $self->get_form($c);
|
|
||||||
my $old_resource = $self->hal_from_item($c, $reseller, 1)->resource;
|
|
||||||
my $resource = $self->apply_patch($c, $old_resource, $json);
|
|
||||||
last unless $resource;
|
|
||||||
|
|
||||||
$reseller = $self->update_item($c, $reseller, $old_resource, $resource, $form);
|
|
||||||
last unless $reseller;
|
|
||||||
|
|
||||||
my $hal = $self->hal_from_item($c, $reseller);
|
|
||||||
last unless $self->add_update_journal_item_hal($c,{ hal => $hal, id => $reseller->id });
|
|
||||||
|
|
||||||
$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, $reseller);
|
|
||||||
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 item_base_journal :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_item_base_journal(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journals_get :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journals_get(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journalsitem_get :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journalsitem_get(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journals_options :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journals_options(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journalsitem_options :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journalsitem_options(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journals_head :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journals_head(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journalsitem_head :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journalsitem_head(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,86 +0,0 @@
|
|||||||
package NGCP::Panel::Controller::API::RtcNetworks;
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
sub allowed_methods{
|
|
||||||
return [qw/GET OPTIONS HEAD/];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub api_description {
|
|
||||||
return 'Show a collection of RTC networks, belonging to a specific reseller.';
|
|
||||||
};
|
|
||||||
|
|
||||||
sub query_params {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::RtcNetworks/;
|
|
||||||
|
|
||||||
sub resource_name{
|
|
||||||
return 'rtcnetworks';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub dispatch_path{
|
|
||||||
return '/api/rtcnetworks/';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub relation{
|
|
||||||
return 'http://purl.org/sipwise/ngcp-api/#rel-rtcnetworks';
|
|
||||||
}
|
|
||||||
|
|
||||||
__PACKAGE__->set_config({
|
|
||||||
allowed_roles => [qw/admin reseller/],
|
|
||||||
});
|
|
||||||
|
|
||||||
sub GET :Allow {
|
|
||||||
my ($self, $c) = @_;
|
|
||||||
my $page = $c->request->params->{page} // 1;
|
|
||||||
my $rows = $c->request->params->{rows} // 10;
|
|
||||||
{
|
|
||||||
my $resellers = $self->item_rs($c);
|
|
||||||
(my $total_count, $resellers, my $resellers_rows) = $self->paginate_order_collection($c, $resellers);
|
|
||||||
my (@embedded, @links);
|
|
||||||
for my $subscriber (@$resellers_rows) {
|
|
||||||
push @embedded, $self->hal_from_item($c, $subscriber);
|
|
||||||
push @links, Data::HAL::Link->new(
|
|
||||||
relation => 'ngcp:'.$self->resource_name,
|
|
||||||
href => sprintf('%s%d', $self->dispatch_path, $subscriber->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/'),
|
|
||||||
$self->collection_nav_links($c, $page, $rows, $total_count, $c->request->path, $c->request->query_params);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,194 +0,0 @@
|
|||||||
package NGCP::Panel::Controller::API::RtcNetworksItem;
|
|
||||||
use NGCP::Panel::Utils::Generic qw(:all);
|
|
||||||
|
|
||||||
use Sipwise::Base;
|
|
||||||
|
|
||||||
use Data::HAL qw();
|
|
||||||
use Data::HAL::Link qw();
|
|
||||||
use HTTP::Headers qw();
|
|
||||||
use HTTP::Status qw(:constants);
|
|
||||||
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/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::RtcNetworks/;
|
|
||||||
|
|
||||||
sub resource_name{
|
|
||||||
return 'rtcnetworks';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub dispatch_path{
|
|
||||||
return '/api/rtcnetworks/';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub relation{
|
|
||||||
return 'http://purl.org/sipwise/ngcp-api/#rel-rtcnetworks';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journal_query_params {
|
|
||||||
my($self,$query_params) = @_;
|
|
||||||
return $self->get_journal_query_params($query_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
__PACKAGE__->set_config({
|
|
||||||
allowed_roles => {
|
|
||||||
Default => [qw/admin reseller/],
|
|
||||||
Journal => [qw/admin reseller/],
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sub GET :Allow {
|
|
||||||
my ($self, $c, $id) = @_;
|
|
||||||
{
|
|
||||||
last unless $self->valid_id($c, $id);
|
|
||||||
my $item = $self->item_by_id($c, $id);
|
|
||||||
last unless $self->resource_exists($c, reseller => $item);
|
|
||||||
|
|
||||||
my $hal = $self->hal_from_item($c, $item);
|
|
||||||
|
|
||||||
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"|r
|
|
||||||
=~ s/rel=self/rel="item self"/r;
|
|
||||||
} $hal->http_headers),
|
|
||||||
), $hal->as_json);
|
|
||||||
$c->response->headers($response->headers);
|
|
||||||
$c->response->body($response->content);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub PUT :Allow {
|
|
||||||
my ($self, $c, $id) = @_;
|
|
||||||
my $schema = $c->model('DB');
|
|
||||||
my $guard = $schema->txn_scope_guard;
|
|
||||||
{
|
|
||||||
my $preference = $self->require_preference($c);
|
|
||||||
last unless $preference;
|
|
||||||
|
|
||||||
my $reseller = $self->item_by_id($c, $id);
|
|
||||||
last unless $self->resource_exists($c, reseller => $reseller);
|
|
||||||
my $resource = $self->get_valid_put_data(
|
|
||||||
c => $c,
|
|
||||||
id => $id,
|
|
||||||
media_type => 'application/json',
|
|
||||||
);
|
|
||||||
last unless $resource;
|
|
||||||
|
|
||||||
my $form = $self->get_form($c);
|
|
||||||
my $old_resource = $self->hal_from_item($c, $reseller, 1)->resource;
|
|
||||||
$reseller = $self->update_item($c, $reseller, $old_resource, $resource, $form);
|
|
||||||
last unless $reseller;
|
|
||||||
|
|
||||||
my $hal = $self->hal_from_item($c, $reseller);
|
|
||||||
last unless $self->add_update_journal_item_hal($c,{ hal => $hal, id => $reseller->id });
|
|
||||||
|
|
||||||
$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, $reseller);
|
|
||||||
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 PATCH :Allow {
|
|
||||||
my ($self, $c, $id) = @_;
|
|
||||||
my $schema = $c->model('DB');
|
|
||||||
my $guard = $schema->txn_scope_guard;
|
|
||||||
{
|
|
||||||
my $preference = $self->require_preference($c);
|
|
||||||
last unless $preference;
|
|
||||||
|
|
||||||
my $reseller = $self->item_by_id($c, $id);
|
|
||||||
last unless $self->resource_exists($c, reseller => $reseller);
|
|
||||||
my $json = $self->get_valid_patch_data(
|
|
||||||
c => $c,
|
|
||||||
id => $id,
|
|
||||||
media_type => 'application/json-patch+json',
|
|
||||||
ops => ["add", "replace", "copy", "remove"],
|
|
||||||
);
|
|
||||||
last unless $json;
|
|
||||||
|
|
||||||
my $form = $self->get_form($c);
|
|
||||||
my $old_resource = $self->hal_from_item($c, $reseller, 1)->resource;
|
|
||||||
my $resource = $self->apply_patch($c, $old_resource, $json);
|
|
||||||
last unless $resource;
|
|
||||||
|
|
||||||
$reseller = $self->update_item($c, $reseller, $old_resource, $resource, $form);
|
|
||||||
last unless $reseller;
|
|
||||||
|
|
||||||
my $hal = $self->hal_from_item($c, $reseller);
|
|
||||||
last unless $self->add_update_journal_item_hal($c,{ hal => $hal, id => $reseller->id });
|
|
||||||
|
|
||||||
$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, $reseller);
|
|
||||||
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 item_base_journal :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_item_base_journal(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journals_get :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journals_get(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journalsitem_get :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journalsitem_get(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journals_options :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journals_options(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journalsitem_options :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journalsitem_options(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journals_head :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journals_head(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journalsitem_head :Journal {
|
|
||||||
my $self = shift @_;
|
|
||||||
return $self->handle_journalsitem_head(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,147 +0,0 @@
|
|||||||
package NGCP::Panel::Controller::API::RtcSessions;
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sub api_description {
|
|
||||||
return 'Show a collection of RTC sessions, belonging to a specific subscriber.';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub allowed_methods{
|
|
||||||
return [qw/GET POST OPTIONS HEAD/];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub query_params {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::RtcSessions/;
|
|
||||||
|
|
||||||
sub resource_name{
|
|
||||||
return 'rtcsessions';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub dispatch_path{
|
|
||||||
return '/api/rtcsessions/';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub relation{
|
|
||||||
return 'http://purl.org/sipwise/ngcp-api/#rel-rtcsessions';
|
|
||||||
}
|
|
||||||
|
|
||||||
__PACKAGE__->set_config({
|
|
||||||
allowed_roles => [qw/admin reseller subscriber subscriberadmin/],
|
|
||||||
});
|
|
||||||
|
|
||||||
sub GET :Allow {
|
|
||||||
my ($self, $c) = @_;
|
|
||||||
my $page = $c->request->params->{page} // 1;
|
|
||||||
my $rows = $c->request->params->{rows} // 10;
|
|
||||||
{
|
|
||||||
my $subscribers = $self->item_rs($c);
|
|
||||||
(my $total_count, $subscribers, my $subscribers_rows) = $self->paginate_order_collection($c, $subscribers);
|
|
||||||
my (@embedded, @links);
|
|
||||||
for my $subscriber (@$subscribers_rows) {
|
|
||||||
my $hal = $self->hal_from_item($c, $subscriber);
|
|
||||||
next unless $hal;
|
|
||||||
push @embedded, $hal;
|
|
||||||
push @links, Data::HAL::Link->new(
|
|
||||||
relation => 'ngcp:'.$self->resource_name,
|
|
||||||
href => sprintf('%s%d', $self->dispatch_path, $subscriber->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/'),
|
|
||||||
$self->collection_nav_links($c, $page, $rows, $total_count, $c->request->path, $c->request->query_params);
|
|
||||||
|
|
||||||
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 POST :Allow {
|
|
||||||
my ($self, $c) = @_;
|
|
||||||
|
|
||||||
my $guard = $c->model('DB')->txn_scope_guard;
|
|
||||||
{
|
|
||||||
my $schema = $c->model('DB');
|
|
||||||
my $resource = $self->get_valid_post_data(
|
|
||||||
c => $c,
|
|
||||||
media_type => 'application/json',
|
|
||||||
);
|
|
||||||
last unless $resource;
|
|
||||||
|
|
||||||
if($c->user->roles eq "admin") {
|
|
||||||
} elsif($c->user->roles eq "reseller") {
|
|
||||||
$resource->{reseller_id} = $c->user->reseller_id; # TODO: ?
|
|
||||||
} else {
|
|
||||||
$resource->{subscriber_id} = $c->user->voip_subscriber->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $subscriber_item = $c->model('DB')->resultset('voip_subscribers')->search_rs({
|
|
||||||
id => $resource->{subscriber_id},
|
|
||||||
})->first;
|
|
||||||
|
|
||||||
unless ($subscriber_item) {
|
|
||||||
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Subscriber invalid or not found.");
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
|
|
||||||
# my $form = $self->get_form();
|
|
||||||
# $resource->{reseller_id} //= undef;
|
|
||||||
# last unless $self->validate_form(
|
|
||||||
# c => $c,
|
|
||||||
# resource => $resource,
|
|
||||||
# form => $form,
|
|
||||||
# );
|
|
||||||
|
|
||||||
my $session_item = NGCP::Panel::Utils::Rtc::create_rtc_session(
|
|
||||||
config => $c->config,
|
|
||||||
subscriber_item => $subscriber_item,
|
|
||||||
resource => $resource,
|
|
||||||
err_code => sub {
|
|
||||||
my ($msg, $debug) = @_;
|
|
||||||
$c->log->debug($debug) if $debug;
|
|
||||||
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, $msg);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
last unless $session_item;
|
|
||||||
|
|
||||||
$guard->commit;
|
|
||||||
|
|
||||||
$c->response->status(HTTP_CREATED);
|
|
||||||
$c->response->header(Location => sprintf('%s%d', $self->dispatch_path, $session_item->id));
|
|
||||||
$c->response->body(q());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,80 +0,0 @@
|
|||||||
package NGCP::Panel::Controller::API::RtcSessionsItem;
|
|
||||||
use NGCP::Panel::Utils::Generic qw(:all);
|
|
||||||
|
|
||||||
use Sipwise::Base;
|
|
||||||
|
|
||||||
|
|
||||||
use Data::HAL qw();
|
|
||||||
use Data::HAL::Link qw();
|
|
||||||
use HTTP::Headers qw();
|
|
||||||
use HTTP::Status qw(:constants);
|
|
||||||
|
|
||||||
require Catalyst::ActionRole::ACL;
|
|
||||||
require NGCP::Panel::Role::HTTPMethods;
|
|
||||||
require Catalyst::ActionRole::RequireSSL;
|
|
||||||
|
|
||||||
use parent qw/NGCP::Panel::Role::EntitiesItem NGCP::Panel::Role::API::RtcSessions/;
|
|
||||||
|
|
||||||
sub resource_name{
|
|
||||||
return 'rtcsessions';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub dispatch_path{
|
|
||||||
return '/api/rtcsessions/';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub relation{
|
|
||||||
return 'http://purl.org/sipwise/ngcp-api/#rel-rtcsessions';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub allowed_methods{
|
|
||||||
return [qw/GET OPTIONS HEAD/];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub journal_query_params {
|
|
||||||
my($self,$query_params) = @_;
|
|
||||||
return $self->get_journal_query_params($query_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
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/];
|
|
||||||
}
|
|
||||||
|
|
||||||
__PACKAGE__->set_config({
|
|
||||||
allowed_roles => {
|
|
||||||
Default => [qw/admin reseller subscriber subscriberadmin/],
|
|
||||||
Journal => [qw/admin reseller/],
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sub GET :Allow {
|
|
||||||
my ($self, $c, $id) = @_;
|
|
||||||
{
|
|
||||||
last unless $self->valid_id($c, $id);
|
|
||||||
my $item = $self->item_by_id($c, $id);
|
|
||||||
last unless $self->resource_exists($c, rtc_session => $item);
|
|
||||||
|
|
||||||
my $hal = $self->hal_from_item($c, $item);
|
|
||||||
|
|
||||||
unless ($hal) {
|
|
||||||
$c->log->error("Session not found. It may have expired.");
|
|
||||||
$self->error($c, HTTP_NOT_FOUND, "Session not found. It may have expired.");
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
|
|
||||||
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"|r
|
|
||||||
=~ s/rel=self/rel="item self"/r;
|
|
||||||
} $hal->http_headers),
|
|
||||||
), $hal->as_json);
|
|
||||||
$c->response->headers($response->headers);
|
|
||||||
$c->response->body($response->content);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,30 +0,0 @@
|
|||||||
package NGCP::Panel::Form::ResellerRtc;
|
|
||||||
|
|
||||||
use HTML::FormHandler::Moose;
|
|
||||||
extends 'NGCP::Panel::Form::Reseller';
|
|
||||||
|
|
||||||
use HTML::FormHandler::Widget::Block::Bootstrap;
|
|
||||||
|
|
||||||
has '+widget_wrapper' => ( default => 'Bootstrap' );
|
|
||||||
has_field 'submitid' => ( type => 'Hidden' );
|
|
||||||
sub build_render_list {[qw/submitid fields actions/]}
|
|
||||||
sub build_form_element_class { [qw/form-horizontal/] }
|
|
||||||
|
|
||||||
has_field 'enable_rtc' => (
|
|
||||||
type => 'Boolean',
|
|
||||||
required => 0,
|
|
||||||
default => 0,
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['Whether an RTC-entity should be created for this reseller.'],
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
has_block 'fields' => (
|
|
||||||
tag => 'div',
|
|
||||||
class => [qw/modal-body/],
|
|
||||||
render_list => [qw/contract name status enable_rtc/],
|
|
||||||
);
|
|
||||||
|
|
||||||
1;
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,22 +0,0 @@
|
|||||||
package NGCP::Panel::Form::Rtc::AppsAdmin;
|
|
||||||
|
|
||||||
use HTML::FormHandler::Moose;
|
|
||||||
extends 'NGCP::Panel::Form::Rtc::AppsReseller';
|
|
||||||
|
|
||||||
has_field 'reseller' => (
|
|
||||||
type => '+NGCP::Panel::Field::Reseller',
|
|
||||||
#validate_when_empty => 1,
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['The reseller id this app belong to.'],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
has_block 'fields' => (
|
|
||||||
tag => 'div',
|
|
||||||
class => [qw/modal-body/],
|
|
||||||
render_list => [qw/reseller rtc_user_id apps/],
|
|
||||||
);
|
|
||||||
|
|
||||||
1;
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,95 +0,0 @@
|
|||||||
package NGCP::Panel::Form::Rtc::AppsReseller;
|
|
||||||
use HTML::FormHandler::Moose;
|
|
||||||
use HTML::FormHandler::Widget::Block::Bootstrap;
|
|
||||||
extends 'HTML::FormHandler';
|
|
||||||
|
|
||||||
# with 'NGCP::Panel::Render::RepeatableJs'; # only used in API currently
|
|
||||||
|
|
||||||
has '+widget_wrapper' => ( default => 'Bootstrap' );
|
|
||||||
has_field 'submitid' => ( type => 'Hidden' );
|
|
||||||
sub build_render_list {return [qw/submitid fields actions/]}
|
|
||||||
sub build_form_element_class {return [qw(form-horizontal)]}
|
|
||||||
|
|
||||||
has_field 'rtc_user_id' => (
|
|
||||||
# readonly
|
|
||||||
type => 'Text',
|
|
||||||
required => 0,
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['ID in the backend RTC API (readonly).'],
|
|
||||||
},
|
|
||||||
readonly => 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
has_field 'apps' => (
|
|
||||||
type => 'Repeatable',
|
|
||||||
required => 0, #1,
|
|
||||||
#setup_for_js => 1,
|
|
||||||
do_wrapper => 1,
|
|
||||||
do_label => 0,
|
|
||||||
tags => {
|
|
||||||
controls_div => 1,
|
|
||||||
},
|
|
||||||
wrapper_class => [qw/hfh-rep/],
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['An array of objects with keys "name", "domain", "secret" and "api_key" to create RTC apps for this reseller'],
|
|
||||||
},
|
|
||||||
num_when_empty => 1,
|
|
||||||
add_extra => 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
has_field 'apps.domain' => (
|
|
||||||
type => 'Text',
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['Domain where the cdk is included.'],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
has_field 'apps.name' => (
|
|
||||||
type => 'Text',
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['Arbitrary text. Name of the app.'],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
has_field 'apps.secret' => (
|
|
||||||
type => 'Text',
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['The secret (readonly).'],
|
|
||||||
},
|
|
||||||
readonly => 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
has_field 'apps.api_key' => (
|
|
||||||
type => 'Text',
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['The API key (readonly).'],
|
|
||||||
},
|
|
||||||
readonly => 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
has_field 'save' => (
|
|
||||||
type => 'Submit',
|
|
||||||
value => 'Save',
|
|
||||||
element_class => [qw/btn btn-primary/],
|
|
||||||
label => '',
|
|
||||||
);
|
|
||||||
|
|
||||||
has_block 'fields' => (
|
|
||||||
tag => 'div',
|
|
||||||
class => [qw/modal-body/],
|
|
||||||
render_list => [qw/rtc_user_id apps/],
|
|
||||||
);
|
|
||||||
|
|
||||||
has_block 'actions' => (
|
|
||||||
tag => 'div',
|
|
||||||
class => [qw/modal-footer/],
|
|
||||||
render_list => [qw/save/],
|
|
||||||
);
|
|
||||||
|
|
||||||
1;
|
|
@ -1,22 +0,0 @@
|
|||||||
package NGCP::Panel::Form::Rtc::NetworksAdmin;
|
|
||||||
|
|
||||||
use HTML::FormHandler::Moose;
|
|
||||||
extends 'NGCP::Panel::Form::Rtc::NetworksReseller';
|
|
||||||
|
|
||||||
has_field 'reseller' => (
|
|
||||||
type => '+NGCP::Panel::Field::Reseller',
|
|
||||||
#validate_when_empty => 1,
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['The reseller id this networks belong to.'],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
has_block 'fields' => (
|
|
||||||
tag => 'div',
|
|
||||||
class => [qw/modal-body/],
|
|
||||||
render_list => [qw/reseller rtc_user_id networks/],
|
|
||||||
);
|
|
||||||
|
|
||||||
1;
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,90 +0,0 @@
|
|||||||
package NGCP::Panel::Form::Rtc::NetworksReseller;
|
|
||||||
use HTML::FormHandler::Moose;
|
|
||||||
use HTML::FormHandler::Widget::Block::Bootstrap;
|
|
||||||
extends 'HTML::FormHandler';
|
|
||||||
|
|
||||||
# with 'NGCP::Panel::Render::RepeatableJs'; # only used in API currently
|
|
||||||
|
|
||||||
has '+widget_wrapper' => ( default => 'Bootstrap' );
|
|
||||||
has_field 'submitid' => ( type => 'Hidden' );
|
|
||||||
sub build_render_list {return [qw/submitid fields actions/]}
|
|
||||||
sub build_form_element_class {return [qw(form-horizontal)]}
|
|
||||||
|
|
||||||
has_field 'rtc_user_id' => (
|
|
||||||
# readonly
|
|
||||||
type => 'Text',
|
|
||||||
required => 0,
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['ID in the backend RTC API (readonly).'],
|
|
||||||
},
|
|
||||||
readonly => 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
has_field 'networks' => (
|
|
||||||
type => 'Repeatable',
|
|
||||||
required => 0, #1,
|
|
||||||
setup_for_js => 1,
|
|
||||||
do_wrapper => 1,
|
|
||||||
do_label => 0,
|
|
||||||
tags => {
|
|
||||||
controls_div => 1,
|
|
||||||
},
|
|
||||||
wrapper_class => [qw/hfh-rep/],
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['An array of objects with keys "config", "connector" and "tag" to create RTC networks for this reseller'],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
# webrtc, conference, xmpp-connector, sip-connector, sipwise-connector
|
|
||||||
has_field 'networks.connector' => (
|
|
||||||
type => 'Select',
|
|
||||||
options => [
|
|
||||||
{ value => 'webrtc', label => 'webrtc' },
|
|
||||||
{ value => 'conference', label => 'conference' },
|
|
||||||
{ value => 'xmpp-connector', label => 'xmpp-connector' },
|
|
||||||
{ value => 'sip-connector', label => 'sip-connector' },
|
|
||||||
{ value => 'sipwise-connector', label => 'sipwise-connector' },
|
|
||||||
],
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['One of the available options. This defines, to which networks rtc subscribers will be able to connect to.'],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
has_field 'networks.tag' => (
|
|
||||||
type => 'Text',
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['An arbitrary name, to address that network instance'],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
has_field 'networks.config' => (
|
|
||||||
type => 'Compound', # Text
|
|
||||||
element_attr => {
|
|
||||||
rel => ['tooltip'],
|
|
||||||
title => ['An arbitrary hash of additional config contents; e.g. {"xms": false}'],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
has_field 'save' => (
|
|
||||||
type => 'Submit',
|
|
||||||
value => 'Save',
|
|
||||||
element_class => [qw/btn btn-primary/],
|
|
||||||
label => '',
|
|
||||||
);
|
|
||||||
|
|
||||||
has_block 'fields' => (
|
|
||||||
tag => 'div',
|
|
||||||
class => [qw/modal-body/],
|
|
||||||
render_list => [qw/rtc_user_id networks/],
|
|
||||||
);
|
|
||||||
|
|
||||||
has_block 'actions' => (
|
|
||||||
tag => 'div',
|
|
||||||
class => [qw/modal-footer/],
|
|
||||||
render_list => [qw/save/],
|
|
||||||
);
|
|
||||||
|
|
||||||
1;
|
|
@ -1,143 +0,0 @@
|
|||||||
package NGCP::Panel::Role::API::RtcApps;
|
|
||||||
use NGCP::Panel::Utils::Generic qw(:all);
|
|
||||||
|
|
||||||
use Sipwise::Base;
|
|
||||||
|
|
||||||
use parent 'NGCP::Panel::Role::API';
|
|
||||||
use boolean qw(true);
|
|
||||||
use Data::HAL qw();
|
|
||||||
use Data::HAL::Link qw();
|
|
||||||
use HTTP::Status qw(:constants);
|
|
||||||
use JSON::Types;
|
|
||||||
|
|
||||||
use NGCP::Panel::Utils::Subscriber;
|
|
||||||
use NGCP::Panel::Utils::Rtc;
|
|
||||||
|
|
||||||
sub get_form {
|
|
||||||
my ($self, $c) = @_;
|
|
||||||
|
|
||||||
return NGCP::Panel::Form::get("NGCP::Panel::Form::Rtc::AppsAdmin", $c);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub hal_from_item {
|
|
||||||
my ($self, $c, $item, $include_id) = @_;
|
|
||||||
|
|
||||||
my $resource = { reseller_id => $item->id };
|
|
||||||
if ($item->rtc_user) {
|
|
||||||
my $rtc_user_id = $item->rtc_user->rtc_user_id;
|
|
||||||
$resource->{rtc_user_id} = $rtc_user_id if $include_id;
|
|
||||||
$resource->{apps} = NGCP::Panel::Utils::Rtc::get_rtc_apps(
|
|
||||||
rtc_user_id => $rtc_user_id,
|
|
||||||
config => $c->config,
|
|
||||||
include_id => $include_id,
|
|
||||||
err_code => sub {
|
|
||||||
my $rtc_error = shift;
|
|
||||||
$c->log->warn($rtc_error);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
#for get=>put compatibility
|
|
||||||
if ('ARRAY' ne ref $resource->{apps}) {
|
|
||||||
$resource->{apps} = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
my $hal = Data::HAL->new(
|
|
||||||
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 => '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 => 'ngcp:resellers', href => sprintf("/api/resellers/%d", $item->id)),
|
|
||||||
Data::HAL::Link->new(relation => 'ngcp:resellers', href => sprintf("/api/rtcnetworks/%d", $item->id)),
|
|
||||||
$self->get_journal_relation_link($c, $item->id),
|
|
||||||
],
|
|
||||||
relation => 'ngcp:'.$self->resource_name,
|
|
||||||
);
|
|
||||||
|
|
||||||
my $form = $self->get_form($c);
|
|
||||||
unless ($include_id) {
|
|
||||||
return unless $self->validate_form(
|
|
||||||
c => $c,
|
|
||||||
form => $form,
|
|
||||||
resource => $resource,
|
|
||||||
run => 0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->expand_fields($c, $resource);
|
|
||||||
$hal->resource($resource);
|
|
||||||
return $hal;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _item_rs {
|
|
||||||
my ($self, $c) = @_;
|
|
||||||
|
|
||||||
my $item_rs;
|
|
||||||
$item_rs = $c->model('DB')->resultset('resellers')
|
|
||||||
->search_rs(undef, {
|
|
||||||
prefetch => 'rtc_user',
|
|
||||||
});
|
|
||||||
if($c->user->roles eq "admin") {
|
|
||||||
} elsif($c->user->roles eq "reseller") {
|
|
||||||
$item_rs = $item_rs->search({
|
|
||||||
id => $c->user->reseller_id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return $item_rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub item_by_id {
|
|
||||||
my ($self, $c, $id) = @_;
|
|
||||||
|
|
||||||
my $item_rs = $self->item_rs($c);
|
|
||||||
return $item_rs->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub update_item {
|
|
||||||
my ($self, $c, $item, $old_resource, $resource, $form) = @_;
|
|
||||||
|
|
||||||
my $reseller = $item;
|
|
||||||
|
|
||||||
if (ref $resource->{apps} ne "ARRAY") {
|
|
||||||
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid field 'apps'. Must be an array.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$form //= $self->get_form($c);
|
|
||||||
return unless $self->validate_form(
|
|
||||||
c => $c,
|
|
||||||
form => $form,
|
|
||||||
resource => $resource,
|
|
||||||
);
|
|
||||||
|
|
||||||
NGCP::Panel::Utils::Rtc::modify_rtc_apps(
|
|
||||||
old_resource => $old_resource,
|
|
||||||
resource => $resource,
|
|
||||||
config => $c->config,
|
|
||||||
reseller_item => $reseller,
|
|
||||||
err_code => sub {
|
|
||||||
my $rtc_error = shift;
|
|
||||||
$c->log->warn($rtc_error);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
} catch($e) {
|
|
||||||
$c->log->error("failed to update rtcapps: $e");
|
|
||||||
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update rtcapps.");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
return $reseller;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,142 +0,0 @@
|
|||||||
package NGCP::Panel::Role::API::RtcNetworks;
|
|
||||||
use NGCP::Panel::Utils::Generic qw(:all);
|
|
||||||
|
|
||||||
use Sipwise::Base;
|
|
||||||
|
|
||||||
use parent 'NGCP::Panel::Role::API';
|
|
||||||
use boolean qw(true);
|
|
||||||
use Data::HAL qw();
|
|
||||||
use Data::HAL::Link qw();
|
|
||||||
use HTTP::Status qw(:constants);
|
|
||||||
use JSON::Types;
|
|
||||||
|
|
||||||
use NGCP::Panel::Utils::Subscriber;
|
|
||||||
use NGCP::Panel::Utils::Rtc;
|
|
||||||
|
|
||||||
sub get_form {
|
|
||||||
my ($self, $c) = @_;
|
|
||||||
|
|
||||||
return NGCP::Panel::Form::get("NGCP::Panel::Form::Rtc::NetworksAdmin", $c);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub hal_from_item {
|
|
||||||
my ($self, $c, $item, $include_id) = @_;
|
|
||||||
|
|
||||||
my $resource = { reseller_id => $item->id };
|
|
||||||
if ($item->rtc_user) {
|
|
||||||
my $rtc_user_id = $item->rtc_user->rtc_user_id;
|
|
||||||
$resource->{rtc_user_id} = $rtc_user_id if $include_id;
|
|
||||||
$resource->{networks} = NGCP::Panel::Utils::Rtc::get_rtc_networks(
|
|
||||||
rtc_user_id => $rtc_user_id,
|
|
||||||
config => $c->config,
|
|
||||||
include_id => $include_id,
|
|
||||||
err_code => sub {
|
|
||||||
my ($msg, $debug) = @_;
|
|
||||||
$c->log->debug($debug) if $debug;
|
|
||||||
$c->log->warn($msg);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
#for get=>put compatibility
|
|
||||||
if ('ARRAY' ne ref $resource->{networks}) {
|
|
||||||
$resource->{networks} = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
my $hal = Data::HAL->new(
|
|
||||||
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 => '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 => 'ngcp:resellers', href => sprintf("/api/resellers/%d", $item->id)),
|
|
||||||
$self->get_journal_relation_link($c, $item->id),
|
|
||||||
],
|
|
||||||
relation => 'ngcp:'.$self->resource_name,
|
|
||||||
);
|
|
||||||
|
|
||||||
my $form = $self->get_form($c);
|
|
||||||
unless ($include_id) {
|
|
||||||
return unless $self->validate_form(
|
|
||||||
c => $c,
|
|
||||||
form => $form,
|
|
||||||
resource => $resource,
|
|
||||||
run => 0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->expand_fields($c, $resource);
|
|
||||||
$hal->resource($resource);
|
|
||||||
return $hal;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _item_rs {
|
|
||||||
my ($self, $c) = @_;
|
|
||||||
|
|
||||||
my $item_rs;
|
|
||||||
$item_rs = $c->model('DB')->resultset('resellers')
|
|
||||||
->search_rs(undef, {
|
|
||||||
prefetch => 'rtc_user',
|
|
||||||
});
|
|
||||||
if($c->user->roles eq "admin") {
|
|
||||||
} elsif($c->user->roles eq "reseller") {
|
|
||||||
$item_rs = $item_rs->search({
|
|
||||||
id => $c->user->reseller_id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return $item_rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub item_by_id {
|
|
||||||
my ($self, $c, $id) = @_;
|
|
||||||
|
|
||||||
my $item_rs = $self->item_rs($c);
|
|
||||||
return $item_rs->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub update_item {
|
|
||||||
my ($self, $c, $item, $old_resource, $resource, $form) = @_;
|
|
||||||
|
|
||||||
my $reseller = $item;
|
|
||||||
|
|
||||||
if (ref $resource->{networks} ne "ARRAY") {
|
|
||||||
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Invalid field 'networks'. Must be an array.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$form //= $self->get_form($c);
|
|
||||||
return unless $self->validate_form(
|
|
||||||
c => $c,
|
|
||||||
form => $form,
|
|
||||||
resource => $resource,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
NGCP::Panel::Utils::Rtc::modify_rtc_networks(
|
|
||||||
old_resource => $old_resource,
|
|
||||||
resource => $resource,
|
|
||||||
config => $c->config,
|
|
||||||
reseller_item => $reseller,
|
|
||||||
err_code => sub {
|
|
||||||
my ($msg, $debug) = @_;
|
|
||||||
$c->log->debug($debug) if $debug;
|
|
||||||
$c->log->warn($msg);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
} catch($e) {
|
|
||||||
$c->log->error("failed to update rtcnetworks: $e");
|
|
||||||
$self->error($c, HTTP_INTERNAL_SERVER_ERROR, "Failed to update rtcnetworks.");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
return $reseller;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,103 +0,0 @@
|
|||||||
package NGCP::Panel::Role::API::RtcSessions;
|
|
||||||
use NGCP::Panel::Utils::Generic qw(:all);
|
|
||||||
|
|
||||||
use Sipwise::Base;
|
|
||||||
|
|
||||||
use parent 'NGCP::Panel::Role::API';
|
|
||||||
|
|
||||||
use boolean qw(true);
|
|
||||||
use Data::HAL qw();
|
|
||||||
use Data::HAL::Link qw();
|
|
||||||
use HTTP::Status qw(:constants);
|
|
||||||
use JSON::Types;
|
|
||||||
|
|
||||||
use NGCP::Panel::Utils::Subscriber;
|
|
||||||
use NGCP::Panel::Utils::Rtc;
|
|
||||||
|
|
||||||
sub get_form {
|
|
||||||
my ($self) = @_;
|
|
||||||
|
|
||||||
#return NGCP::Panel::Form::get("NGCP::Panel::Form::Rtc::NetworksAdmin", $c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub hal_from_item {
|
|
||||||
my ($self, $c, $item) = @_;
|
|
||||||
|
|
||||||
my $resource = {
|
|
||||||
subscriber_id => $item->subscriber->voip_subscriber->id, # this may be confusing but we store the provisioning-subscriber-id but show the billing one
|
|
||||||
rtc_network_tag => $item->rtc_network_tag,
|
|
||||||
};
|
|
||||||
|
|
||||||
my $rtc_session = NGCP::Panel::Utils::Rtc::get_rtc_session(
|
|
||||||
config => $c->config,
|
|
||||||
item => $item,
|
|
||||||
err_code => sub {
|
|
||||||
my ($msg, $debug) = @_;
|
|
||||||
$c->log->debug($debug) if $debug;
|
|
||||||
$c->log->warn($msg);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
if ($rtc_session) {
|
|
||||||
$resource->{rtc_browser_token} = $rtc_session->{data}{token};
|
|
||||||
$resource->{rtc_app_name} = $rtc_session->{data}{app}{name} if $rtc_session->{data}{app}{name};
|
|
||||||
} else {
|
|
||||||
# here either delete our DB entry, or recreate it accordingly
|
|
||||||
$item->delete;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $hal = Data::HAL->new(
|
|
||||||
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 => '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 => 'ngcp:subscribers', href => sprintf("/api/subscribers/%d", $item->subscriber->voip_subscriber->id)),
|
|
||||||
$self->get_journal_relation_link($c, $item->id),
|
|
||||||
],
|
|
||||||
relation => 'ngcp:'.$self->resource_name,
|
|
||||||
);
|
|
||||||
|
|
||||||
$self->expand_fields($c, $resource);
|
|
||||||
$hal->resource($resource);
|
|
||||||
return $hal;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub item_rs {
|
|
||||||
my ($self, $c) = @_;
|
|
||||||
|
|
||||||
my $item_rs;
|
|
||||||
$item_rs = $c->model('DB')->resultset('rtc_session');
|
|
||||||
if($c->user->roles eq "admin") {
|
|
||||||
} elsif($c->user->roles eq "reseller") {
|
|
||||||
$item_rs = $item_rs->search({
|
|
||||||
'contact.reseller_id' => $c->user->reseller_id,
|
|
||||||
},{
|
|
||||||
join => {subscriber => { voip_subscriber => { contract => 'contact' }}},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$item_rs = $item_rs->search({
|
|
||||||
'subscriber.id' => $c->user->id,
|
|
||||||
},{
|
|
||||||
join => 'subscriber',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return $item_rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub item_by_id {
|
|
||||||
my ($self, $c, $id) = @_;
|
|
||||||
|
|
||||||
my $item_rs = $self->item_rs($c);
|
|
||||||
return $item_rs->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,306 +0,0 @@
|
|||||||
package NGCP::Panel::Utils::ComxAPIClient;
|
|
||||||
|
|
||||||
use warnings;
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Moo;
|
|
||||||
# use Digest::MD5 qw/md5_hex/;
|
|
||||||
# use HTTP::Tiny;
|
|
||||||
# use Storable qw/freeze/;
|
|
||||||
use Types::Standard qw(Int HashRef);
|
|
||||||
# with 'Role::REST::Client';
|
|
||||||
use LWP::UserAgent;
|
|
||||||
use JSON qw/decode_json encode_json/;
|
|
||||||
|
|
||||||
has 'ua' => ( is => 'rw', default => sub {
|
|
||||||
return LWP::UserAgent->new(
|
|
||||||
ssl_opts => { verify_hostname => 0, SSL_verify_mode => 0 },
|
|
||||||
timeout => 20,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
has 'host' => (is => 'rw', default => 'https://www.api-cdk.tld:8191');
|
|
||||||
|
|
||||||
has 'login_status' => (is => 'rw',
|
|
||||||
#isa => 'HTTP::Response',
|
|
||||||
default => sub {return {};},
|
|
||||||
);
|
|
||||||
|
|
||||||
# returns appid or 0
|
|
||||||
sub login {
|
|
||||||
my ( $self, $username, $password, $netloc ) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
$netloc //= $self->host =~ s!^https?://(.*:[0-9]*)(/.*$|$)!$1!r;
|
|
||||||
$ua->credentials($netloc, "rtcengine", $username, $password);
|
|
||||||
my $resp = $ua->get($self->host . '/users');
|
|
||||||
$self->login_status( $self->_create_response($resp) );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
# outdated: only one account (with one network) for the session
|
|
||||||
sub create_session_and_account {
|
|
||||||
my ($self, $appid, $network_tag, $identifier, $access_token, $owner, $account_config) = @_;
|
|
||||||
|
|
||||||
my $session = $self->create_session($appid, $owner);
|
|
||||||
$session->{data}{accounts} = [] if($session->{data});
|
|
||||||
|
|
||||||
my $account = $self->create_account(
|
|
||||||
$session->{data}{id},
|
|
||||||
$owner,
|
|
||||||
$identifier,
|
|
||||||
$network_tag,
|
|
||||||
$access_token,
|
|
||||||
$account_config );
|
|
||||||
push @{ $session->{data}{accounts} }, $account->{data};
|
|
||||||
|
|
||||||
return $session;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub create_session {
|
|
||||||
my ($self, $appid, $owner) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
my $session_content = encode_json({
|
|
||||||
app => $appid,
|
|
||||||
owner => $owner,
|
|
||||||
});
|
|
||||||
my $session = $self->_create_response(
|
|
||||||
$ua->post($self->host . '/sessions', 'Content-Type' => 'application/json', Content => $session_content),
|
|
||||||
);
|
|
||||||
return $session;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub create_account {
|
|
||||||
my ($self, $session_id, $owner, $identifier, $network_tag, $access_token, $account_config) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
|
|
||||||
my $account_content = encode_json({
|
|
||||||
session => $session_id,
|
|
||||||
network => $network_tag,
|
|
||||||
identifier => $identifier,
|
|
||||||
accessToken => $access_token,
|
|
||||||
owner => $owner,
|
|
||||||
$account_config ? (config => encode_json($account_config)) : (),
|
|
||||||
});
|
|
||||||
my $account = $self->_create_response(
|
|
||||||
$ua->post($self->host . '/accounts', 'Content-Type' => 'application/json', Content => $account_content),
|
|
||||||
);
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub create_network {
|
|
||||||
my ($self, $tag, $connector, $config, $owner) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
my $network_content = encode_json({
|
|
||||||
tag => $tag,
|
|
||||||
connector => $connector,
|
|
||||||
config => encode_json($config),
|
|
||||||
owner => $owner,
|
|
||||||
});
|
|
||||||
my $network = $self->_create_response(
|
|
||||||
$ua->post($self->host . '/networks', 'Content-Type' => 'application/json', Content => $network_content),
|
|
||||||
);
|
|
||||||
return $network;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub create_user {
|
|
||||||
my ($self, $email, $password) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
my $user_content = encode_json({
|
|
||||||
email => $email,
|
|
||||||
password => $password,
|
|
||||||
});
|
|
||||||
my $user = $self->_create_response(
|
|
||||||
$ua->post($self->host . '/users', 'Content-Type' => 'application/json', Content => $user_content),
|
|
||||||
);
|
|
||||||
return $user;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub delete_network {
|
|
||||||
my ($self, $network_id) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
$network_id //= "";
|
|
||||||
my $resp;
|
|
||||||
$resp = $ua->delete($self->host . "/networks/id/$network_id");
|
|
||||||
return $self->_create_response($resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub delete_user {
|
|
||||||
my ($self, $user_id) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
$user_id //= "";
|
|
||||||
my $resp;
|
|
||||||
$resp = $ua->delete($self->host . "/users/id/$user_id");
|
|
||||||
return $self->_create_response($resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub delete_app {
|
|
||||||
my ($self, $app_id) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
$app_id //= "";
|
|
||||||
my $resp;
|
|
||||||
$resp = $ua->delete($self->host . "/apps/id/$app_id");
|
|
||||||
return $self->_create_response($resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub create_app {
|
|
||||||
my ($self, $name, $domain, $owner) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
my $app_content = encode_json({
|
|
||||||
name => $name,
|
|
||||||
domain => $domain,
|
|
||||||
owner => $owner,
|
|
||||||
});
|
|
||||||
my $app = $self->_create_response(
|
|
||||||
$ua->post($self->host . '/apps', 'Content-Type' => 'application/json', Content => $app_content),
|
|
||||||
);
|
|
||||||
return $app;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_sessions {
|
|
||||||
my ($self, $max_rows) = @_;
|
|
||||||
my $sessions = $self->_resolve_collection_fast( '/sessions', $max_rows );
|
|
||||||
if ('ARRAY' eq ref $sessions->{data} && @{ $sessions->{data} }) {
|
|
||||||
for my $session (@{ $sessions->{data} }) {
|
|
||||||
$session->{accounts} = $self->_resolve_collection_fast( $session->{accounts}{href} );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $sessions;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_session {
|
|
||||||
my ($self, $session_id) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
|
|
||||||
my $session = $self->_create_response(
|
|
||||||
$ua->get($self->host . "/sessions/id/$session_id"),
|
|
||||||
);
|
|
||||||
if ($session->{data}) {
|
|
||||||
my ($app_id) = $session->{data}{app}{href} =~ m!apps/id/(.*)$!;
|
|
||||||
my $item_res = $ua->get($self->host . "/apps/id/$app_id");
|
|
||||||
my $item_data = decode_json($item_res->content);
|
|
||||||
$session->{data}{app} = $item_data;
|
|
||||||
}
|
|
||||||
return $session;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub delete_all_sessions {
|
|
||||||
my ($self) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
my $resp;
|
|
||||||
for my $session_data ($self->get_sessions->{data}) {
|
|
||||||
my $session_id = $session_data->{id};
|
|
||||||
$resp = $ua->delete($self->host . "/sessions/id/$session_id");
|
|
||||||
last if $resp->code >= 300;
|
|
||||||
}
|
|
||||||
return $resp;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_users {
|
|
||||||
my ($self, $max_rows) = @_;
|
|
||||||
my $users = $self->_resolve_collection_fast( '/users', $max_rows );
|
|
||||||
return $users;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_apps_by_user_id {
|
|
||||||
my ($self, $user_id) = @_;
|
|
||||||
my $apps = $self->_resolve_collection_fast( "/users/id/$user_id/apps" );
|
|
||||||
return $apps;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_networks {
|
|
||||||
my ($self) = @_;
|
|
||||||
my $networks = $self->_resolve_collection_fast( '/networks' );
|
|
||||||
return $networks;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_networks_by_user_id {
|
|
||||||
my ($self, $user_id) = @_;
|
|
||||||
my $networks = $self->_resolve_collection_fast( "/users/id/$user_id/networks" );
|
|
||||||
return $networks;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _resolve_collection {
|
|
||||||
my ($self, $bare_url, $max_rows) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
my $rel_url = $self->_strip_host( $bare_url );
|
|
||||||
my $res = $ua->get($self->host . $rel_url);
|
|
||||||
my @result;
|
|
||||||
return {code => $res->code, response => $res} unless $res->code == 200;
|
|
||||||
my $collection = JSON::decode_json($res->content);
|
|
||||||
return {code => $res->code, response => $res,
|
|
||||||
error_detail => 'could not decode_json'} unless $collection;
|
|
||||||
my $item_res;
|
|
||||||
for my $item (@{ $collection->{items} }) {
|
|
||||||
last if (defined $max_rows && $max_rows-- <= 0);
|
|
||||||
my $url = $self->_strip_host( $item->{href} );
|
|
||||||
$item_res = $ua->get($self->host . $url);
|
|
||||||
my $item_data = decode_json($item_res->content);
|
|
||||||
push @result, $item_data;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
response => $item_res, # latest response
|
|
||||||
code => $item_res->code,
|
|
||||||
data => \@result,
|
|
||||||
total_count => scalar(@result),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _resolve_collection_fast {
|
|
||||||
my ($self, $bare_url, $max_rows) = @_;
|
|
||||||
my $ua = $self->ua;
|
|
||||||
my $rel_url = $self->_strip_host( $bare_url );
|
|
||||||
$rel_url =
|
|
||||||
$rel_url .
|
|
||||||
( ($rel_url =~ m/\?/) ? '&' : '?' ) .
|
|
||||||
'expand=true';
|
|
||||||
my $res = $ua->get($self->host . $rel_url);
|
|
||||||
my @result;
|
|
||||||
return $self->_create_response($res) unless $res->code == 200;
|
|
||||||
my $collection = JSON::decode_json($res->content);
|
|
||||||
return {code => $res->code, response => $res,
|
|
||||||
error_detail => 'could not decode_json'} unless $collection;
|
|
||||||
if ('HASH' eq ref $collection) { # everything ok
|
|
||||||
return {
|
|
||||||
response => $res,
|
|
||||||
code => $res->code,
|
|
||||||
data => $collection->{items},
|
|
||||||
total_count => $collection->{total} // (scalar @{ $collection->{items} }),
|
|
||||||
};
|
|
||||||
} else { # unknown error
|
|
||||||
return {
|
|
||||||
response => $res,
|
|
||||||
code => $res->code,
|
|
||||||
data => $collection,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _strip_host {
|
|
||||||
my ($self, $url) = @_;
|
|
||||||
my $url_orig = $self->host;
|
|
||||||
my $url_noip = $url_orig =~ s!:\d+!!r;
|
|
||||||
return $url =~ s!$url_orig|$url_noip!!r;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _create_response {
|
|
||||||
my ($self, $res) = @_;
|
|
||||||
my $data;
|
|
||||||
my $debug;
|
|
||||||
if ($res->is_success && $res->content) {
|
|
||||||
$data = decode_json($res->content);
|
|
||||||
} else {
|
|
||||||
$debug = "RTC response: " . $res->decoded_content
|
|
||||||
. ", RTC request: " . $res->request->as_string;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
code => $res->code,
|
|
||||||
data => $data,
|
|
||||||
response => $res,
|
|
||||||
$debug ? (debug => $debug) : (),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,747 +0,0 @@
|
|||||||
package NGCP::Panel::Utils::Rtc;
|
|
||||||
|
|
||||||
use warnings;
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use JSON qw//;
|
|
||||||
use UUID;
|
|
||||||
|
|
||||||
use NGCP::Panel::Utils::ComxAPIClient;
|
|
||||||
use NGCP::Panel::Utils::Generic qw/compare/;
|
|
||||||
|
|
||||||
sub modify_reseller_rtc {
|
|
||||||
my %params = @_;
|
|
||||||
my ($old_resource, $resource, $config, $reseller_item, $err_code) =
|
|
||||||
@params{qw/old_resource resource config reseller_item err_code/};
|
|
||||||
|
|
||||||
if (!defined $err_code || ref $err_code ne 'CODE') {
|
|
||||||
$err_code = sub { return 0; };
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!defined $old_resource) && (defined $resource)) { # newly created reseller
|
|
||||||
|
|
||||||
# 1. enable_rtc is off -> do nothing
|
|
||||||
if (!$resource->{enable_rtc}) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_create_rtc_user(
|
|
||||||
resource => $resource,
|
|
||||||
config => $config,
|
|
||||||
reseller_item => $reseller_item,
|
|
||||||
err_code => $err_code);
|
|
||||||
|
|
||||||
} elsif ((defined $old_resource) && (defined $resource)) {
|
|
||||||
|
|
||||||
if($old_resource->{status} ne 'terminated' &&
|
|
||||||
$resource->{status} eq 'terminated' &&
|
|
||||||
$old_resource->{enable_rtc}) { # just terminated
|
|
||||||
|
|
||||||
$resource->{enable_rtc} = JSON::false;
|
|
||||||
_delete_rtc_user(
|
|
||||||
config => $config,
|
|
||||||
reseller_item => $reseller_item,
|
|
||||||
err_code => $err_code);
|
|
||||||
|
|
||||||
} elsif ($old_resource->{enable_rtc} &&
|
|
||||||
!$resource->{enable_rtc}) { # disable rtc
|
|
||||||
|
|
||||||
_delete_rtc_user(
|
|
||||||
config => $config,
|
|
||||||
reseller_item => $reseller_item,
|
|
||||||
err_code => $err_code);
|
|
||||||
} elsif (!$old_resource->{enable_rtc} &&
|
|
||||||
$resource->{enable_rtc} &&
|
|
||||||
$resource->{status} ne 'terminated') { # enable rtc
|
|
||||||
|
|
||||||
_create_rtc_user(
|
|
||||||
resource => $resource,
|
|
||||||
config => $config,
|
|
||||||
reseller_item => $reseller_item,
|
|
||||||
err_code => $err_code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _create_rtc_user {
|
|
||||||
my %params = @_;
|
|
||||||
my ($resource, $config, $reseller_item, $err_code) =
|
|
||||||
@params{qw/resource config reseller_item err_code/};
|
|
||||||
|
|
||||||
my $rtc_networks = $resource->{rtc_networks} // [];
|
|
||||||
if ('ARRAY' ne (ref $rtc_networks)) {
|
|
||||||
$rtc_networks = [$rtc_networks];
|
|
||||||
}
|
|
||||||
|
|
||||||
# 2. create user w reseller-name and reseller-name _ "pass"
|
|
||||||
my $reseller_name = $resource->{name} =~ s/\s+//rg;
|
|
||||||
|
|
||||||
my $comx = NGCP::Panel::Utils::ComxAPIClient->new(
|
|
||||||
host => $config->{rtc}{schema}.'://'.
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port}.
|
|
||||||
$config->{rtc}{path},
|
|
||||||
);
|
|
||||||
$comx->login(
|
|
||||||
$config->{rtc}{user},
|
|
||||||
$config->{rtc}{pass},
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port});
|
|
||||||
if ($comx->login_status->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Rtc Login failed. Check config settings. Status code: ' . $comx->login_status->{code}, $comx->login_status->{debug});
|
|
||||||
}
|
|
||||||
my ($uuid_bin, $uuid);
|
|
||||||
UUID::generate($uuid_bin);
|
|
||||||
UUID::unparse($uuid_bin, $uuid);
|
|
||||||
my $rand = get_random(10, $err_code);
|
|
||||||
return unless $rand;
|
|
||||||
my $pass = unpack("H*", $rand);
|
|
||||||
my $user = $comx->create_user(
|
|
||||||
$uuid . '@ngcp.local',
|
|
||||||
$pass,
|
|
||||||
);
|
|
||||||
if ($user->{code} != 201) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Creating rtc user failed. Error code: ' . $user->{code}, $user->{debug});
|
|
||||||
}
|
|
||||||
|
|
||||||
# 3. create relation in our db
|
|
||||||
$reseller_item->create_related('rtc_user', {
|
|
||||||
rtc_user_id => $user->{data}{id},
|
|
||||||
});
|
|
||||||
|
|
||||||
# 4. create related app
|
|
||||||
my $app = $comx->create_app(
|
|
||||||
$uuid . '_default_app',
|
|
||||||
$uuid . '.sipwise.local',
|
|
||||||
$user->{data}{id},
|
|
||||||
);
|
|
||||||
if ($app->{code} != 201) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Creating rtc app failed. Error code: ' . $app->{code}, $app->{debug});
|
|
||||||
}
|
|
||||||
|
|
||||||
# 5. create related networks
|
|
||||||
for my $n (@{ $rtc_networks }) {
|
|
||||||
my $connector;
|
|
||||||
if ($n =~ m/^(sip|xmpp)$/) {
|
|
||||||
$connector = "$n-connector";
|
|
||||||
} else {
|
|
||||||
$connector = $n;
|
|
||||||
}
|
|
||||||
my $n_response = $comx->create_network(
|
|
||||||
$n,
|
|
||||||
$connector,
|
|
||||||
{xms => JSON::false},
|
|
||||||
$user->{data}{id},
|
|
||||||
);
|
|
||||||
if ($n_response->{code} != 201) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Creating rtc network failed. Error code: ' . $n_response->{code}, $n_response->{debug});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _delete_rtc_user {
|
|
||||||
my %params = @_;
|
|
||||||
my ($config, $reseller_item, $err_code) =
|
|
||||||
@params{qw/config reseller_item err_code/};
|
|
||||||
|
|
||||||
my $comx = NGCP::Panel::Utils::ComxAPIClient->new(
|
|
||||||
host => $config->{rtc}{schema}.'://'.
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port}.
|
|
||||||
$config->{rtc}{path},
|
|
||||||
);
|
|
||||||
$comx->login(
|
|
||||||
$config->{rtc}{user},
|
|
||||||
$config->{rtc}{pass},
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port});
|
|
||||||
if ($comx->login_status->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Rtc Login failed. Check config settings. Status code: ' . $comx->login_status->{code}, $comx->login_status->{debug});
|
|
||||||
}
|
|
||||||
|
|
||||||
my $rtc_user = $reseller_item->rtc_user;
|
|
||||||
if (!defined $rtc_user) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'No rtc user found in db for this reseller.');
|
|
||||||
}
|
|
||||||
# app and networks are deleted automatically
|
|
||||||
my $delete_resp = $comx->delete_user(
|
|
||||||
$rtc_user->rtc_user_id,
|
|
||||||
);
|
|
||||||
if ($delete_resp->{code} == 200) {
|
|
||||||
$rtc_user->delete;
|
|
||||||
} else {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Deleting rtc user failed. Error code: ' . $delete_resp->{code}, $delete_resp->{debug});
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_rtc_apps {
|
|
||||||
my %params = @_;
|
|
||||||
my ($rtc_user_id, $config, $include_id, $err_code) =
|
|
||||||
@params{qw/rtc_user_id config include_id err_code/};
|
|
||||||
|
|
||||||
if (!defined $err_code || ref $err_code ne 'CODE') {
|
|
||||||
$err_code = sub { return 0; };
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comx = NGCP::Panel::Utils::ComxAPIClient->new(
|
|
||||||
host => $config->{rtc}{schema}.'://'.
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port}.
|
|
||||||
$config->{rtc}{path},
|
|
||||||
);
|
|
||||||
$comx->login(
|
|
||||||
$config->{rtc}{user},
|
|
||||||
$config->{rtc}{pass},
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port});
|
|
||||||
if ($comx->login_status->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Rtc Login failed. Check config settings.');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $apps_resp = $comx->get_apps_by_user_id($rtc_user_id);
|
|
||||||
my $apps = $apps_resp->{data};
|
|
||||||
unless (defined $apps && 'ARRAY' eq ref $apps && @{ $apps }) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Fetching apps failed. Code: ' . $apps_resp->{code});
|
|
||||||
}
|
|
||||||
|
|
||||||
my $res = [map {{
|
|
||||||
domain =>$_->{domain},
|
|
||||||
name => $_->{name},
|
|
||||||
secret => $_->{secret},
|
|
||||||
api_key => $_->{apiKey}, # todo: which spelling do we use?
|
|
||||||
$include_id ? (id => $_->{id}) : (),
|
|
||||||
}} @{ $apps }];
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub modify_rtc_apps {
|
|
||||||
my %params = @_;
|
|
||||||
my ($old_resource, $resource, $config, $reseller_item, $err_code) =
|
|
||||||
@params{qw/old_resource resource config reseller_item err_code/};
|
|
||||||
#TODO: stub, to be done
|
|
||||||
|
|
||||||
if (!defined $err_code || ref $err_code ne 'CODE') {
|
|
||||||
$err_code = sub { return 0; };
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!defined $old_resource) || (!defined $resource)) { # can only modify (no create/delete) the whole resource
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Cannot Modify rtc app. Old or new resource missing.');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comx = NGCP::Panel::Utils::ComxAPIClient->new(
|
|
||||||
host => $config->{rtc}{schema}.'://'.
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port}.
|
|
||||||
$config->{rtc}{path},
|
|
||||||
);
|
|
||||||
$comx->login(
|
|
||||||
$config->{rtc}{user},
|
|
||||||
$config->{rtc}{pass},
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port});
|
|
||||||
if ($comx->login_status->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Rtc Login failed. Check config settings. Status code: ' . $comx->login_status->{code}, $comx->login_status->{debug});
|
|
||||||
}
|
|
||||||
|
|
||||||
my (@deleted, @new);
|
|
||||||
for my $a (@{ $resource->{apps} }) {
|
|
||||||
my $app_name = $a->{name};
|
|
||||||
my ($old_app) = grep {$app_name eq $_->{name}} @{ $old_resource->{apps} };
|
|
||||||
if (!defined $old_app) {
|
|
||||||
push @new, $a;
|
|
||||||
} else {
|
|
||||||
if ($a->{domain} ne $old_app->{domain}) {
|
|
||||||
push @deleted, $old_app;
|
|
||||||
push @new, $a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for my $a (@{ $old_resource->{apps} }) {
|
|
||||||
my $app_name = $a->{name};
|
|
||||||
|
|
||||||
my ($new_app) = grep {$app_name eq $_->{name}} @{ $resource->{apps} };
|
|
||||||
if (!defined $new_app) {
|
|
||||||
push @deleted, $a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for my $app (@deleted) {
|
|
||||||
my $a_response = $comx->delete_app($app->{id});
|
|
||||||
if ($a_response->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Deleting rtc app failed. Error code: ' . $a_response->{code});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for my $app (@new) {
|
|
||||||
my $a_response = $comx->create_app(
|
|
||||||
$app->{name},
|
|
||||||
$app->{domain},
|
|
||||||
$old_resource->{rtc_user_id},
|
|
||||||
);
|
|
||||||
if ($a_response->{code} != 201) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Creating rtc app failed. Error code: ' . $a_response->{code});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_rtc_networks {
|
|
||||||
my %params = @_;
|
|
||||||
my ($rtc_user_id, $config, $reseller_item, $include_id, $err_code) =
|
|
||||||
@params{qw/rtc_user_id config reseller_item include_id err_code/};
|
|
||||||
|
|
||||||
if (!defined $err_code || ref $err_code ne 'CODE') {
|
|
||||||
$err_code = sub { return 0; };
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comx = NGCP::Panel::Utils::ComxAPIClient->new(
|
|
||||||
host => $config->{rtc}{schema}.'://'.
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port}.
|
|
||||||
$config->{rtc}{path},
|
|
||||||
);
|
|
||||||
$comx->login(
|
|
||||||
$config->{rtc}{user},
|
|
||||||
$config->{rtc}{pass},
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port});
|
|
||||||
if ($comx->login_status->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Rtc Login failed. Check config settings. Status code: ' . $comx->login_status->{code}, $comx->login_status->{debug});
|
|
||||||
}
|
|
||||||
|
|
||||||
my $networks_resp = $comx->get_networks_by_user_id($rtc_user_id);
|
|
||||||
my $networks = $networks_resp->{data};
|
|
||||||
unless (defined $networks && 'ARRAY' eq ref $networks && @{ $networks }) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Fetching networks failed. Code: ' . $networks_resp->{code}, $networks_resp->{debug});
|
|
||||||
}
|
|
||||||
|
|
||||||
my $res = [map {{
|
|
||||||
config =>$_->{config},
|
|
||||||
connector => $_->{connector},
|
|
||||||
tag => $_->{tag},
|
|
||||||
$include_id ? (id => $_->{id}) : (),
|
|
||||||
}} @{ $networks }];
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub modify_rtc_networks {
|
|
||||||
my %params = @_;
|
|
||||||
my ($old_resource, $resource, $config, $reseller_item, $err_code) =
|
|
||||||
@params{qw/old_resource resource config reseller_item err_code/};
|
|
||||||
|
|
||||||
if (!defined $err_code || ref $err_code ne 'CODE') {
|
|
||||||
$err_code = sub { return 0; };
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!defined $old_resource) || (!defined $resource)) { # can only modify (no create/delete) the whole resource
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Cannot Modify rtc network. Old or new resource missing.');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comx = NGCP::Panel::Utils::ComxAPIClient->new(
|
|
||||||
host => $config->{rtc}{schema}.'://'.
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port}.
|
|
||||||
$config->{rtc}{path},
|
|
||||||
);
|
|
||||||
$comx->login(
|
|
||||||
$config->{rtc}{user},
|
|
||||||
$config->{rtc}{pass},
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port});
|
|
||||||
if ($comx->login_status->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Rtc Login failed. Check config settings.');
|
|
||||||
}
|
|
||||||
|
|
||||||
my (@deleted, @new);
|
|
||||||
for my $nw (@{ $resource->{networks} }) {
|
|
||||||
my $nw_tag = $nw->{tag};
|
|
||||||
my ($old_nw) = grep {$nw_tag eq $_->{tag}} @{ $old_resource->{networks} };
|
|
||||||
if (!defined $old_nw) {
|
|
||||||
push @new, $nw;
|
|
||||||
} else {
|
|
||||||
if ($nw->{connector} ne $old_nw->{connector}
|
|
||||||
|| !compare($nw->{config}, $old_nw->{config})
|
|
||||||
) {
|
|
||||||
push @deleted, $old_nw;
|
|
||||||
push @new, $nw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for my $nw (@{ $old_resource->{networks} }) {
|
|
||||||
my $nw_tag = $nw->{tag};
|
|
||||||
|
|
||||||
my ($new_nw) = grep {$nw_tag eq $_->{tag}} @{ $resource->{networks} };
|
|
||||||
if (!defined $new_nw) {
|
|
||||||
push @deleted, $nw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for my $nw (@deleted) {
|
|
||||||
my $n_response = $comx->delete_network($nw->{id});
|
|
||||||
if ($n_response->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Deleting rtc network failed. Error code: ' . $n_response->{code}, $n_response->{debug});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for my $nw (@new) {
|
|
||||||
my $n_response = $comx->create_network(
|
|
||||||
$nw->{tag},
|
|
||||||
$nw->{connector},
|
|
||||||
$nw->{config} // {},
|
|
||||||
$old_resource->{rtc_user_id},
|
|
||||||
);
|
|
||||||
if ($n_response->{code} != 201) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Creating rtc network failed. Error code: ' . $n_response->{code}, $n_response->{debug});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
# returns enable_rtc (true|false) and rtc_browser_token (string)
|
|
||||||
sub get_rtc_subscriber_data {
|
|
||||||
my %params = @_;
|
|
||||||
my ($prov_subs, $config, $err_code) =
|
|
||||||
@params{qw/prov_subs config err_code/};
|
|
||||||
|
|
||||||
if (!defined $err_code || ref $err_code ne 'CODE') {
|
|
||||||
$err_code = sub { return 0; };
|
|
||||||
}
|
|
||||||
|
|
||||||
unless ($prov_subs) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
"Couldn't get rtc_subscriber_data. No provisioning subscriber.");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $rtc_session = $prov_subs->rtc_session;
|
|
||||||
unless ($rtc_session) {
|
|
||||||
return {enable_rtc => 0}; # JSON::false ?
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO: huh? is this the right browser token?
|
|
||||||
return {enable_rtc => 1, rtc_browser_token => 'abcde TODO'};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub modify_subscriber_rtc {
|
|
||||||
my %params = @_;
|
|
||||||
my ($old_resource, $resource, $config, $prov_subs, $err_code) =
|
|
||||||
@params{qw/old_resource resource config prov_subs err_code/};
|
|
||||||
|
|
||||||
if (!defined $err_code || ref $err_code ne 'CODE') {
|
|
||||||
$err_code = sub { return 0; };
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!defined $old_resource) && (defined $resource)) { # newly created reseller
|
|
||||||
|
|
||||||
# 1. enable_rtc is off -> do nothing
|
|
||||||
if (!$resource->{enable_rtc}) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_create_subscriber_rtc(
|
|
||||||
resource => $resource,
|
|
||||||
config => $config,
|
|
||||||
prov_subs => $prov_subs,
|
|
||||||
err_code => $err_code);
|
|
||||||
|
|
||||||
} elsif ((defined $old_resource) && (defined $resource)) {
|
|
||||||
|
|
||||||
if($old_resource->{status} ne 'terminated' &&
|
|
||||||
$resource->{status} eq 'terminated' &&
|
|
||||||
$old_resource->{enable_rtc}) { # just terminated
|
|
||||||
|
|
||||||
$resource->{enable_rtc} = JSON::false;
|
|
||||||
_delete_subscriber_rtc(
|
|
||||||
config => $config,
|
|
||||||
prov_subs => $prov_subs,
|
|
||||||
err_code => $err_code);
|
|
||||||
|
|
||||||
} elsif ($old_resource->{enable_rtc} &&
|
|
||||||
!$resource->{enable_rtc}) { # disable rtc
|
|
||||||
|
|
||||||
_delete_subscriber_rtc(
|
|
||||||
config => $config,
|
|
||||||
prov_subs => $prov_subs,
|
|
||||||
err_code => $err_code);
|
|
||||||
} elsif (!$old_resource->{enable_rtc} &&
|
|
||||||
$resource->{enable_rtc} &&
|
|
||||||
$resource->{status} ne 'terminated') { # enable rtc
|
|
||||||
|
|
||||||
_create_rtc_user(
|
|
||||||
resource => $resource,
|
|
||||||
config => $config,
|
|
||||||
prov_subs => $prov_subs,
|
|
||||||
err_code => $err_code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _create_subscriber_rtc {
|
|
||||||
my %params = @_;
|
|
||||||
my ($resource, $config, $prov_subs, $err_code) =
|
|
||||||
@params{qw/resource config prov_subs err_code/};
|
|
||||||
|
|
||||||
my $reseller = $prov_subs->voip_subscriber->contract->contact->reseller;
|
|
||||||
unless ($reseller) {
|
|
||||||
return unless &{err_code}(
|
|
||||||
'Creating subscriber rtc data failed. Reseller not found.');
|
|
||||||
}
|
|
||||||
my $rtc_user = $reseller->rtc_user;
|
|
||||||
unless ($rtc_user) {
|
|
||||||
return unless &{err_code}(
|
|
||||||
'Creating subscriber rtc data failed. Reseller has not enabled rtc.');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comx = NGCP::Panel::Utils::ComxAPIClient->new(
|
|
||||||
host => $config->{rtc}{schema}.'://'.
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port}.
|
|
||||||
$config->{rtc}{path},
|
|
||||||
);
|
|
||||||
$comx->login(
|
|
||||||
$config->{rtc}{user},
|
|
||||||
$config->{rtc}{pass},
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port});
|
|
||||||
if ($comx->login_status->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Rtc Login failed. Check config settings. Status code: ' . $comx->login_status->{code}, $comx->login_status->{debug});
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comx_apps = $comx->get_apps_by_user_id($rtc_user->rtc_user_id);
|
|
||||||
my $comx_app;
|
|
||||||
if ($comx_apps->{data} && @{ $comx_apps->{data} }){
|
|
||||||
$comx_app = $comx_apps->{data}[0];
|
|
||||||
} else {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'_create_subscriber_rtc: Could not find app.');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $session = $comx->create_session(
|
|
||||||
$comx_app->{id},
|
|
||||||
$rtc_user->rtc_user_id,
|
|
||||||
);
|
|
||||||
if ($session->{code} != 201) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Creating rtc session failed. Error code: ' . $session->{code}, $session->{debug});
|
|
||||||
}
|
|
||||||
|
|
||||||
# # 3. create relation in our db
|
|
||||||
# $prov_subs->create_related('rtc_session', {
|
|
||||||
# rtc_session_id => $session->{data}{id},
|
|
||||||
# });
|
|
||||||
|
|
||||||
# # 4. create related app
|
|
||||||
# my $app = $comx->create_app(
|
|
||||||
# $reseller_name . '_app',
|
|
||||||
# $reseller_name . 'www.sipwise.com',
|
|
||||||
# $user->{data}{id},
|
|
||||||
# );
|
|
||||||
# if ($app->{code} != 201) {
|
|
||||||
# return unless &{$err_code}(
|
|
||||||
# 'Creating rtc app failed. Error code: ' . $app->{code});
|
|
||||||
# }
|
|
||||||
|
|
||||||
# # 5. create related networks
|
|
||||||
# for my $n (@{ $rtc_networks }) {
|
|
||||||
# my $n_response = $comx->create_network(
|
|
||||||
# $reseller_name . "_$n",
|
|
||||||
# $n . '-connector',
|
|
||||||
# {xms => JSON::false},
|
|
||||||
# $user->{data}{id},
|
|
||||||
# );
|
|
||||||
# if ($n_response->{code} != 201) {
|
|
||||||
# return unless &{$err_code}(
|
|
||||||
# 'Creating rtc network failed. Error code: ' . $n_response->{code});
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
# return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _delete_subscriber_rtc {
|
|
||||||
# my %params = @_;
|
|
||||||
# my ($config, $prov_subs, $err_code) =
|
|
||||||
# @params{qw/config prov_subs err_code/};
|
|
||||||
|
|
||||||
# my $comx = NGCP::Panel::Utils::ComxAPIClient->new(
|
|
||||||
# host => $config->{rtc}{schema}.'://'.
|
|
||||||
# $config->{rtc}{host}.':'.$config->{rtc}{port}.
|
|
||||||
# $config->{rtc}{path},
|
|
||||||
# );
|
|
||||||
# $comx->login(
|
|
||||||
# $config->{rtc}{user},
|
|
||||||
# $config->{rtc}{pass},
|
|
||||||
# $config->{rtc}{host}.':'.$config->{rtc}{port});
|
|
||||||
# if ($comx->login_status->{code} != 200) {
|
|
||||||
# return unless &{$err_code}(
|
|
||||||
# 'Rtc Login failed. Check config settings. Status code: ' . $comx->login_status->{code}, $comx->login_status->{debug});
|
|
||||||
# }
|
|
||||||
|
|
||||||
# my $rtc_user = $reseller_item->rtc_user;
|
|
||||||
# if (!defined $rtc_user) {
|
|
||||||
# return unless &{$err_code}(
|
|
||||||
# 'No rtc user found in db for this reseller.');
|
|
||||||
# }
|
|
||||||
# # app and networks are deleted automatically
|
|
||||||
# my $delete_resp = $comx->delete_user(
|
|
||||||
# $rtc_user->rtc_user_id,
|
|
||||||
# );
|
|
||||||
# if ($delete_resp->{code} == 200) {
|
|
||||||
# $rtc_user->delete;
|
|
||||||
# } else {
|
|
||||||
# return unless &{$err_code}(
|
|
||||||
# 'Deleting rtc user failed. Error code: ' . $delete_resp->{code});
|
|
||||||
# }
|
|
||||||
# return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub create_rtc_session {
|
|
||||||
my %params = @_;
|
|
||||||
my ($config, $err_code, $resource, $subscriber_item) =
|
|
||||||
@params{qw/config err_code resource subscriber_item/};
|
|
||||||
|
|
||||||
if (!defined $err_code || ref $err_code ne 'CODE') {
|
|
||||||
$err_code = sub { return 0; };
|
|
||||||
}
|
|
||||||
|
|
||||||
my $reseller = $subscriber_item->contract->contact->reseller;
|
|
||||||
unless ($reseller) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Creating subscriber rtc data failed. Reseller not found.');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $rtc_user = $reseller->rtc_user;
|
|
||||||
unless ($rtc_user) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Creating subscriber rtc data failed. Reseller has not enabled rtc.');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comx = NGCP::Panel::Utils::ComxAPIClient->new(
|
|
||||||
host => $config->{rtc}{schema}.'://'.
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port}.
|
|
||||||
$config->{rtc}{path},
|
|
||||||
);
|
|
||||||
$comx->login(
|
|
||||||
$config->{rtc}{user},
|
|
||||||
$config->{rtc}{pass},
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port});
|
|
||||||
if ($comx->login_status->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Rtc Login failed. Check config settings. Status code: ' . $comx->login_status->{code}, $comx->login_status->{debug});
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comx_apps = $comx->get_apps_by_user_id($rtc_user->rtc_user_id);
|
|
||||||
my $comx_app;
|
|
||||||
if ($comx_apps->{data} && @{ $comx_apps->{data} }){
|
|
||||||
if ($resource->{rtc_app_name}) {
|
|
||||||
($comx_app) = grep {$_->{name} eq $resource->{rtc_app_name}} @{ $comx_apps->{data} };
|
|
||||||
} else { # default app
|
|
||||||
($comx_app) = grep {$_->{name} =~ m/_default_app$/;} @{ $comx_apps->{data} };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unless ($comx_app) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'create_rtc_session: Could not find app.');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comx_networks = $comx->get_networks_by_user_id($rtc_user->rtc_user_id);
|
|
||||||
my $comx_network_tags = [];
|
|
||||||
if ($comx_networks->{data} && 'ARRAY' eq ref $comx_networks->{data}) {
|
|
||||||
$comx_network_tags = [ map { $_->{tag} } @{ $comx_networks->{data} } ];
|
|
||||||
} else {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'create_rtc_session: Could not fetch networks for given rtc user.');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $session = $comx->create_session(
|
|
||||||
$comx_app->{id},
|
|
||||||
$rtc_user->rtc_user_id,
|
|
||||||
);
|
|
||||||
if ($session->{code} != 201) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Creating rtc session failed. Error code: ' . $session->{code}, $session->{debug});
|
|
||||||
}
|
|
||||||
for my $n (@{ $comx_networks->{data} }) {
|
|
||||||
my $identifier;
|
|
||||||
if ($n->{connector} eq "sip-connector") {
|
|
||||||
$identifier = 'sip:' . $subscriber_item->username . '@' . $subscriber_item->domain->domain;
|
|
||||||
} elsif ($n->{connector} eq "xmpp-connector") {
|
|
||||||
$identifier = 'xmpp:' . $subscriber_item->username . '@' . $subscriber_item->domain->domain;
|
|
||||||
} else { # webrtc, ...
|
|
||||||
$identifier = $subscriber_item->username;
|
|
||||||
}
|
|
||||||
my $account = $comx->create_account(
|
|
||||||
$session->{data}{id},
|
|
||||||
$rtc_user->rtc_user_id,
|
|
||||||
$identifier,
|
|
||||||
$n->{tag},
|
|
||||||
$subscriber_item->provisioning_voip_subscriber->password,
|
|
||||||
{xms => JSON::false},
|
|
||||||
);
|
|
||||||
if ($account->{code} != 201) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
"Creating rtc account ($n->{tag}) failed. Error code: " . $account->{code}, $account->{debug});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
my $rtc_session_item = $subscriber_item->provisioning_voip_subscriber->create_related('rtc_session', {
|
|
||||||
rtc_session_id => $session->{data}{id},
|
|
||||||
});
|
|
||||||
return $rtc_session_item;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_rtc_session {
|
|
||||||
my %params = @_;
|
|
||||||
my ($config, $item, $err_code) =
|
|
||||||
@params{qw/config item err_code/};
|
|
||||||
|
|
||||||
if (!defined $err_code || ref $err_code ne 'CODE') {
|
|
||||||
$err_code = sub { return 0; };
|
|
||||||
}
|
|
||||||
|
|
||||||
my $comx = NGCP::Panel::Utils::ComxAPIClient->new(
|
|
||||||
host => $config->{rtc}{schema}.'://'.
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port}.
|
|
||||||
$config->{rtc}{path},
|
|
||||||
);
|
|
||||||
$comx->login(
|
|
||||||
$config->{rtc}{user},
|
|
||||||
$config->{rtc}{pass},
|
|
||||||
$config->{rtc}{host}.':'.$config->{rtc}{port});
|
|
||||||
if ($comx->login_status->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
'Rtc Login failed. Check config settings. Status code: ' . $comx->login_status->{code}, $comx->login_status->{debug});
|
|
||||||
}
|
|
||||||
|
|
||||||
my $session = $comx->get_session($item->rtc_session_id);
|
|
||||||
if ($session->{code} != 200) {
|
|
||||||
return unless &{$err_code}(
|
|
||||||
"Couldn't find session. Error code: " . $session->{code}, $session->{debug});
|
|
||||||
}
|
|
||||||
return $session;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_random {
|
|
||||||
my ($num, $err_code) = @_;
|
|
||||||
my ($fd, $buf);
|
|
||||||
unless(open($fd, '<', '/dev/urandom')) {
|
|
||||||
return unless &{$err_code}("Failed to open /dev/urandom: $!");
|
|
||||||
}
|
|
||||||
unless(read($fd, $buf, $num) == $num) {
|
|
||||||
return unless &{$err_code}("Failed to read $num bytes from /dev/urandom: $!");
|
|
||||||
}
|
|
||||||
close($fd);
|
|
||||||
return $buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
@ -1,630 +0,0 @@
|
|||||||
[% site_config.title = c.loc('Web Phone for ') _ subscriber.username _ '@' _ subscriber.domain.domain -%]
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/libs/jssip-0.3.0.min.js"></script>
|
|
||||||
<!--<script type="text/javascript" src="/js/libs/stanzaio.bundle.min.js"></script>-->
|
|
||||||
<script type="text/javascript" src="/js/libs/stanzaio.bundle.js"></script>
|
|
||||||
<script type="text/javascript" src="/js/libs/bootstrap-select.min.js"></script>
|
|
||||||
<script type="text/javascript" src="/js/libs/bootstrap-switch.js"></script>
|
|
||||||
<script type="text/javascript" src="/js/libs/jquery.slimscroll.min.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/bootstrap-select/bootstrap-select.min.css"/>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/bootstrap-switch/bootstrap-switch.css"/>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/font/font-awesome/css/font-awesome.min.css"/>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
#xmpp-roster {
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#xmpp-roster .popover {
|
|
||||||
max-width: 100%;
|
|
||||||
min-height: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.xmpp-roster-entry-col1.available {
|
|
||||||
background: #080;
|
|
||||||
}
|
|
||||||
.xmpp-roster-entry-col1.unavailable {
|
|
||||||
background: #ddd;
|
|
||||||
}
|
|
||||||
.xmpp-roster-entry-col1.chat {
|
|
||||||
background: #0f0;
|
|
||||||
}
|
|
||||||
.xmpp-roster-entry-col1.away,
|
|
||||||
.xmpp-roster-entry-col1.xa {
|
|
||||||
background: #fa0;
|
|
||||||
}
|
|
||||||
.xmpp-roster-entry-col1.dnd {
|
|
||||||
background: #f00;
|
|
||||||
}
|
|
||||||
|
|
||||||
.xmpp-roster-entry-ctrl {
|
|
||||||
margin-right:10px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-left.switch-mini, .switch-right.switch-mini {
|
|
||||||
/* make more space on left/right */
|
|
||||||
padding-left: 5px;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
.has-switch {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.xmpp-chat-time {
|
|
||||||
font-style:italic;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
.xmpp-chat-sent {
|
|
||||||
float: right;
|
|
||||||
clear: both;
|
|
||||||
margin-right: 15px;
|
|
||||||
margin-left: 30px;
|
|
||||||
text-align: right;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
.xmpp-chat-recv {
|
|
||||||
float: left;
|
|
||||||
clear: both;
|
|
||||||
margin-left: 0px;
|
|
||||||
margin-right: 30px;
|
|
||||||
text-align: left;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.has-switch {
|
|
||||||
min-width: 200px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<span class="pull-left" style="margin:0 5px 0 5px;">
|
|
||||||
<a class="btn btn-primary btn-large" href="[% c.uri_for('/back') %]"><i class="icon-arrow-left"></i> [% c.loc('Back') %]</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
[% back_created = 1 -%]
|
|
||||||
|
|
||||||
<div class="ngcp-separator"></div>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var phone = null;
|
|
||||||
var chat = null;
|
|
||||||
var sip_configuration = null;
|
|
||||||
var xmpp_configuration = null;
|
|
||||||
var xmpp_last_state = 'available';
|
|
||||||
var orig_page_title = document.title;
|
|
||||||
var window_focus = true;
|
|
||||||
var window_timeout;
|
|
||||||
var xmpp_show_offline = false;
|
|
||||||
var xmpp_last_time = "";
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: "[% c.uri_for_action('/subscriber/webphone_ajax', c.req.captures) %]"
|
|
||||||
}).done(function(data) {
|
|
||||||
|
|
||||||
sip_configuration = data.aaData.sip;
|
|
||||||
sip_configuration.register = true;
|
|
||||||
sip_configuration.trace_sip = true;
|
|
||||||
phone = new JsSIP.UA(sip_configuration);
|
|
||||||
|
|
||||||
// ws connection events
|
|
||||||
phone.on('connected', function(e){
|
|
||||||
console.log("connected");
|
|
||||||
$("#sip-status").html("[% c.loc('connected - registering...') %]");
|
|
||||||
});
|
|
||||||
phone.on('disconnected', function(e){
|
|
||||||
console.log("disconnected");
|
|
||||||
$("#sip-status").html("[% c.loc('disconnected.') %]");
|
|
||||||
});
|
|
||||||
|
|
||||||
// in/out call event
|
|
||||||
phone.on('newRTCSession', function(e){
|
|
||||||
//console.log("newRTCSession", e.originator, e.session);
|
|
||||||
console.log("newRTCSession", e);
|
|
||||||
|
|
||||||
var session = e.data.session;
|
|
||||||
if(session.direction == 'incoming') {
|
|
||||||
session.answer({
|
|
||||||
mediaConstraints: { audio: true, video: $('#sip_toggle_video').is(':checked') }
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: create_incall_window($(obj.target).parents("li.xmpp-roster-entry"), jidid, item.jid.bare);
|
|
||||||
|
|
||||||
session.on('started', function(e) {
|
|
||||||
console.log("RTCSession session started");
|
|
||||||
var rtcSession = e.sender;
|
|
||||||
if(rtcSession.getLocalStreams().length > 0) {
|
|
||||||
selfView.src = window.URL.createObjectURL(rtcSession.getLocalStreams()[0]);
|
|
||||||
selfView.volume = 0;
|
|
||||||
}
|
|
||||||
if(rtcSession.getRemoteStreams().length > 0) {
|
|
||||||
remoteView.src = window.URL.createObjectURL(rtcSession.getRemoteStreams()[0]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// in/out im event
|
|
||||||
phone.on('newMessage', function(e){
|
|
||||||
console.log("newMessage");
|
|
||||||
});
|
|
||||||
// registration events
|
|
||||||
phone.on('registered', function(e){
|
|
||||||
console.log("registered");
|
|
||||||
$("#sip-status").html("[% c.loc('registered.') %]");
|
|
||||||
});
|
|
||||||
phone.on('unregistered', function(e){
|
|
||||||
console.log("unregistered");
|
|
||||||
$("#sip-status").html("[% c.loc('unregistered.') %]");
|
|
||||||
});
|
|
||||||
phone.on('registrationFailed', function(e){
|
|
||||||
console.log("registrationFailed", e.data.response);
|
|
||||||
$("#sip-status").html("[% c.loc('registration failed:') %] " + e.data.response.status_code + " - " + e.data.response.reason_phrase);
|
|
||||||
});
|
|
||||||
|
|
||||||
phone.start();
|
|
||||||
|
|
||||||
xmpp_configuration = data.aaData.xmpp;
|
|
||||||
// chat client modifies it, so make a copy to have the original
|
|
||||||
// one later on re-connects
|
|
||||||
var tmp_xmpp_configuration = jQuery.extend(true, {}, xmpp_configuration);
|
|
||||||
chat = XMPP.createClient(tmp_xmpp_configuration);
|
|
||||||
register_chat_callbacks();
|
|
||||||
chat.connect();
|
|
||||||
});
|
|
||||||
|
|
||||||
function register_chat_callbacks() {
|
|
||||||
var timer = null;
|
|
||||||
chat.on('disconnected', function() {
|
|
||||||
console.log("xmpp disconnection");
|
|
||||||
$("#xmpp-status").html("[% c.loc('disconnected.') %]");
|
|
||||||
if(timer)
|
|
||||||
return 1;
|
|
||||||
console.log("prepare re-connect timer");
|
|
||||||
$('#xmpp-roster').empty();
|
|
||||||
var xmpp_last_state_tmp = xmpp_last_state;
|
|
||||||
$('#xmpp-pres').val('unavailable');
|
|
||||||
$('#xmpp-pres').change();
|
|
||||||
xmpp_last_state = xmpp_last_state_tmp;
|
|
||||||
timer = window.setInterval(function(){
|
|
||||||
console.log("perform re-connect");
|
|
||||||
window.clearInterval(timer);
|
|
||||||
timer = null;
|
|
||||||
chat.disconnect();
|
|
||||||
console.log("create new client", xmpp_configuration);
|
|
||||||
var tmp_xmpp_configuration = jQuery.extend(true, {}, xmpp_configuration);
|
|
||||||
chat = XMPP.createClient(tmp_xmpp_configuration);
|
|
||||||
register_chat_callbacks();
|
|
||||||
chat.connect();
|
|
||||||
}, 3000);
|
|
||||||
});
|
|
||||||
|
|
||||||
chat.on('chatState', function(obj) {
|
|
||||||
console.log("got chat state", obj);
|
|
||||||
var jid = obj.from.bare;
|
|
||||||
var msg;
|
|
||||||
if(obj.chatState == "composing") {
|
|
||||||
msg = "[% c.loc('is typing...') %]";
|
|
||||||
} else if(obj.chatState == "paused") {
|
|
||||||
msg = "[% c.loc('has stopped typing.') %]";
|
|
||||||
} else if(obj.chatState == "active") {
|
|
||||||
// chat session started/closed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var jidid = jid.replace(/[^a-zA-Z0-9_]/g, '-');
|
|
||||||
var chat_win = $('#xmpp-roster #' + jidid).find('.popover');
|
|
||||||
if(!chat_win.length) {
|
|
||||||
chat_win = create_chat_window($('#xmpp-roster #' + jidid), jidid, jid);
|
|
||||||
}
|
|
||||||
$(chat_win).find('.xmpp-chat-history').append('<li><em>' + msg + '</em></li>')
|
|
||||||
.slimScroll({ scrollBy: '50px' });
|
|
||||||
});
|
|
||||||
|
|
||||||
chat.on('chat', function(obj) {
|
|
||||||
console.log("got message ", obj);
|
|
||||||
var jid = obj.from.bare;
|
|
||||||
var jidid = jid.replace(/[^a-zA-Z0-9_]/g, '-');
|
|
||||||
|
|
||||||
var chat_win = $('#xmpp-roster #' + jidid).find('.popover');
|
|
||||||
if(!chat_win.length) {
|
|
||||||
chat_win = create_chat_window($('#xmpp-roster #' + jidid), jidid, jid);
|
|
||||||
}
|
|
||||||
|
|
||||||
var now = get_time_string();
|
|
||||||
if(now != xmpp_last_time) {
|
|
||||||
xmpp_last_time = now;
|
|
||||||
$(chat_win).find('.xmpp-chat-history').append('<li><span class="xmpp-chat-recv"><span class="xmpp-chat-time">' + now + '</span></span></li>')
|
|
||||||
}
|
|
||||||
$(chat_win).find('.xmpp-chat-history').append('<li><span class="xmpp-chat-recv">' + obj.body + '</span></li>')
|
|
||||||
.slimScroll({ scrollBy: '50px' });
|
|
||||||
|
|
||||||
raise_attention('chat');
|
|
||||||
});
|
|
||||||
|
|
||||||
chat.on('groupchat', function(message) {
|
|
||||||
console.log("got group message ", message);
|
|
||||||
});
|
|
||||||
|
|
||||||
chat.on('session:started', function() {
|
|
||||||
$("#xmpp-status").html("[% c.loc('online.') %]");
|
|
||||||
console.log("XMPP session started");
|
|
||||||
chat.enableCarbons();
|
|
||||||
chat.getRoster(function(err, resp) {
|
|
||||||
console.log(err, resp);
|
|
||||||
chat.sendPresence();
|
|
||||||
if(err == null) {
|
|
||||||
$.each(resp.roster.items, function(index, item) {
|
|
||||||
console.log(item.name);
|
|
||||||
var jidid = item.jid.bare.replace(/[^a-zA-Z0-9_]/g, '-');
|
|
||||||
var entry = create_xmpp_entry_dom(jidid, item.jid.bare, item.name || item.jid.bare);
|
|
||||||
$('#xmpp-roster').append(entry);
|
|
||||||
$('#xmpp-roster li').sort(roster_asc_sort).appendTo('#xmpp-roster');
|
|
||||||
equalHeights($('#' + jidid).find('.xmpp-roster-entry-col1'), $('#' + jidid).find('.xmpp-roster-entry-col2'));
|
|
||||||
$('#' + jidid)
|
|
||||||
.mouseenter(function(obj) {
|
|
||||||
$(obj.currentTarget).find('.xmpp-roster-entry-col3').show();
|
|
||||||
})
|
|
||||||
.mouseleave(function(obj) {
|
|
||||||
$(obj.currentTarget).find('.xmpp-roster-entry-col3').hide();
|
|
||||||
})
|
|
||||||
.find('[rel="tooltip"]').tooltip({'html': false});
|
|
||||||
|
|
||||||
$('#' + jidid).find('.xmpp-roster-entry-ctrl-chat').click(function(obj) {
|
|
||||||
console.log("start chat");
|
|
||||||
create_chat_window($(obj.target).parents("li.xmpp-roster-entry"), jidid, item.jid.bare);
|
|
||||||
});
|
|
||||||
$('#' + jidid).find('.xmpp-roster-entry-ctrl-phone').click(function(obj) {
|
|
||||||
console.log("start chat");
|
|
||||||
create_outcall_window($(obj.target).parents("li.xmpp-roster-entry"), jidid, item.jid.bare);
|
|
||||||
var session = call(item.jid.bare);
|
|
||||||
});
|
|
||||||
|
|
||||||
// we get a presence callback where we'll show it
|
|
||||||
$(entry).hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$('#xmpp-pres').val(xmpp_last_state);
|
|
||||||
$('#xmpp-pres').change();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
chat.on('presence', function(pres) {
|
|
||||||
if(pres.from.bare == xmpp_configuration.jid) {
|
|
||||||
console.log("skip own presence info");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
var type = pres.type || 'available';
|
|
||||||
var show;
|
|
||||||
if(type == 'available') {
|
|
||||||
show = pres.show || 'available';
|
|
||||||
} else {
|
|
||||||
show = pres.show || 'unavailable';
|
|
||||||
}
|
|
||||||
var jidid = pres.from.bare.replace(/[^a-zA-Z0-9_]/g, '-');
|
|
||||||
|
|
||||||
$("#xmpp-roster #" + jidid + " .xmpp-roster-entry-col1").removeClass().addClass("xmpp-roster-entry-col1 " + show);
|
|
||||||
console.log("xmpp-roster type=" + pres.type + ", show=" + pres.show);
|
|
||||||
if(show != 'unavailable' || xmpp_show_offline) {
|
|
||||||
$("#xmpp-roster #" + jidid).show();
|
|
||||||
} else {
|
|
||||||
$("#xmpp-roster #" + jidid).hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function call(dest_uri) {
|
|
||||||
var eventHandlers = {
|
|
||||||
'progress': function(e) {
|
|
||||||
console.log("call in progress", e);
|
|
||||||
$("#sip-status").html("[% c.loc('in progress...') %]");
|
|
||||||
},
|
|
||||||
'failed': function(e) {
|
|
||||||
console.log("call failed");
|
|
||||||
$("#sip-status").html("[% c.loc('call failed:') %] ", e);
|
|
||||||
},
|
|
||||||
'started': function(e) {
|
|
||||||
console.log("call started");
|
|
||||||
$("#sip-status").html("[% c.loc('call started.') %]");
|
|
||||||
|
|
||||||
var rtcSession = e.sender;
|
|
||||||
|
|
||||||
if (rtcSession.getLocalStreams().length > 0) {
|
|
||||||
selfView.src = window.URL.createObjectURL(rtcSession.getLocalStreams()[0]);
|
|
||||||
}
|
|
||||||
if (rtcSession.getRemoteStreams().length > 0) {
|
|
||||||
remoteView.src = window.URL.createObjectURL(rtcSession.getRemoteStreams()[0]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'ended': function(e){
|
|
||||||
console.log("call ended");
|
|
||||||
$("#sip-status").html("[% c.loc('call ended.') %]");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
'eventHandlers': eventHandlers,
|
|
||||||
'extraHeaders': [ 'X-Foo: foo', 'X-Bar: bar' ],
|
|
||||||
'mediaConstraints': { 'audio': true, 'video': $('#sip_toggle_video').is(':checked') }
|
|
||||||
};
|
|
||||||
|
|
||||||
phone.call('sip:' + dest_uri, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
function roster_asc_sort(a, b) {
|
|
||||||
return ($(b).find('.xmpp-roster-entry-name').text().toLowerCase()) < ($(a).find('.xmpp-roster-entry-name').text().toLowerCase()) ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_time_string() {
|
|
||||||
var now = new Date();
|
|
||||||
//return ((now.getHours() < 10)?"0":"") + now.getHours() +":"+ ((now.getMinutes() < 10)?"0":"") + now.getMinutes() +":"+ ((now.getSeconds() < 10)?"0":"") + now.getSeconds();
|
|
||||||
return ((now.getHours() < 10)?"0":"") + now.getHours() +":"+ ((now.getMinutes() < 10)?"0":"") + now.getMinutes();
|
|
||||||
}
|
|
||||||
|
|
||||||
function create_xmpp_entry_dom(jidid, jid, name) {
|
|
||||||
var entry =
|
|
||||||
'<li id="' + jidid + '" class="xmpp-roster-entry row span6" style="clear:both; float:left; padding:0; margin:1px; background:#f0f0f0;">' +
|
|
||||||
' <div class="xmpp-roster-entry-col1 unavailable" style="float:left; width:10px; padding:0; margin:0; "> </div>' +
|
|
||||||
' <div class="xmpp-roster-entry-col2 span3" style="float:left; padding:20px; margin:0;">' +
|
|
||||||
' <div>' +
|
|
||||||
' <span class="xmpp-roster-entry-name" style="font-size:1.3em; font-weight:bold;">' + name + '</span>' +
|
|
||||||
' </div>' +
|
|
||||||
' <div>' +
|
|
||||||
' <span class="xmpp-roster-entry-details" style="font-size:1em; font-weight:normal;">' + jid + '</span>' +
|
|
||||||
' </div>' +
|
|
||||||
' </div>' +
|
|
||||||
' <div class="xmpp-roster-entry-col3" style="float:right; padding:20px 0 20px 0; margin:0; display:none;">' +
|
|
||||||
' <div style="float:right; font-size:1.5em">' +
|
|
||||||
' <span class="fa fa-comment xmpp-roster-entry-ctrl xmpp-roster-entry-ctrl-chat" rel="tooltip" title="Start Chat"></span>' +
|
|
||||||
' <span class="fa fa-phone xmpp-roster-entry-ctrl xmpp-roster-entry-ctrl-phone" rel="tooltip" title="Make Call"></span>' +
|
|
||||||
' <span class="fa fa-file-text xmpp-roster-entry-ctrl xmpp-roster-entry-ctrl-fax" rel="tooltip" title="Send Fax"></span>' +
|
|
||||||
' </div>' +
|
|
||||||
' </div>' +
|
|
||||||
'</li>';
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
function create_chat_window(parent, jidid, jid) {
|
|
||||||
$(parent).popover("destroy");
|
|
||||||
$(parent).popover({
|
|
||||||
placement: 'right',
|
|
||||||
html: true,
|
|
||||||
container: '#' + jidid,
|
|
||||||
trigger: 'manual',
|
|
||||||
title: '<div> <span class="pull-left">' + jid + '</span><span class="xmpp-chat-close pull-right fa fa-times"></span></div>',
|
|
||||||
content: '<div class="span4" style="margin:10px;"><ul class="xmpp-chat-history" style="list-style-type:none; margin:0; min-height:100px;"></ul><input data-jid="'+ jid + '" type="text" class="xmpp-chat-input" style="width:100%; margin:10px 0 0 0;"/></div>'
|
|
||||||
});
|
|
||||||
$(parent).popover("show");
|
|
||||||
$(parent).find(".xmpp-chat-input").focus();
|
|
||||||
$(parent).find(".xmpp-chat-history").slimScroll({
|
|
||||||
height: '100px',
|
|
||||||
railVisible: true,
|
|
||||||
alwaysVisible: true,
|
|
||||||
start: 'bottom'
|
|
||||||
});
|
|
||||||
return $(parent).find(".popover");
|
|
||||||
}
|
|
||||||
|
|
||||||
function create_incall_window(parent, jidid, jid) {
|
|
||||||
$(parent).popover("destroy");
|
|
||||||
$(parent).popover({
|
|
||||||
placement: 'right',
|
|
||||||
html: true,
|
|
||||||
container: '#' + jidid,
|
|
||||||
trigger: 'manual',
|
|
||||||
title: '<div> <span class="pull-left">[% c.loc('Call from') %] ' + jid + '</span><span class="xmpp-chat-close pull-right fa fa-times"></span></div>',
|
|
||||||
content: '<div class="span4" style="margin:10px;"><button class="sip-accept-call" style="margin-right:20px;">[% c.loc('Accept') %]</button><button class="sip-reject-call">[% c.loc('Reject') %]</button></div>'
|
|
||||||
});
|
|
||||||
$(parent).popover("show");
|
|
||||||
$(parent).find(".sip-accept-call").click(function(){
|
|
||||||
console.log("answering call");
|
|
||||||
/*
|
|
||||||
var session = ???;
|
|
||||||
session.answer({
|
|
||||||
mediaConstraints: { audio: true, video: $('#sip_toggle_video').is(':checked') }
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
});
|
|
||||||
$(parent).find(".sip-reject-call").click(function(){
|
|
||||||
console.log("rejecting call");
|
|
||||||
// var session = ???; session.terminate({ status_code: 486 });
|
|
||||||
});
|
|
||||||
return $(parent).find(".popover");
|
|
||||||
}
|
|
||||||
|
|
||||||
function create_outcall_window(parent, jidid, jid) {
|
|
||||||
$(parent).popover("destroy");
|
|
||||||
$(parent).popover({
|
|
||||||
placement: 'right',
|
|
||||||
html: true,
|
|
||||||
container: '#' + jidid,
|
|
||||||
trigger: 'manual',
|
|
||||||
title: '<div> <span class="pull-left">[% c.loc('Calling') %] ' + jid + '</span><span class="xmpp-chat-close pull-right fa fa-times"></span></div>',
|
|
||||||
content: '<div class="span4" style="margin:10px;"><button class="sip-stop-call" style="margin-right:20px;">[% c.loc('Terminate Call') %]</button></div>'
|
|
||||||
});
|
|
||||||
$(parent).popover("show");
|
|
||||||
$(parent).find(".sip-stop-call").click(function(){
|
|
||||||
console.log("stopping call");
|
|
||||||
/*
|
|
||||||
var session = ???;
|
|
||||||
session.terminate();
|
|
||||||
*/
|
|
||||||
});
|
|
||||||
return $(parent).find(".popover");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function equalHeights (element1, element2) {
|
|
||||||
var height;
|
|
||||||
|
|
||||||
if (element1.outerHeight() > element2.outerHeight())
|
|
||||||
{
|
|
||||||
height = element1.outerHeight();
|
|
||||||
element2.css('height', height);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
height = element2.outerHeight();
|
|
||||||
element1.css('height', height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function raise_attention(type) {
|
|
||||||
if(!window_focus) {
|
|
||||||
if(type == "chat") {
|
|
||||||
flash_title('[% c.loc('NEW MESSAGE') %]');
|
|
||||||
} else {
|
|
||||||
flash_title(type + '! ' + orig_page_title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function flash_title(title) {
|
|
||||||
function step() {
|
|
||||||
document.title = (document.title == orig_page_title) ? title : orig_page_title;
|
|
||||||
window_timeout = setTimeout(step, 800);
|
|
||||||
};
|
|
||||||
|
|
||||||
cancel_flash_title(window_timeout);
|
|
||||||
step();
|
|
||||||
};
|
|
||||||
|
|
||||||
function cancel_flash_title() {
|
|
||||||
clearTimeout(window_timeout);
|
|
||||||
document.title = orig_page_title;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
$('.selectpicker').selectpicker();
|
|
||||||
|
|
||||||
$('#xmpp-toggle-offline').bootstrapSwitch();
|
|
||||||
$('#xmpp-toggle-offline').bootstrapSwitch('setSizeClass', 'switch-mini');
|
|
||||||
$('#xmpp-toggle-offline').on('switch-change', function(obj) {
|
|
||||||
if(obj.currentTarget.checked) {
|
|
||||||
console.log("show offline entries");
|
|
||||||
xmpp_show_offline = true;
|
|
||||||
$('.xmpp-roster-entry').show();
|
|
||||||
} else {
|
|
||||||
console.log("hide offline entries");
|
|
||||||
xmpp_show_offline = false;
|
|
||||||
$('.xmpp-roster-entry-col1.unavailable').parent().hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('#sip_toggle_video').bootstrapSwitch();
|
|
||||||
$('#sip_toggle_video').bootstrapSwitch('setSizeClass', 'switch-mini');
|
|
||||||
|
|
||||||
$('#xmpp-pres').change(function(obj) {
|
|
||||||
var show = obj.currentTarget[obj.currentTarget.selectedIndex].value;
|
|
||||||
xmpp_last_state = show;
|
|
||||||
var type = (show == "unavailable" ? "unavailable" : "available");
|
|
||||||
console.log("changing xmpp presence status, show=" + show + ", type=" + type);
|
|
||||||
if(show == "available") {
|
|
||||||
chat.sendPresence();
|
|
||||||
} else {
|
|
||||||
chat.sendPresence({ type: type, show: show });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).keypress(function(obj) {
|
|
||||||
if($(obj.target).hasClass("xmpp-chat-input")) {
|
|
||||||
// return esc and tab
|
|
||||||
if (obj.which == 9 || obj.which == 27) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(obj.which == 13 && $(obj.target).val().length) {
|
|
||||||
obj.preventDefault();
|
|
||||||
chat.sendMessage({ to: $(obj.target).data("jid"), body: $(obj.target).val() });
|
|
||||||
var chat_win = $(obj.target).parent().find(".xmpp-chat-history");
|
|
||||||
var now = get_time_string();
|
|
||||||
if(now != xmpp_last_time) {
|
|
||||||
xmpp_last_time = now;
|
|
||||||
$(chat_win).append('<li><span class="xmpp-chat-sent"><span class="xmpp-chat-time">' + now + '</span></span></li>')
|
|
||||||
}
|
|
||||||
$(chat_win).append('<li><span class="xmpp-chat-sent">' + $(obj.target).val() + '</span></li>')
|
|
||||||
.slimScroll({ scrollBy: '50px' });
|
|
||||||
$(obj.target).val("");
|
|
||||||
} else {
|
|
||||||
// TODO: send chatState message somehow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).click(function(obj) {
|
|
||||||
if($(obj.target).hasClass("xmpp-chat-close")) {
|
|
||||||
console.log("hiding chat window");
|
|
||||||
$(obj.target).parents("li.xmpp-roster-entry").popover("destroy");
|
|
||||||
$(obj.target).parents(".popover").remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(window).focus(function() {
|
|
||||||
window_focus = true;
|
|
||||||
document.title = orig_page_title;
|
|
||||||
clearTimeout(window_timeout);
|
|
||||||
}).blur(function() {
|
|
||||||
window_focus = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
window.onbeforeunload = function(obj) {
|
|
||||||
if(phone.isRegistered()) {
|
|
||||||
console.log("unregistering phone before leaving");
|
|
||||||
phone.unregister({'all': true});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$('#xmpp-buddy-add').click(function(obj) {
|
|
||||||
var jid = $('#xmpp-buddy-add-jid').val();
|
|
||||||
console.log(">>>>>>>>> adding jid " + jid);
|
|
||||||
chat.subscribe(jid);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="span6">[% c.loc('Phone Status:') %] <span id="sip-status">[% c.loc('connecting...') %]</span></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="span6">[% c.loc('Chat Status:') %] <span id="xmpp-status">[% c.loc('connecting...') %]</span></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3>[% c.loc('Buddy List') %]</h3>
|
|
||||||
<div class="row span6" style="margin:0; clear:both; padding:10px;">
|
|
||||||
<input id="xmpp-toggle-offline" style="float:left;" type="checkbox" data-on="success" data-off="default" data-on-label="[% c.loc('Show Offline') %]" data-off-label="[% c.loc('Hide Offline') %]">
|
|
||||||
<input id="sip_toggle_video" checked style="float:left" type="checkbox" data-on="success" data-off="default" data-on-label="[% c.loc('Audio&Video') %]" data-off-label="[% c.loc('Audio Only') %]">
|
|
||||||
</div>
|
|
||||||
<div class="span6" style="margin:0; clear:both; padding:0;">
|
|
||||||
<div class="span4" style="margin:0;">
|
|
||||||
<input type="text" id="xmpp-buddy-add-jid" class="span4"/>
|
|
||||||
</div>
|
|
||||||
<div class="span2" style="margin:0; float:right;">
|
|
||||||
<button class="btn btn-primary btn-medium" id="xmpp-buddy-add"><i class="icon-plus"></i> Add Buddy</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row span6" style="margin:0; clear:both;">
|
|
||||||
<select id="xmpp-pres" class="selectpicker span6">
|
|
||||||
[% FOR opt IN
|
|
||||||
[
|
|
||||||
{ n = "unavailable", d = c.loc('Offline') },
|
|
||||||
{ n = "available", d = c.loc('Available') },
|
|
||||||
{ n = "away", d = c.loc('Away') },
|
|
||||||
{ n = "xa", d = c.loc('Extended Away') },
|
|
||||||
{ n = "dnd", d = c.loc('Do Not Disturb') },
|
|
||||||
]
|
|
||||||
-%]
|
|
||||||
<option value="[% opt.n %]" data-content="<span class='xmpp-roster-entry-col1 [% opt.n %]'> </span><span> [% opt.d %]</span>">[% opt.d %]</option>
|
|
||||||
[% END -%]
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<ul id="xmpp-roster" class="span8" style="list-style-type:none; padding:0; margin:0;">
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<video id="selfView" autoplay hidden=true></video>
|
|
||||||
<video id="remoteView" autoplay hidden=true></video>
|
|
||||||
|
|
||||||
[% # vim: set tabstop=4 syntax=html expandtab: -%]
|
|
@ -1,201 +0,0 @@
|
|||||||
use warnings;
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Net::Domain qw(hostfqdn);
|
|
||||||
use JSON qw();
|
|
||||||
use Test::More;
|
|
||||||
use URI::Escape qw();
|
|
||||||
|
|
||||||
#use LWP::Debug;
|
|
||||||
|
|
||||||
my $is_local_env = 0;
|
|
||||||
|
|
||||||
unless ($ENV{TEST_RTC}) {
|
|
||||||
plan skip_all => "not testing rtc, enable TEST_RTC=yes to run tests";
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $uri = $ENV{CATALYST_SERVER} || ('https://'.hostfqdn.':4443');
|
|
||||||
|
|
||||||
my $domain_name = $ENV{TEST_RTC_DOMAIN};
|
|
||||||
unless ($domain_name) {
|
|
||||||
($domain_name) = ($uri =~ m!^https?://([^/:]*)(:[0-9]+)?/?.*$!);
|
|
||||||
}
|
|
||||||
|
|
||||||
my ($ua, $req, $res, $data);
|
|
||||||
|
|
||||||
use Test::Collection;
|
|
||||||
$ua = Test::Collection->new()->ua();
|
|
||||||
|
|
||||||
my ($domain_id);
|
|
||||||
{
|
|
||||||
$req = HTTP::Request->new('GET', "$uri/api/domains/?domain=$domain_name");
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 200, "GET search domain");
|
|
||||||
$data = JSON::from_json($res->decoded_content);
|
|
||||||
ok($data->{total_count}, "got at least one domain") || die "we can't continue without domain";
|
|
||||||
|
|
||||||
my $selected_domain = ( 'ARRAY' eq ref $data->{_embedded}{'ngcp:domains'} )
|
|
||||||
? $data->{_embedded}{'ngcp:domains'}[0]
|
|
||||||
: $data->{_embedded}{'ngcp:domains'};
|
|
||||||
|
|
||||||
$domain_id = $selected_domain->{id};
|
|
||||||
$domain_name = $selected_domain->{domain};
|
|
||||||
|
|
||||||
diag("domain: $selected_domain->{domain} ($domain_id)");
|
|
||||||
}
|
|
||||||
|
|
||||||
my ($contract_id, $reseller_id, $customer_id, $bprof_id, $customercontact_id, $network_tag);
|
|
||||||
{
|
|
||||||
$req = HTTP::Request->new('POST', $uri.'/api/contracts/');
|
|
||||||
$req->header('Content-Type' => 'application/json');
|
|
||||||
$req->header('Prefer' => 'return=representation');
|
|
||||||
$req->content(JSON::to_json({
|
|
||||||
contact_id => 2,
|
|
||||||
status => 'active',
|
|
||||||
type => 'reseller',
|
|
||||||
billing_profile_id => 1,
|
|
||||||
}));
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 201, "POST create contract");
|
|
||||||
($contract_id) = $res->header('Location') =~ m!/(\d+)$!;
|
|
||||||
ok($contract_id, "got contract_id") || die "we don't continue here";
|
|
||||||
|
|
||||||
$req = HTTP::Request->new('POST', $uri.'/api/resellers/');
|
|
||||||
$req->header('Content-Type' => 'application/json');
|
|
||||||
$req->header('Prefer' => 'return=representation');
|
|
||||||
$req->content(JSON::to_json({
|
|
||||||
contract_id => $contract_id,
|
|
||||||
name => 'rtc test reseller ' . time,
|
|
||||||
enable_rtc => JSON::true,
|
|
||||||
status => 'active',
|
|
||||||
rtc_networks => ['sip','xmpp','webrtc'],
|
|
||||||
}));
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 201, "POST create reseller");
|
|
||||||
($reseller_id) = $res->header('Location') =~ m!/(\d+)$!;
|
|
||||||
ok($reseller_id, "got reseller_id") || die "we don't continue here";
|
|
||||||
|
|
||||||
$req = HTTP::Request->new('GET', $uri . "/api/resellers/$reseller_id");
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 200, "fetch POSTed reseller");
|
|
||||||
$data = JSON::from_json($res->decoded_content);
|
|
||||||
ok($data->{enable_rtc}, "reseller has rtc enabled");
|
|
||||||
|
|
||||||
$req = HTTP::Request->new('GET', $uri . "/api/rtcnetworks/$reseller_id");
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 200, "fetch rtcnetworks");
|
|
||||||
$data = JSON::from_json($res->decoded_content);
|
|
||||||
is($data->{networks}[0]{connector}, 'sip-connector', "rtcnetwork exists");
|
|
||||||
$network_tag = $data->{networks}[0]{tag};
|
|
||||||
|
|
||||||
diag("reseller id: $reseller_id , first network_tag: $network_tag");
|
|
||||||
|
|
||||||
$req = HTTP::Request->new('POST', $uri.'/api/billingprofiles/');
|
|
||||||
$req->header('Content-Type' => 'application/json');
|
|
||||||
$req->header('Prefer' => 'return=representation');
|
|
||||||
$req->content(JSON::to_json({
|
|
||||||
name => 'rtc test bprof ' . time,
|
|
||||||
handle => 'rtc_test_bprof_' . time,
|
|
||||||
reseller_id => $reseller_id,
|
|
||||||
}));
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 201, "POST create billingprofile");
|
|
||||||
($bprof_id) = $res->header('Location') =~ m!/(\d+)$!;
|
|
||||||
ok($bprof_id, "got bprof_id") || die "we don't continue here";
|
|
||||||
|
|
||||||
$req = HTTP::Request->new('POST', $uri.'/api/customercontacts/');
|
|
||||||
$req->header('Content-Type' => 'application/json');
|
|
||||||
$req->header('Prefer' => 'return=representation');
|
|
||||||
$req->content(JSON::to_json({
|
|
||||||
email => 'rtccustomer@ngcp.com',
|
|
||||||
reseller_id => $reseller_id,
|
|
||||||
}));
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 201, "POST create customercontact");
|
|
||||||
($customercontact_id) = $res->header('Location') =~ m!/(\d+)$!;
|
|
||||||
ok($customercontact_id, "got customercontact_id") || die "we don't continue here";
|
|
||||||
|
|
||||||
$req = HTTP::Request->new('POST', $uri.'/api/customers/');
|
|
||||||
$req->header('Content-Type' => 'application/json');
|
|
||||||
$req->header('Prefer' => 'return=representation');
|
|
||||||
$req->content(JSON::to_json({
|
|
||||||
contact_id => $customercontact_id,
|
|
||||||
billing_profile_id => $bprof_id,
|
|
||||||
reseller_id => $reseller_id,
|
|
||||||
status => 'active',
|
|
||||||
type => 'sipaccount',
|
|
||||||
}));
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 201, "POST create customer");
|
|
||||||
($customer_id) = $res->header('Location') =~ m!/(\d+)$!;
|
|
||||||
ok($customer_id, "got customer_id") || die "we don't continue here";
|
|
||||||
|
|
||||||
diag("customer id: $customer_id");
|
|
||||||
}
|
|
||||||
|
|
||||||
my ($sub1_id, $sub1_name, $sub2_id, $sub2_name);
|
|
||||||
{
|
|
||||||
$sub1_name = 'rtcsub' .int(rand(1000));
|
|
||||||
$sub2_name = 'rtcsub' .int(rand(1000));
|
|
||||||
|
|
||||||
$req = HTTP::Request->new('POST', $uri.'/api/subscribers/');
|
|
||||||
$req->header('Content-Type' => 'application/json');
|
|
||||||
$req->header('Prefer' => 'return=representation');
|
|
||||||
$req->content(JSON::to_json({
|
|
||||||
customer_id => $customer_id,
|
|
||||||
domain_id => $domain_id,
|
|
||||||
username => $sub1_name,
|
|
||||||
password => $sub1_name,
|
|
||||||
webusername => $sub1_name,
|
|
||||||
webpassword => $sub1_name,
|
|
||||||
}));
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 201, "POST create subscriber 1");
|
|
||||||
($sub1_id) = $res->header('Location') =~ m!/(\d+)$!;
|
|
||||||
ok($sub1_id, "got sub1_id") || die "we don't continue here";
|
|
||||||
|
|
||||||
$req = HTTP::Request->new('PATCH', $uri."/api/subscriberpreferences/$sub1_id");
|
|
||||||
$req->header('Content-Type' => 'application/json-patch+json');
|
|
||||||
$req->header('Prefer' => 'return=representation');
|
|
||||||
$req->content(JSON::to_json([
|
|
||||||
{op => 'add', path => '/use_rtpproxy', value => 'never'},
|
|
||||||
]));
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 200, "PATCH set subscriberpreferences sub1");
|
|
||||||
|
|
||||||
diag("subscriber $sub1_name\@$domain_name (pass: $sub1_name, id: $sub1_id)");
|
|
||||||
|
|
||||||
$req = HTTP::Request->new('POST', $uri.'/api/subscribers/');
|
|
||||||
$req->header('Content-Type' => 'application/json');
|
|
||||||
$req->header('Prefer' => 'return=representation');
|
|
||||||
$req->content(JSON::to_json({
|
|
||||||
customer_id => $customer_id,
|
|
||||||
domain_id => $domain_id,
|
|
||||||
username => $sub2_name,
|
|
||||||
password => $sub2_name,
|
|
||||||
webusername => $sub2_name,
|
|
||||||
webpassword => $sub2_name,
|
|
||||||
}));
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 201, "POST create subscriber 2");
|
|
||||||
($sub2_id) = $res->header('Location') =~ m!/(\d+)$!;
|
|
||||||
ok($sub2_id, "got sub2_id") || die "we don't continue here";
|
|
||||||
|
|
||||||
$req = HTTP::Request->new('PATCH', $uri."/api/subscriberpreferences/$sub2_id");
|
|
||||||
$req->header('Content-Type' => 'application/json-patch+json');
|
|
||||||
$req->header('Prefer' => 'return=representation');
|
|
||||||
$req->content(JSON::to_json([
|
|
||||||
{op => 'add', path => '/use_rtpproxy', value => 'never'},
|
|
||||||
]));
|
|
||||||
$res = $ua->request($req);
|
|
||||||
is($res->code, 200, "PATCH set subscriberpreferences sub2");
|
|
||||||
|
|
||||||
diag("subscriber $sub2_name\@$domain_name (pass: $sub2_name, id: $sub2_id)");
|
|
||||||
diag("you can now create new session using:");
|
|
||||||
my $noport_uri = ($uri =~ s/:[0-9]+//r);
|
|
||||||
diag(" curl -XPOST -v -k --user $sub1_name\@$domain_name:$sub1_name -H'Content-Type: application/json' $noport_uri/api/rtcsessions/ --data-binary '{}'");
|
|
||||||
diag(" curl -XPOST -v -k --user $sub2_name\@$domain_name:$sub2_name -H'Content-Type: application/json' $noport_uri/api/rtcsessions/ --data-binary '{}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
done_testing;
|
|
@ -1,91 +0,0 @@
|
|||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
use Test::More;
|
|
||||||
use Test::Collection;
|
|
||||||
use Test::FakeData;
|
|
||||||
use Data::Dumper;
|
|
||||||
|
|
||||||
|
|
||||||
unless ($ENV{TEST_RTC}) {
|
|
||||||
plan skip_all => "not testing rtc, enable TEST_RTC=yes to run tests";
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $fake_data = Test::FakeData->new;
|
|
||||||
$fake_data->set_data_from_script({
|
|
||||||
'resellers' => {
|
|
||||||
'data' => {
|
|
||||||
name => "apitest reseller name " . time(),
|
|
||||||
contract_id => sub { return shift->create('contracts', @_); },
|
|
||||||
status => 'active',
|
|
||||||
enable_rtc => 1, # JSON::false
|
|
||||||
rtc_networks => ['sip', 'xmpp', 'sipwise'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
my $test_machine = Test::Collection->new(
|
|
||||||
name => 'resellers',
|
|
||||||
embedded_resources => [qw/resellers/],
|
|
||||||
);
|
|
||||||
$test_machine->methods->{collection}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS)};
|
|
||||||
$test_machine->methods->{item}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS PUT PATCH DELETE)};
|
|
||||||
# store some basic reseller data, to run tests with
|
|
||||||
$test_machine->DATA_ITEM_STORE($fake_data->process('resellers'));
|
|
||||||
$test_machine->form_data_item( );
|
|
||||||
|
|
||||||
my $reseller_id;
|
|
||||||
|
|
||||||
# test reseller API
|
|
||||||
{
|
|
||||||
my ($res, $content) = $test_machine->check_item_get('/api/resellers/?page=1&rows=10', "fetch resellers collection");
|
|
||||||
my $req;
|
|
||||||
($res, $content, $req) = $test_machine->check_item_post();
|
|
||||||
is($res->code, 201, 'create test reseller successful');
|
|
||||||
#my $reseller_id = $test_machine->get_id_from_created($res);
|
|
||||||
($reseller_id) = $res->header('Location') =~ m/(\d+)$/;
|
|
||||||
|
|
||||||
cmp_ok($reseller_id, '>', 0, 'got valid reseller id');
|
|
||||||
($res, $content) = $test_machine->check_item_get("/api/resellers/$reseller_id/", "fetch created reseller");
|
|
||||||
is($res->code, 200, 'reseller successfully retrieved');
|
|
||||||
ok($content->{enable_rtc}, 'rtc is enabled on created reseller');
|
|
||||||
}
|
|
||||||
|
|
||||||
# test rtcnetworks API
|
|
||||||
{
|
|
||||||
my ($res, $content) = $test_machine->check_item_get("/api/rtcnetworks/$reseller_id", "fetch rtcnetwork");
|
|
||||||
is($res->code, 200, 'rtcnetwork successfully retrieved');
|
|
||||||
isa_ok($content->{networks}, 'ARRAY', 'networks arrayref exists');
|
|
||||||
is(scalar(@{ $content->{networks} }), 3, 'should contain the 3 precreated networks');
|
|
||||||
is($content->{networks}[0]{connector}, 'sip-connector', 'First network is of "sip-connector"');
|
|
||||||
|
|
||||||
($res, $content) = $test_machine->request_patch(
|
|
||||||
[
|
|
||||||
{ op => 'remove', path => '/networks/2'},
|
|
||||||
{ op => 'replace', path => '/networks/1/connector', value => 'webrtc'},
|
|
||||||
],
|
|
||||||
"/api/rtcnetworks/$reseller_id/",
|
|
||||||
);
|
|
||||||
is($res->code, 200, 'PATCH operation on rtcnetworks item');
|
|
||||||
isa_ok($content->{networks}, 'ARRAY', 'networks arrayref exists');
|
|
||||||
is(scalar(@{ $content->{networks} }), 2, 'should be left with 2 networks');
|
|
||||||
is($content->{networks}[1]{connector}, 'webrtc', 'Changed one network to "webrtc"');
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
my ($res, $content, $req) = $test_machine->request_patch(
|
|
||||||
[
|
|
||||||
{ op => 'replace', path => '/status', value => 'terminated' },
|
|
||||||
],
|
|
||||||
"/api/resellers/$reseller_id/",
|
|
||||||
);
|
|
||||||
is($res->code, 200, 'terminate reseller successful');
|
|
||||||
}
|
|
||||||
$test_machine->clear_test_data_all();
|
|
||||||
|
|
||||||
done_testing;
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
||||||
# vim: set tabstop=4 expandtab:
|
|
Loading…
Reference in new issue