TT#29620 Switch Perl code from Windows \r\n to Unix \n

The only JS and json data left in Windows style:

14:19:58 ✔ taurus:(master)~/sipwise/git/ngcp-panel$ ack -l "\r\n"
share/static/js/jquery.loadJSON.js
share/static/js/libs/svg-edit/config-sample.js
share/static/js/libs/svg-edit/canvg/canvg.js
share/static/js/libs/svg-edit/contextmenu/jquery.contextMenu.js
share/static/js/libs/svg-edit/jquery-ui/jquery-ui-1.8.custom.js
share/static/js/libs/svg-edit/extensions/webappfind-icon.svg
share/static/js/libs/svg-edit/extensions/shapelib/animal.json
share/static/js/libs/svg-edit/extensions/shapelib/object.json
share/static/js/libs/svg-edit/extensions/shapelib/electronics.json
share/static/js/libs/svg-edit/extensions/shapelib/misc.json
share/static/js/libs/svg-edit/extensions/shapelib/game.json
share/static/js/libs/svg-edit/extensions/shapelib/flowchart.json
share/static/js/libs/svg-edit/extensions/shapelib/raphael.txt
share/static/js/libs/svg-edit/extensions/shapelib/raphael_1.json
share/static/js/libs/svg-edit/extensions/shapelib/symbol.json
share/static/js/libs/svg-edit/extensions/shapelib/music.json
share/static/js/libs/svg-edit/extensions/shapelib/arrow.json
share/static/js/libs/svg-edit/extensions/shapelib/raphael_2.json
share/static/js/libs/svg-edit/extensions/shapelib/math.json
share/static/js/libs/svg-edit/extensions/shapelib/dialog_balloon.json
share/static/js/libs/svg-edit/extensions/ext-xdomain-messaging.js
share/static/js/libs/svg-edit-2.6/jquery-ui/jquery-ui-1.8.custom.js
share/static/js/jquery.dump.js
14:19:58 ✔ taurus:(master)~/sipwise/git/ngcp-panel$

Change-Id: Ia6245db0528abf0902fe5e62cff26de294510dd4
changes/16/21216/4
Alexander Lutay 8 years ago
parent cdbc01978c
commit a9b94c4808

@ -1,71 +1,71 @@
package NGCP::Panel::Role::Journal;
use Sipwise::Base;
use NGCP::Panel::Utils::Journal;
sub add_create_journal_item_hal {
my ($self,$c,@args) = @_;
return NGCP::Panel::Utils::Journal::add_journal_item_hal($self,$c,NGCP::Panel::Utils::Journal::CREATE_JOURNAL_OP,@args);
}
sub add_update_journal_item_hal {
my ($self,$c,@args) = @_;
return NGCP::Panel::Utils::Journal::add_journal_item_hal($self,$c,NGCP::Panel::Utils::Journal::UPDATE_JOURNAL_OP,@args);
}
sub add_delete_journal_item_hal {
my ($self,$c,@args) = @_;
return NGCP::Panel::Utils::Journal::add_journal_item_hal($self,$c,NGCP::Panel::Utils::Journal::DELETE_JOURNAL_OP,@args);
}
sub get_journal_action_config {
my ($class,$resource_name,$action_template) = @_;
my $cfg = NGCP::Panel::Utils::Journal::get_journal_resource_config(NGCP::Panel->config,$resource_name);
if ($cfg->{journal_resource_enabled}) {
return NGCP::Panel::Utils::Journal::get_api_journal_action_config('api/' . $resource_name,$action_template,$class->get_journal_methods);
}
return [];
}
sub get_journal_query_params {
my ($class,$query_params) = @_;
return NGCP::Panel::Utils::Journal::get_api_journal_query_params($query_params);
}
sub handle_item_base_journal {
return NGCP::Panel::Utils::Journal::handle_api_item_base_journal(@_);
}
sub handle_journals_get {
return NGCP::Panel::Utils::Journal::handle_api_journals_get(@_);
}
sub handle_journalsitem_get {
return NGCP::Panel::Utils::Journal::handle_api_journalsitem_get(@_);
}
sub handle_journals_options {
return NGCP::Panel::Utils::Journal::handle_api_journals_options(@_);
}
sub handle_journalsitem_options {
return NGCP::Panel::Utils::Journal::handle_api_journalsitem_options(@_);
}
sub handle_journals_head {
return NGCP::Panel::Utils::Journal::handle_api_journals_head(@_);
}
sub handle_journalsitem_head {
return NGCP::Panel::Utils::Journal::handle_api_journalsitem_head(@_);
}
sub get_journal_relation_link {
my $cfg = NGCP::Panel::Utils::Journal::get_journal_resource_config(NGCP::Panel->config,$_[0]->resource_name);
if ($cfg->{journal_resource_enabled}) {
return NGCP::Panel::Utils::Journal::get_journal_relation_link(@_);
}
return ();
}
1;
package NGCP::Panel::Role::Journal;
use Sipwise::Base;
use NGCP::Panel::Utils::Journal;
sub add_create_journal_item_hal {
my ($self,$c,@args) = @_;
return NGCP::Panel::Utils::Journal::add_journal_item_hal($self,$c,NGCP::Panel::Utils::Journal::CREATE_JOURNAL_OP,@args);
}
sub add_update_journal_item_hal {
my ($self,$c,@args) = @_;
return NGCP::Panel::Utils::Journal::add_journal_item_hal($self,$c,NGCP::Panel::Utils::Journal::UPDATE_JOURNAL_OP,@args);
}
sub add_delete_journal_item_hal {
my ($self,$c,@args) = @_;
return NGCP::Panel::Utils::Journal::add_journal_item_hal($self,$c,NGCP::Panel::Utils::Journal::DELETE_JOURNAL_OP,@args);
}
sub get_journal_action_config {
my ($class,$resource_name,$action_template) = @_;
my $cfg = NGCP::Panel::Utils::Journal::get_journal_resource_config(NGCP::Panel->config,$resource_name);
if ($cfg->{journal_resource_enabled}) {
return NGCP::Panel::Utils::Journal::get_api_journal_action_config('api/' . $resource_name,$action_template,$class->get_journal_methods);
}
return [];
}
sub get_journal_query_params {
my ($class,$query_params) = @_;
return NGCP::Panel::Utils::Journal::get_api_journal_query_params($query_params);
}
sub handle_item_base_journal {
return NGCP::Panel::Utils::Journal::handle_api_item_base_journal(@_);
}
sub handle_journals_get {
return NGCP::Panel::Utils::Journal::handle_api_journals_get(@_);
}
sub handle_journalsitem_get {
return NGCP::Panel::Utils::Journal::handle_api_journalsitem_get(@_);
}
sub handle_journals_options {
return NGCP::Panel::Utils::Journal::handle_api_journals_options(@_);
}
sub handle_journalsitem_options {
return NGCP::Panel::Utils::Journal::handle_api_journalsitem_options(@_);
}
sub handle_journals_head {
return NGCP::Panel::Utils::Journal::handle_api_journals_head(@_);
}
sub handle_journalsitem_head {
return NGCP::Panel::Utils::Journal::handle_api_journalsitem_head(@_);
}
sub get_journal_relation_link {
my $cfg = NGCP::Panel::Utils::Journal::get_journal_resource_config(NGCP::Panel->config,$_[0]->resource_name);
if ($cfg->{journal_resource_enabled}) {
return NGCP::Panel::Utils::Journal::get_journal_relation_link(@_);
}
return ();
}
1;

@ -1,111 +1,111 @@
package NGCP::Panel::Utils::API::Calllist;
use strict;
use warnings;
use HTTP::Status qw(:constants);
sub get_owner_data {
my ($self, $c, $schema, $source) = @_;
my $ret;
$source //= $c->req->params;
my $src_subscriber_id = $source->{subscriber_id};
my $src_customer_id = $source->{customer_id};
if($c->user->roles eq "admin" || $c->user->roles eq "reseller") {
if($src_subscriber_id) {
my $sub = $schema->resultset('voip_subscribers')->find($src_subscriber_id);
unless($sub) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
if($c->user->roles eq "reseller" && $sub->contract->contact->reseller_id != $c->user->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
return {
subscriber => $sub,
customer => $sub->contract,
};
} elsif($src_customer_id) {
my $cust = $schema->resultset('contracts')->find($src_customer_id);
unless($cust && $cust->contact->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'customer_id'.");
return;
}
if($c->user->roles eq "reseller" && $cust->contact->reseller_id != $c->user->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'customer_id'.");
return;
}
return {
subscriber => undef,
customer => $cust,
};
} else {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Mandatory parameter 'subscriber_id' or 'customer_id' missing in request");
return;
}
} elsif($c->user->roles eq "subscriberadmin") {
if($src_subscriber_id) {
my $sub = $schema->resultset('voip_subscribers')->find($src_subscriber_id);
unless($sub) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
if($sub->contract_id != $c->user->account_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
return {
subscriber => $sub,
customer => $sub->contract,
};
} else {
my $cust = $schema->resultset('contracts')->find($c->user->account_id);
unless($cust && $cust->contact->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'customer_id'.");
return;
}
return {
subscriber => undef,
customer => $cust,
};
}
} elsif($c->user->roles eq "subscriber") {
return {
subscriber => $c->user->voip_subscriber,
customer => $c->user->voip_subscriber->contract,
};
} else {
$self->error($c, HTTP_NOT_FOUND, "Unknown role '".$c->user->roles."' of the user.");
return;
}
}
1;
=head1 NAME
NGCP::Panel::Utils::API::Calllist
=head1 DESCRIPTION
A temporary helper to manipulate calls related data in REST API modules
=head1 METHODS
=head2 get_owner_data
Check if mandatory calls list parameters customer_id or subscriber_id are presented and get proper objects.
=head1 AUTHOR
Irina Peshinskaya
=head1 LICENSE
This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
# vim: set tabstop=4 expandtab:
package NGCP::Panel::Utils::API::Calllist;
use strict;
use warnings;
use HTTP::Status qw(:constants);
sub get_owner_data {
my ($self, $c, $schema, $source) = @_;
my $ret;
$source //= $c->req->params;
my $src_subscriber_id = $source->{subscriber_id};
my $src_customer_id = $source->{customer_id};
if($c->user->roles eq "admin" || $c->user->roles eq "reseller") {
if($src_subscriber_id) {
my $sub = $schema->resultset('voip_subscribers')->find($src_subscriber_id);
unless($sub) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
if($c->user->roles eq "reseller" && $sub->contract->contact->reseller_id != $c->user->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
return {
subscriber => $sub,
customer => $sub->contract,
};
} elsif($src_customer_id) {
my $cust = $schema->resultset('contracts')->find($src_customer_id);
unless($cust && $cust->contact->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'customer_id'.");
return;
}
if($c->user->roles eq "reseller" && $cust->contact->reseller_id != $c->user->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'customer_id'.");
return;
}
return {
subscriber => undef,
customer => $cust,
};
} else {
$self->error($c, HTTP_UNPROCESSABLE_ENTITY, "Mandatory parameter 'subscriber_id' or 'customer_id' missing in request");
return;
}
} elsif($c->user->roles eq "subscriberadmin") {
if($src_subscriber_id) {
my $sub = $schema->resultset('voip_subscribers')->find($src_subscriber_id);
unless($sub) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
if($sub->contract_id != $c->user->account_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'subscriber_id'.");
return;
}
return {
subscriber => $sub,
customer => $sub->contract,
};
} else {
my $cust = $schema->resultset('contracts')->find($c->user->account_id);
unless($cust && $cust->contact->reseller_id) {
$self->error($c, HTTP_NOT_FOUND, "Invalid 'customer_id'.");
return;
}
return {
subscriber => undef,
customer => $cust,
};
}
} elsif($c->user->roles eq "subscriber") {
return {
subscriber => $c->user->voip_subscriber,
customer => $c->user->voip_subscriber->contract,
};
} else {
$self->error($c, HTTP_NOT_FOUND, "Unknown role '".$c->user->roles."' of the user.");
return;
}
}
1;
=head1 NAME
NGCP::Panel::Utils::API::Calllist
=head1 DESCRIPTION
A temporary helper to manipulate calls related data in REST API modules
=head1 METHODS
=head2 get_owner_data
Check if mandatory calls list parameters customer_id or subscriber_id are presented and get proper objects.
=head1 AUTHOR
Irina Peshinskaya
=head1 LICENSE
This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
# vim: set tabstop=4 expandtab:

@ -1,66 +1,66 @@
package NGCP::Panel::Utils::API::Subscribers;
use strict;
use warnings;
use HTTP::Status qw(:constants);
sub get_active_subscriber{
my($api, $c, $id, $params) = @_;
my $sub_rs = $c->model('DB')->resultset('voip_subscribers')->search({
'me.id' => $id,
'me.status' => { '!=' => 'terminated' },
});
if($c->user->roles eq "admin") {
} elsif($c->user->roles eq "reseller") {
$sub_rs = $sub_rs->search({
'contact.reseller_id' => $c->user->reseller_id,
},{
join => { contract => 'contact' },
});
} elsif($c->user->roles eq "subscriberadmin") {
$sub_rs = $sub_rs->search({
'contract.id' => $c->user->account_id,
},{
join => { 'contract' },
});
} elsif($c->user->roles eq "subscriber") {
$sub_rs = $sub_rs->search({
'me.uuid' => $c->user->uuid,
});
}
my $sub = $sub_rs->first;
unless($sub && $sub->provisioning_voip_subscriber) {
$c->log->error($params->{error_log} ? $params->{error_log} : "invalid subscriber_id '$id'"); # TODO: user, message, trace, ...
$api->error($c, HTTP_UNPROCESSABLE_ENTITY, $params->{error} ? $params->{error} : "No subscriber for subscriber_id found");
return;
}
return $sub;
}
1;
=head1 NAME
NGCP::Panel::Utils::API::Subscribers
=head1 DESCRIPTION
A temporary helper to manipulate subscribers related data in REST API modules
=head1 METHODS
=head2 get_active_subscriber
Get subscriber NGCP::Schema::Result object of the active subscriber by the mandatory form parameter subscriber_id.
=head1 AUTHOR
Irina Peshinskaya
=head1 LICENSE
This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
# vim: set tabstop=4 expandtab:
package NGCP::Panel::Utils::API::Subscribers;
use strict;
use warnings;
use HTTP::Status qw(:constants);
sub get_active_subscriber{
my($api, $c, $id, $params) = @_;
my $sub_rs = $c->model('DB')->resultset('voip_subscribers')->search({
'me.id' => $id,
'me.status' => { '!=' => 'terminated' },
});
if($c->user->roles eq "admin") {
} elsif($c->user->roles eq "reseller") {
$sub_rs = $sub_rs->search({
'contact.reseller_id' => $c->user->reseller_id,
},{
join => { contract => 'contact' },
});
} elsif($c->user->roles eq "subscriberadmin") {
$sub_rs = $sub_rs->search({
'contract.id' => $c->user->account_id,
},{
join => { 'contract' },
});
} elsif($c->user->roles eq "subscriber") {
$sub_rs = $sub_rs->search({
'me.uuid' => $c->user->uuid,
});
}
my $sub = $sub_rs->first;
unless($sub && $sub->provisioning_voip_subscriber) {
$c->log->error($params->{error_log} ? $params->{error_log} : "invalid subscriber_id '$id'"); # TODO: user, message, trace, ...
$api->error($c, HTTP_UNPROCESSABLE_ENTITY, $params->{error} ? $params->{error} : "No subscriber for subscriber_id found");
return;
}
return $sub;
}
1;
=head1 NAME
NGCP::Panel::Utils::API::Subscribers
=head1 DESCRIPTION
A temporary helper to manipulate subscribers related data in REST API modules
=head1 METHODS
=head2 get_active_subscriber
Get subscriber NGCP::Schema::Result object of the active subscriber by the mandatory form parameter subscriber_id.
=head1 AUTHOR
Irina Peshinskaya
=head1 LICENSE
This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
# vim: set tabstop=4 expandtab:

@ -1,251 +1,251 @@
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use NGCP::Schema;
use NGCP::Panel::Utils::Subscriber;
use NGCP::Panel::Utils::Preferences;
use Test::More;
use Data::HAL qw();
use Data::HAL::Link qw();
use Safe::Isa qw($_isa);
use NGCP::Panel::Form::CFSimpleAPI;
my $schema = NGCP::Schema->connect();
my $ql_exists = 0;
my ($ql,$ana);
if($ql_exists){
#use DBIx::Class::QueryLog;
#use DBIx::Class::QueryLog::Analyzer;
my $ql = DBIx::Class::QueryLog->new;
$schema->storage->debugobj($ql);
$schema->storage->debug(1);
my $ana = DBIx::Class::QueryLog::Analyzer->new({ querylog => $ql });
$ql->bucket('origin');
}
my $time = time();
print "start;\n";
#print Dumper($schema);
my $item_rs = $schema->resultset('voip_subscribers')->search( {
'me.status' => { '!=' => 'terminated' }
},{
prefetch => { 'provisioning_voip_subscriber'=>'voip_cf_mappings'},
#prefetch => 'provisioning_voip_subscriber',
rows => 200,
},
);
my (@arr_orig,@arr_opt);
for my $item ($item_rs->all) {
# print Dumper({$item->get_inflated_columns});
my %resource = ();
my $prov_subs = $item->provisioning_voip_subscriber;
for my $cf_type (qw/cfu cfb cft cfna cfs/) {
my $mapping = $schema->resultset('voip_cf_mappings')->search({
subscriber_id => $prov_subs->id,
type => $cf_type,
})->first;
if ($mapping) {
$resource{$cf_type} = _contents_from_cfm($mapping, $item);
} else {
$resource{$cf_type} = {};
}
}
if(keys %{$resource{cft}}){
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => undef, attribute => 'ringtimeout', prov_subscriber => $prov_subs, schema => $schema )->first;
$ringtimeout_preference = $ringtimeout_preference ? $ringtimeout_preference->value : undef;
$resource{cft}{ringtimeout} = $ringtimeout_preference;
}
additional_processing($item, \%resource);
push @arr_orig, \%resource;
}
print "1.time=".(time()-$time).";\n";
#exit;
if($ql_exists){
$ql->bucket('optimized');
}
$time = time();
for my $item ($item_rs->all) {
my %resource = ();
my $prov_subs = $item->provisioning_voip_subscriber;
@resource{qw/cfu cfb cft cfna cfs/} = ({}) x 5;
for my $item_cf ($item->provisioning_voip_subscriber->voip_cf_mappings->all){
$resource{$item_cf->type} = _contents_from_cfm($item_cf, $item);
}
if(keys %{$resource{cft}}){
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => undef, attribute => 'ringtimeout', prov_subscriber => $prov_subs, schema => $schema )->first;
$ringtimeout_preference = $ringtimeout_preference ? $ringtimeout_preference->value : undef;
$resource{cft}{ringtimeout} = $ringtimeout_preference;
}
additional_processing($item, \%resource);
push @arr_opt, \%resource;
}
print "2.time=".(time()-$time).";\n";
is_deeply(\@arr_orig, \@arr_opt, "check that arrays are equiv");
#print Dumper[\@arr_orig, \@arr_opt];
if($ql_exists){
print Dumper $ana->get_totaled_queries_by_bucket;
}
sub additional_processing{
my($item,$resource) = @_;
my $type='';
my %resource=%$resource;
my $hal = Data::HAL->new(
links => [
Data::HAL::Link->new(
relation => 'curies',
href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
name => 'ngcp',
templated => 1,
),
Data::HAL::Link->new(relation => 'collection', href => sprintf("%s", '')),
Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
Data::HAL::Link->new(relation => 'self', href => sprintf("%s%s", '', $item->id)),
Data::HAL::Link->new(relation => "ngcp:$type", href => sprintf("/api/%s/%s", $type, $item->id)),
Data::HAL::Link->new(relation => 'ngcp:subscribers', href => sprintf("/api/subscribers/%d", $item->id)),
],
relation => 'ngcp:callforwards',
);
my $form=NGCP::Panel::Form::CFSimpleAPI->new();
validate_form(
form => $form,
resource => \%resource,
run => 0,
);
$hal->resource(\%resource);
}
sub _contents_from_cfm {
my ($cfm_item, $sub) = @_;
my (@times, @destinations);
my $timeset_item = $cfm_item->time_set;
my $dset_item = $cfm_item->destination_set;
for my $time ($timeset_item ? $timeset_item->voip_cf_periods->all : () ) {
push @times, {$time->get_inflated_columns};
delete @{$times[-1]}{'time_set_id', 'id'};
}
for my $dest ($dset_item ? $dset_item->voip_cf_destinations->all : () ) {
my ($d, $duri) = NGCP::Panel::Utils::Subscriber::destination_to_field($dest->destination);
my $deflated;
if($d eq "uri") {
$deflated = NGCP::Panel::Utils::Subscriber::uri_deflate(undef, $duri,$sub) if $d eq "uri";
$d = $dest->destination;
}
push @destinations, {$dest->get_inflated_columns,
destination => $d,
$deflated ? (simple_destination => $deflated) : (),
};
delete @{$destinations[-1]}{'destination_set_id', 'id'};
}
return {times => \@times, destinations => \@destinations};
}
sub validate_form {
my (%params) = @_;
my $resource = $params{resource};
my $form = $params{form};
my $run = $params{run} // 1;
my $exceptions = $params{exceptions} // [];
my $form_params = $params{form_params} // {};
push @{ $exceptions }, "external_id";
my @normalized = ();
# move {xxx_id} into {xxx}{id} for FormHandler
foreach my $key(keys %{ $resource } ) {
my $skip_normalize = grep {/^$key$/} @{ $exceptions };
if($key =~ /^(.+)_id$/ && !$skip_normalize && !exists $resource->{$1}) {
push @normalized, $1;
$resource->{$1}{id} = delete $resource->{$key};
}
}
# remove unknown keys
my %fields = map { $_->name => $_ } $form->fields;
validate_fields($resource, \%fields, $run);
if($run) {
# check keys/vals
$form->process(params => $resource, posted => 1, %{$form_params} );
unless($form->validated) {
my $e = join '; ', map {
sprintf 'field=\'%s\', input=\'%s\', errors=\'%s\'',
($_->parent->$_isa('HTML::FormHandler::Field') ? $_->parent->name . '_' : '') . $_->name,
$_->input // '',
join('', @{ $_->errors })
} $form->error_fields;
return;
}
}
# move {xxx}{id} back into {xxx_id} for DB
foreach my $key(@normalized) {
next unless(exists $resource->{$key});
$resource->{$key . '_id'} = defined($resource->{$key}{id}) ?
int($resource->{$key}{id}) :
$resource->{$key}{id};
delete $resource->{$key};
}
return 1;
}
sub validate_fields {
my ($resource, $fields, $run) = @_;
for my $k (keys %{ $resource }) {
#if($resource->{$k}->$_isa('JSON::XS::Boolean') || $resource->{$k}->$_isa('JSON::PP::Boolean')) {
if($resource->{$k}->$_isa('JSON::PP::Boolean')) {
$resource->{$k} = $resource->{$k} ? 1 : 0;
}
unless(exists $fields->{$k}) {
delete $resource->{$k};
}
$resource->{$k} = DateTime::Format::RFC3339->format_datetime($resource->{$k})
if $resource->{$k}->$_isa('DateTime');
$resource->{$k} = $resource->{$k} + 0
if(defined $resource->{$k} && (
$fields->{$k}->$_isa('HTML::FormHandler::Field::Integer') ||
$fields->{$k}->$_isa('HTML::FormHandler::Field::Money') ||
$fields->{$k}->$_isa('HTML::FormHandler::Field::Float')) &&
(is_int($resource->{$k}) || is_decimal($resource->{$k})));
if (defined $resource->{$k} &&
$fields->{$k}->$_isa('HTML::FormHandler::Field::Repeatable') &&
"ARRAY" eq ref $resource->{$k} ) {
for my $elem (@{ $resource->{$k} }) {
my ($subfield_instance) = $fields->{$k}->fields;
my %subfields = map { $_->name => $_ } $subfield_instance->fields;
validate_fields($elem, \%subfields, $run);
}
}
# only do this for converting back from obj to hal
# otherwise it breaks db fields with the \0 and \1 notation
unless($run) {
$resource->{$k} = $resource->{$k} ? JSON::true : JSON::false
if(defined $resource->{$k} &&
$fields->{$k}->$_isa('HTML::FormHandler::Field::Boolean'));
}
}
return 1;
}
1;
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use NGCP::Schema;
use NGCP::Panel::Utils::Subscriber;
use NGCP::Panel::Utils::Preferences;
use Test::More;
use Data::HAL qw();
use Data::HAL::Link qw();
use Safe::Isa qw($_isa);
use NGCP::Panel::Form::CFSimpleAPI;
my $schema = NGCP::Schema->connect();
my $ql_exists = 0;
my ($ql,$ana);
if($ql_exists){
#use DBIx::Class::QueryLog;
#use DBIx::Class::QueryLog::Analyzer;
my $ql = DBIx::Class::QueryLog->new;
$schema->storage->debugobj($ql);
$schema->storage->debug(1);
my $ana = DBIx::Class::QueryLog::Analyzer->new({ querylog => $ql });
$ql->bucket('origin');
}
my $time = time();
print "start;\n";
#print Dumper($schema);
my $item_rs = $schema->resultset('voip_subscribers')->search( {
'me.status' => { '!=' => 'terminated' }
},{
prefetch => { 'provisioning_voip_subscriber'=>'voip_cf_mappings'},
#prefetch => 'provisioning_voip_subscriber',
rows => 200,
},
);
my (@arr_orig,@arr_opt);
for my $item ($item_rs->all) {
# print Dumper({$item->get_inflated_columns});
my %resource = ();
my $prov_subs = $item->provisioning_voip_subscriber;
for my $cf_type (qw/cfu cfb cft cfna cfs/) {
my $mapping = $schema->resultset('voip_cf_mappings')->search({
subscriber_id => $prov_subs->id,
type => $cf_type,
})->first;
if ($mapping) {
$resource{$cf_type} = _contents_from_cfm($mapping, $item);
} else {
$resource{$cf_type} = {};
}
}
if(keys %{$resource{cft}}){
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => undef, attribute => 'ringtimeout', prov_subscriber => $prov_subs, schema => $schema )->first;
$ringtimeout_preference = $ringtimeout_preference ? $ringtimeout_preference->value : undef;
$resource{cft}{ringtimeout} = $ringtimeout_preference;
}
additional_processing($item, \%resource);
push @arr_orig, \%resource;
}
print "1.time=".(time()-$time).";\n";
#exit;
if($ql_exists){
$ql->bucket('optimized');
}
$time = time();
for my $item ($item_rs->all) {
my %resource = ();
my $prov_subs = $item->provisioning_voip_subscriber;
@resource{qw/cfu cfb cft cfna cfs/} = ({}) x 5;
for my $item_cf ($item->provisioning_voip_subscriber->voip_cf_mappings->all){
$resource{$item_cf->type} = _contents_from_cfm($item_cf, $item);
}
if(keys %{$resource{cft}}){
my $ringtimeout_preference = NGCP::Panel::Utils::Preferences::get_usr_preference_rs(
c => undef, attribute => 'ringtimeout', prov_subscriber => $prov_subs, schema => $schema )->first;
$ringtimeout_preference = $ringtimeout_preference ? $ringtimeout_preference->value : undef;
$resource{cft}{ringtimeout} = $ringtimeout_preference;
}
additional_processing($item, \%resource);
push @arr_opt, \%resource;
}
print "2.time=".(time()-$time).";\n";
is_deeply(\@arr_orig, \@arr_opt, "check that arrays are equiv");
#print Dumper[\@arr_orig, \@arr_opt];
if($ql_exists){
print Dumper $ana->get_totaled_queries_by_bucket;
}
sub additional_processing{
my($item,$resource) = @_;
my $type='';
my %resource=%$resource;
my $hal = Data::HAL->new(
links => [
Data::HAL::Link->new(
relation => 'curies',
href => 'http://purl.org/sipwise/ngcp-api/#rel-{rel}',
name => 'ngcp',
templated => 1,
),
Data::HAL::Link->new(relation => 'collection', href => sprintf("%s", '')),
Data::HAL::Link->new(relation => 'profile', href => 'http://purl.org/sipwise/ngcp-api/'),
Data::HAL::Link->new(relation => 'self', href => sprintf("%s%s", '', $item->id)),
Data::HAL::Link->new(relation => "ngcp:$type", href => sprintf("/api/%s/%s", $type, $item->id)),
Data::HAL::Link->new(relation => 'ngcp:subscribers', href => sprintf("/api/subscribers/%d", $item->id)),
],
relation => 'ngcp:callforwards',
);
my $form=NGCP::Panel::Form::CFSimpleAPI->new();
validate_form(
form => $form,
resource => \%resource,
run => 0,
);
$hal->resource(\%resource);
}
sub _contents_from_cfm {
my ($cfm_item, $sub) = @_;
my (@times, @destinations);
my $timeset_item = $cfm_item->time_set;
my $dset_item = $cfm_item->destination_set;
for my $time ($timeset_item ? $timeset_item->voip_cf_periods->all : () ) {
push @times, {$time->get_inflated_columns};
delete @{$times[-1]}{'time_set_id', 'id'};
}
for my $dest ($dset_item ? $dset_item->voip_cf_destinations->all : () ) {
my ($d, $duri) = NGCP::Panel::Utils::Subscriber::destination_to_field($dest->destination);
my $deflated;
if($d eq "uri") {
$deflated = NGCP::Panel::Utils::Subscriber::uri_deflate(undef, $duri,$sub) if $d eq "uri";
$d = $dest->destination;
}
push @destinations, {$dest->get_inflated_columns,
destination => $d,
$deflated ? (simple_destination => $deflated) : (),
};
delete @{$destinations[-1]}{'destination_set_id', 'id'};
}
return {times => \@times, destinations => \@destinations};
}
sub validate_form {
my (%params) = @_;
my $resource = $params{resource};
my $form = $params{form};
my $run = $params{run} // 1;
my $exceptions = $params{exceptions} // [];
my $form_params = $params{form_params} // {};
push @{ $exceptions }, "external_id";
my @normalized = ();
# move {xxx_id} into {xxx}{id} for FormHandler
foreach my $key(keys %{ $resource } ) {
my $skip_normalize = grep {/^$key$/} @{ $exceptions };
if($key =~ /^(.+)_id$/ && !$skip_normalize && !exists $resource->{$1}) {
push @normalized, $1;
$resource->{$1}{id} = delete $resource->{$key};
}
}
# remove unknown keys
my %fields = map { $_->name => $_ } $form->fields;
validate_fields($resource, \%fields, $run);
if($run) {
# check keys/vals
$form->process(params => $resource, posted => 1, %{$form_params} );
unless($form->validated) {
my $e = join '; ', map {
sprintf 'field=\'%s\', input=\'%s\', errors=\'%s\'',
($_->parent->$_isa('HTML::FormHandler::Field') ? $_->parent->name . '_' : '') . $_->name,
$_->input // '',
join('', @{ $_->errors })
} $form->error_fields;
return;
}
}
# move {xxx}{id} back into {xxx_id} for DB
foreach my $key(@normalized) {
next unless(exists $resource->{$key});
$resource->{$key . '_id'} = defined($resource->{$key}{id}) ?
int($resource->{$key}{id}) :
$resource->{$key}{id};
delete $resource->{$key};
}
return 1;
}
sub validate_fields {
my ($resource, $fields, $run) = @_;
for my $k (keys %{ $resource }) {
#if($resource->{$k}->$_isa('JSON::XS::Boolean') || $resource->{$k}->$_isa('JSON::PP::Boolean')) {
if($resource->{$k}->$_isa('JSON::PP::Boolean')) {
$resource->{$k} = $resource->{$k} ? 1 : 0;
}
unless(exists $fields->{$k}) {
delete $resource->{$k};
}
$resource->{$k} = DateTime::Format::RFC3339->format_datetime($resource->{$k})
if $resource->{$k}->$_isa('DateTime');
$resource->{$k} = $resource->{$k} + 0
if(defined $resource->{$k} && (
$fields->{$k}->$_isa('HTML::FormHandler::Field::Integer') ||
$fields->{$k}->$_isa('HTML::FormHandler::Field::Money') ||
$fields->{$k}->$_isa('HTML::FormHandler::Field::Float')) &&
(is_int($resource->{$k}) || is_decimal($resource->{$k})));
if (defined $resource->{$k} &&
$fields->{$k}->$_isa('HTML::FormHandler::Field::Repeatable') &&
"ARRAY" eq ref $resource->{$k} ) {
for my $elem (@{ $resource->{$k} }) {
my ($subfield_instance) = $fields->{$k}->fields;
my %subfields = map { $_->name => $_ } $subfield_instance->fields;
validate_fields($elem, \%subfields, $run);
}
}
# only do this for converting back from obj to hal
# otherwise it breaks db fields with the \0 and \1 notation
unless($run) {
$resource->{$k} = $resource->{$k} ? JSON::true : JSON::false
if(defined $resource->{$k} &&
$fields->{$k}->$_isa('HTML::FormHandler::Field::Boolean'));
}
}
return 1;
}
1;

@ -1,13 +1,13 @@
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use NGCP::Panel::Form::CFSimpleAPI;
for(my $i=0; $i<200;$i++){
my $form=NGCP::Panel::Form::CFSimpleAPI->new();
}
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use NGCP::Panel::Form::CFSimpleAPI;
for(my $i=0; $i<200;$i++){
my $form=NGCP::Panel::Form::CFSimpleAPI->new();
}
1;

@ -1,58 +1,58 @@
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use NGCP::Schema;
use NGCP::Panel::Utils::Preferences;
use NGCP::Panel::Utils::Generic qw(:all);
use Safe::Isa qw($_isa);
my $logger = Log::Log4perl->get_logger('NGCP::Panel');
my $schema = NGCP::Schema->connect();
my $dbh = $schema->storage->dbh;
use Test::MockObject;
my $c_mock = Test::MockObject->new();
my $user_mock = Test::MockObject->new();
$user_mock->set_always( 'roles' => 'reseller' );
$c_mock->set_always( 'log' => $logger )->set_always( 'model' => $schema )->set_always( 'user' => $user_mock );
my $cnt = 1000;
my $devmod_id = 1;
my $time = time;
for(my $i=0; $i<$cnt; $i++){
my $dev_pref_rs = NGCP::Panel::Utils::Preferences::get_preferences_rs(
c => $c_mock,
type => 'dev',
id => $devmod_id,
);
my $pref_values = get_inflated_columns_all($dev_pref_rs,'hash' => 'attribute', 'column' => 'value', 'force_array' => 1);
}
print "pure.time=".(time-$time).";\n";
my $time = time;
for(my $i=0; $i<$cnt; $i++){
my $devprof_pref_rs = $c_mock->model('DB')
->resultset('voip_preferences')
->search({
'profile.id' => $devmod_id,
},{
prefetch => {'voip_devprof_preferences' => 'profile'},
});
my %pref_values;
foreach my $value($devprof_pref_rs->all) {
$pref_values{$value->attribute} =
[ map {$_->value} $value->voip_devprof_preferences->all ];
}
}
print "DBIx.time=".(time-$time).";\n";
#pure.time=5;
#DBIx.time=14;
r
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use NGCP::Schema;
use NGCP::Panel::Utils::Preferences;
use NGCP::Panel::Utils::Generic qw(:all);
use Safe::Isa qw($_isa);
my $logger = Log::Log4perl->get_logger('NGCP::Panel');
my $schema = NGCP::Schema->connect();
my $dbh = $schema->storage->dbh;
use Test::MockObject;
my $c_mock = Test::MockObject->new();
my $user_mock = Test::MockObject->new();
$user_mock->set_always( 'roles' => 'reseller' );
$c_mock->set_always( 'log' => $logger )->set_always( 'model' => $schema )->set_always( 'user' => $user_mock );
my $cnt = 1000;
my $devmod_id = 1;
my $time = time;
for(my $i=0; $i<$cnt; $i++){
my $dev_pref_rs = NGCP::Panel::Utils::Preferences::get_preferences_rs(
c => $c_mock,
type => 'dev',
id => $devmod_id,
);
my $pref_values = get_inflated_columns_all($dev_pref_rs,'hash' => 'attribute', 'column' => 'value', 'force_array' => 1);
}
print "pure.time=".(time-$time).";\n";
my $time = time;
for(my $i=0; $i<$cnt; $i++){
my $devprof_pref_rs = $c_mock->model('DB')
->resultset('voip_preferences')
->search({
'profile.id' => $devmod_id,
},{
prefetch => {'voip_devprof_preferences' => 'profile'},
});
my %pref_values;
foreach my $value($devprof_pref_rs->all) {
$pref_values{$value->attribute} =
[ map {$_->value} $value->voip_devprof_preferences->all ];
}
}
print "DBIx.time=".(time-$time).";\n";
#pure.time=5;
#DBIx.time=14;
r
1;

@ -1,29 +1,29 @@
package Parent;
use warnings;
use strict;
our $VERSION = 1.23;
sub VERSION { $VERSION }
sub child_version { $_[0]->VERSION }
package Child;
use base qw(Parent);
our $VERSION = 5.43;
sub VERSION { $VERSION }
sub new { bless {}, $_[0]; }
sub parent_version { $_[0]->SUPER::VERSION }
print "Child version is ", Child->VERSION, "\n"; # 5.43
my $child = Child->new;
print "Child version: ", $child->VERSION, "\n"; # 5.43
print "Parent version: ", $child->parent_version, "\n"; # 1.23
package Parent;
use warnings;
use strict;
our $VERSION = 1.23;
sub VERSION { $VERSION }
sub child_version { $_[0]->VERSION }
package Child;
use base qw(Parent);
our $VERSION = 5.43;
sub VERSION { $VERSION }
sub new { bless {}, $_[0]; }
sub parent_version { $_[0]->SUPER::VERSION }
print "Child version is ", Child->VERSION, "\n"; # 5.43
my $child = Child->new;
print "Child version: ", $child->VERSION, "\n"; # 5.43
print "Parent version: ", $child->parent_version, "\n"; # 1.23
print "Child version: ", $child->child_version, "\n"; # 5.43

@ -1,39 +1,39 @@
use strict;
use warnings;
use Test::Collection;
use Test::FakeData;
use Test::More;
use Data::Dumper;
#use NGCP::Panel::Utils::Subscriber;
my $test_machine = Test::Collection->new(
name => 'reminders',
);
my $fake_data = Test::FakeData->new;
$test_machine->methods->{collection}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS POST)};
$test_machine->methods->{item}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS PUT PATCH DELETE)};
$fake_data->set_data_from_script({
'reminders' => {
'data' => {
subscriber_id => sub { return shift->get_id('subscribers',@_); },
recur => 'weekdays',#never' (only once)|'weekdays' (on weekdays)|'always' (everyday)
'time' => '14:00',
},
'query' => ['subscriber_id'],
},
});
$test_machine->DATA_ITEM_STORE($fake_data->process('reminders'));
$test_machine->form_data_item();
$test_machine->check_create_correct( 1, );
$test_machine->check_get2put();
$test_machine->check_bundle();
$test_machine->clear_test_data_all();#fake data aren't registered in this test machine, so they will stay.
done_testing;
# vim: set tabstop=4 expandtab:
use strict;
use warnings;
use Test::Collection;
use Test::FakeData;
use Test::More;
use Data::Dumper;
#use NGCP::Panel::Utils::Subscriber;
my $test_machine = Test::Collection->new(
name => 'reminders',
);
my $fake_data = Test::FakeData->new;
$test_machine->methods->{collection}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS POST)};
$test_machine->methods->{item}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS PUT PATCH DELETE)};
$fake_data->set_data_from_script({
'reminders' => {
'data' => {
subscriber_id => sub { return shift->get_id('subscribers',@_); },
recur => 'weekdays',#never' (only once)|'weekdays' (on weekdays)|'always' (everyday)
'time' => '14:00',
},
'query' => ['subscriber_id'],
},
});
$test_machine->DATA_ITEM_STORE($fake_data->process('reminders'));
$test_machine->form_data_item();
$test_machine->check_create_correct( 1, );
$test_machine->check_get2put();
$test_machine->check_bundle();
$test_machine->clear_test_data_all();#fake data aren't registered in this test machine, so they will stay.
done_testing;
# vim: set tabstop=4 expandtab:

@ -1,86 +1,86 @@
use strict;
use warnings;
use Test::Collection;
use Test::FakeData;
use Test::More;
use Data::Dumper;
use NGCP::Panel::Utils::DateTime;
#init test_machine
my $test_machine = Test::Collection->new(
name => 'subscriberregistrations',
ALLOW_EMPTY_COLLECTION => 1,
);
my $fake_data = Test::FakeData->new;
$test_machine->methods->{collection}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS POST)};
$test_machine->methods->{item}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS PUT PATCH DELETE)};
my $expires = NGCP::Panel::Utils::DateTime::current_local();
$fake_data->set_data_from_script({
'subscriberregistrations' => {
data => {
'contact' => 'test',
'expires' => $expires->ymd('-') . ' ' . $expires->hms(':'),
'q' => 0.5,
'subscriber_id' => sub { return shift->get_id('subscribers', @_); },
},
'update_change_fields' => [qw/_links expires id/],#expires seems like timezone difference
},
});
$test_machine->DATA_ITEM_STORE($fake_data->process('subscriberregistrations'));
$test_machine->form_data_item( );
# create 3 new vouchers from DATA_ITEM
$test_machine->check_create_correct( 3, sub{ $_[0]->{contact} .= time().'_'.$_[1]->{i} ; } );
#order of [check_bundle, check_get2put ] is important here:
#subscriberregistrations really is just a wrapper arounf kamailio rpc calls,
#and update of the existing item is made as delete+create. So, on every PUT or PATCH we delete item, and create new.
#It makes internal Collection list of created items misordered with real data in db,
#because Collection just keeps all created item, and doesn't try to recreate them on every update
$test_machine->check_bundle();
$test_machine->clear_test_data_all();
$test_machine->check_create_correct( 1, sub{ $_[0]->{contact} .= time().'_'.$_[1]->{i} ; } );
for (my $i=0; $i < 15; $i++) {
$test_machine->check_get2put(undef, undef, { ignore_fields => [qw/id _links/] });
}
$test_machine->clear_data_created();
$test_machine->check_create_correct( 1, sub{ $_[0]->{contact} .= time().'_'.$_[1]->{i} ; } );
{
my($res, $content) = $test_machine->check_item_post(sub{$_[0]->{q} = 2;$_[0]->{contact} .= time().'_MT14779_1' ;});
$test_machine->http_code_msg(422, "check creation of the subscriber registration with q > 1. MT#14779",$res,$content);
}
{
my($res, $content) = $test_machine->check_item_post(sub{$_[0]->{q} = -2;$_[0]->{contact} .= time().'_MT14779_2' ;});
$test_machine->http_code_msg(422, "check creation of the subscriber registration with q < -1. MT#14779",$res,$content);
}
{
# Default value should be used.
my($res, $content) = $test_machine->check_item_post(sub{delete $_[0]->{q};$_[0]->{contact} .= time().'_MT14779_3';});
$test_machine->http_code_msg(201, "check creation of the subscriber registration without q. MT#14779.",$res,$content);
}
{
my($res, $content) = $test_machine->check_item_post(sub{delete $_[0]->{expires};$_[0]->{contact} .= time().'_MT14891_1';});
$test_machine->http_code_msg(422, "check creation of the subscriber registration without required expires. MT#14891.",$res,$content);
}
#api doesn't deny extra fields
#{
# my($res, $content) = $test_machine->check_item_post(sub{$_[0]->{user_agent} = 'Test User Agent';$_[0]->{contact} .= time().'_MT14789' ;});
# $test_machine->http_code_msg(422, "check creation of the subscriber registration with already removed "user_agent". MT#14789.",$res,$content);
#}
$test_machine->clear_test_data_all();
done_testing;
# vim: set tabstop=4 expandtab:
use strict;
use warnings;
use Test::Collection;
use Test::FakeData;
use Test::More;
use Data::Dumper;
use NGCP::Panel::Utils::DateTime;
#init test_machine
my $test_machine = Test::Collection->new(
name => 'subscriberregistrations',
ALLOW_EMPTY_COLLECTION => 1,
);
my $fake_data = Test::FakeData->new;
$test_machine->methods->{collection}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS POST)};
$test_machine->methods->{item}->{allowed} = {map {$_ => 1} qw(GET HEAD OPTIONS PUT PATCH DELETE)};
my $expires = NGCP::Panel::Utils::DateTime::current_local();
$fake_data->set_data_from_script({
'subscriberregistrations' => {
data => {
'contact' => 'test',
'expires' => $expires->ymd('-') . ' ' . $expires->hms(':'),
'q' => 0.5,
'subscriber_id' => sub { return shift->get_id('subscribers', @_); },
},
'update_change_fields' => [qw/_links expires id/],#expires seems like timezone difference
},
});
$test_machine->DATA_ITEM_STORE($fake_data->process('subscriberregistrations'));
$test_machine->form_data_item( );
# create 3 new vouchers from DATA_ITEM
$test_machine->check_create_correct( 3, sub{ $_[0]->{contact} .= time().'_'.$_[1]->{i} ; } );
#order of [check_bundle, check_get2put ] is important here:
#subscriberregistrations really is just a wrapper arounf kamailio rpc calls,
#and update of the existing item is made as delete+create. So, on every PUT or PATCH we delete item, and create new.
#It makes internal Collection list of created items misordered with real data in db,
#because Collection just keeps all created item, and doesn't try to recreate them on every update
$test_machine->check_bundle();
$test_machine->clear_test_data_all();
$test_machine->check_create_correct( 1, sub{ $_[0]->{contact} .= time().'_'.$_[1]->{i} ; } );
for (my $i=0; $i < 15; $i++) {
$test_machine->check_get2put(undef, undef, { ignore_fields => [qw/id _links/] });
}
$test_machine->clear_data_created();
$test_machine->check_create_correct( 1, sub{ $_[0]->{contact} .= time().'_'.$_[1]->{i} ; } );
{
my($res, $content) = $test_machine->check_item_post(sub{$_[0]->{q} = 2;$_[0]->{contact} .= time().'_MT14779_1' ;});
$test_machine->http_code_msg(422, "check creation of the subscriber registration with q > 1. MT#14779",$res,$content);
}
{
my($res, $content) = $test_machine->check_item_post(sub{$_[0]->{q} = -2;$_[0]->{contact} .= time().'_MT14779_2' ;});
$test_machine->http_code_msg(422, "check creation of the subscriber registration with q < -1. MT#14779",$res,$content);
}
{
# Default value should be used.
my($res, $content) = $test_machine->check_item_post(sub{delete $_[0]->{q};$_[0]->{contact} .= time().'_MT14779_3';});
$test_machine->http_code_msg(201, "check creation of the subscriber registration without q. MT#14779.",$res,$content);
}
{
my($res, $content) = $test_machine->check_item_post(sub{delete $_[0]->{expires};$_[0]->{contact} .= time().'_MT14891_1';});
$test_machine->http_code_msg(422, "check creation of the subscriber registration without required expires. MT#14891.",$res,$content);
}
#api doesn't deny extra fields
#{
# my($res, $content) = $test_machine->check_item_post(sub{$_[0]->{user_agent} = 'Test User Agent';$_[0]->{contact} .= time().'_MT14789' ;});
# $test_machine->http_code_msg(422, "check creation of the subscriber registration with already removed "user_agent". MT#14789.",$res,$content);
#}
$test_machine->clear_test_data_all();
done_testing;
# vim: set tabstop=4 expandtab:

@ -1,138 +1,138 @@
package Test::HTTPRequestAsCurl;
use 5.008005;
use strict;
use warnings;
our $VERSION = "0.03";
use Carp;
use String::ShellQuote qw/ shell_quote /;
#use Win32::ShellQuote qw/ cmd_escape /;
use Exporter::Shiny qw/ as_curl /;
sub as_curl {
my ($request, %params) = @_;
my $content = $request->content;
my @data = split '&', $content;
my $method = $request->method;
my $uri = $request->uri;
my $headers = $request->headers;
my $user = $headers->authorization_basic || ( $params{credentials} ? join(':', @{$params{credentials}}{qw/user password/}) : '');
#my @h = grep { $_ !~ /(authorization|content-length|content-type)/i }
my @h = grep { $_ !~ /(authorization|content-length)/i }
$headers->header_field_names;
my @cmd = (["curl"]);
push(@cmd, ["--request", $method, $uri]);
push(@cmd, ["--dump-header", "-"]);
push(@cmd, ["--insecure"]) if $user;
push(@cmd, ["--user", $user]) if $user;
push(@cmd, ["--header", "$_: " . $headers->header($_)]) for sort @h;
push(@cmd, ["--data", $_]) for sort @data;
#return map { @$_ } @cmd unless keys %params;
return _make_it_pretty(\@cmd, %params);
}
sub _make_it_pretty {
my ($cmd, %params) = @_;
$params{shell} = $params{shell} || _default_shell_escape();
#$params{newline} = $params{newline} || "\\ \n";
$params{newline} = $params{newline} || "";
my $string;
for my $part (@$cmd) {
#if ($params{shell} eq 'win32') {
# $string .= cmd_escape join " ", @$part;
# $string .= ' ^' . $params{newline};
#}
#els
if ($params{shell} eq 'bourne') {
$string .= shell_quote @$part;
$string .= ' ' . $params{newline};
}
else {
croak "this shell is not currently supported: $params{shell}";
}
}
return $string;
}
sub _default_shell_escape { $^O eq 'MSWin32' ? 'win32' : 'bourne' }
1;
__END__
=encoding utf-8
=head1 NAME
HTTP::Request::AsCurl - Generate a curl command from an HTTP::Request object.
=head1 SYNOPSIS
use HTTP::Request::Common;
use HTTP::Request::AsCurl qw/as_curl/;
my $request = POST('api.earth.defense/weapon1', {
target => 'mothership',
when => 'now'
});
system as_curl($request);
print as_curl($request, pretty => 1, newline => "\n", shell => 'bourne');
# curl \
# --request POST api.earth.defense/weapon1 \
# --dump-header - \
# --data target=mothership \
# --data when=now
=head1 DESCRIPTION
This module converts an HTTP::Request object to a curl command. It can be used
for debugging REST APIs.
It handles headers and basic authentication.
=head1 METHODS
=head2 as_curl($request, %params)
Accepts an HTTP::Request object and converts it to a curl command. If there
are no C<%params>, C<as_curl()> returns the cmd as an array suitable for being
passed to system().
If there are C<%params>, C<as_curl()> returns a formatted string. The string's
format defaults to using "\n" for newlines and escaping the curl command using
bourne shell rules unless you are on a win32 system in which case it defaults
to using win32 cmd.exe escaping rules.
Available params are as follows
newline: defaults to "\n"
shell: currently available options are 'bourne' and 'win32'
=head1 LICENSE
Copyright (C) Eric Johnson.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 AUTHOR
Eric Johnson E<lt>eric.git@iijo.orgE<gt>
=cut
package Test::HTTPRequestAsCurl;
use 5.008005;
use strict;
use warnings;
our $VERSION = "0.03";
use Carp;
use String::ShellQuote qw/ shell_quote /;
#use Win32::ShellQuote qw/ cmd_escape /;
use Exporter::Shiny qw/ as_curl /;
sub as_curl {
my ($request, %params) = @_;
my $content = $request->content;
my @data = split '&', $content;
my $method = $request->method;
my $uri = $request->uri;
my $headers = $request->headers;
my $user = $headers->authorization_basic || ( $params{credentials} ? join(':', @{$params{credentials}}{qw/user password/}) : '');
#my @h = grep { $_ !~ /(authorization|content-length|content-type)/i }
my @h = grep { $_ !~ /(authorization|content-length)/i }
$headers->header_field_names;
my @cmd = (["curl"]);
push(@cmd, ["--request", $method, $uri]);
push(@cmd, ["--dump-header", "-"]);
push(@cmd, ["--insecure"]) if $user;
push(@cmd, ["--user", $user]) if $user;
push(@cmd, ["--header", "$_: " . $headers->header($_)]) for sort @h;
push(@cmd, ["--data", $_]) for sort @data;
#return map { @$_ } @cmd unless keys %params;
return _make_it_pretty(\@cmd, %params);
}
sub _make_it_pretty {
my ($cmd, %params) = @_;
$params{shell} = $params{shell} || _default_shell_escape();
#$params{newline} = $params{newline} || "\\ \n";
$params{newline} = $params{newline} || "";
my $string;
for my $part (@$cmd) {
#if ($params{shell} eq 'win32') {
# $string .= cmd_escape join " ", @$part;
# $string .= ' ^' . $params{newline};
#}
#els
if ($params{shell} eq 'bourne') {
$string .= shell_quote @$part;
$string .= ' ' . $params{newline};
}
else {
croak "this shell is not currently supported: $params{shell}";
}
}
return $string;
}
sub _default_shell_escape { $^O eq 'MSWin32' ? 'win32' : 'bourne' }
1;
__END__
=encoding utf-8
=head1 NAME
HTTP::Request::AsCurl - Generate a curl command from an HTTP::Request object.
=head1 SYNOPSIS
use HTTP::Request::Common;
use HTTP::Request::AsCurl qw/as_curl/;
my $request = POST('api.earth.defense/weapon1', {
target => 'mothership',
when => 'now'
});
system as_curl($request);
print as_curl($request, pretty => 1, newline => "\n", shell => 'bourne');
# curl \
# --request POST api.earth.defense/weapon1 \
# --dump-header - \
# --data target=mothership \
# --data when=now
=head1 DESCRIPTION
This module converts an HTTP::Request object to a curl command. It can be used
for debugging REST APIs.
It handles headers and basic authentication.
=head1 METHODS
=head2 as_curl($request, %params)
Accepts an HTTP::Request object and converts it to a curl command. If there
are no C<%params>, C<as_curl()> returns the cmd as an array suitable for being
passed to system().
If there are C<%params>, C<as_curl()> returns a formatted string. The string's
format defaults to using "\n" for newlines and escaping the curl command using
bourne shell rules unless you are on a win32 system in which case it defaults
to using win32 cmd.exe escaping rules.
Available params are as follows
newline: defaults to "\n"
shell: currently available options are 'bourne' and 'win32'
=head1 LICENSE
Copyright (C) Eric Johnson.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 AUTHOR
Eric Johnson E<lt>eric.git@iijo.orgE<gt>
=cut

Loading…
Cancel
Save