Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions lib/Zonemaster/Backend/DB/MySQL.pm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use DBI qw(:utils);
use JSON::PP;

use Zonemaster::Backend::Validator qw( untaint_ipv6_address );
use Zonemaster::Backend::Errors;

with 'Zonemaster::Backend::DB';

Expand Down Expand Up @@ -228,12 +229,14 @@ sub get_test_params {

my ( $params_json ) = $self->dbh->selectrow_array( "SELECT params FROM test_results WHERE hash_id=?", undef, $test_id );

die Zonemaster::Backend::Error::ResourceNotFound->new( message => "Test not found", data => { test_id => $test_id } ) unless defined $params_json;

my $result;
eval {
$result = decode_json( $params_json );
};

warn "decoding of params_json failed (testi_id: [$test_id]):".Dumper($params_json) if $@;
die Zonemaster::Backend::Error::JsonError->new( reason => "$@", data => { test_id => $test_id } ) if $@;

return decode_json( $params_json );
}
Expand All @@ -249,8 +252,20 @@ sub test_results {
my $result;
my ( $hrefs ) = $self->dbh->selectall_hashref( "SELECT id, hash_id, CONVERT_TZ(`creation_time`, \@\@session.time_zone, '+00:00') AS creation_time, params, results FROM test_results WHERE hash_id=?", 'hash_id', undef, $test_id );
$result = $hrefs->{$test_id};
$result->{params} = decode_json( $result->{params} );
$result->{results} = decode_json( $result->{results} );

die Zonemaster::Backend::Error::ResourceNotFound->new( message => "Test not found", data => { test_id => $test_id } ) unless defined $result;

eval {
$result->{params} = decode_json( $result->{params} );

if (defined $result->{results}) {
$result->{results} = decode_json( $result->{results} );
} else {
$result->{results} = [];
}
};

die Zonemaster::Backend::Error::JsonError->new( reason => "$@", data => { test_id => $test_id } ) if $@;

return $result;
}
Expand Down
32 changes: 22 additions & 10 deletions lib/Zonemaster/Backend/DB/PostgreSQL.pm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use Encode;
use JSON::PP;

use Zonemaster::Backend::DB;
use Zonemaster::Backend::Errors;

with 'Zonemaster::Backend::DB';

Expand Down Expand Up @@ -207,8 +208,12 @@ sub get_test_params {

my $dbh = $self->dbh;
my ( $params_json ) = $dbh->selectrow_array( "SELECT params FROM test_results WHERE hash_id=?", undef, $test_id );

die Zonemaster::Backend::Error::ResourceNotFound->new( message => "Test not found", data => { test_id => $test_id } ) unless defined $params_json;

eval { $result = decode_json( encode_utf8( $params_json ) ); };
die "$@ \n" if $@;

die Zonemaster::Backend::Error::JsonError->new( reason => "$@", data => { test_id => $test_id } ) if $@;

return $result;
}
Expand All @@ -222,27 +227,34 @@ sub test_results {
if ( $results );

my $result;
eval {
my ( $hrefs ) = $dbh->selectall_hashref( "SELECT id, hash_id, creation_time at time zone current_setting('TIMEZONE') at time zone 'UTC' as creation_time, params, results FROM test_results WHERE hash_id=?", 'hash_id', undef, $test_id );
$result = $hrefs->{$test_id};
my ( $hrefs ) = $dbh->selectall_hashref( "SELECT id, hash_id, creation_time at time zone current_setting('TIMEZONE') at time zone 'UTC' as creation_time, params, results FROM test_results WHERE hash_id=?", 'hash_id', undef, $test_id );
$result = $hrefs->{$test_id};

die Zonemaster::Backend::Error::ResourceNotFound->new( message => "Test not found", data => { test_id => $test_id } ) unless defined $result;

eval {
# This workaround is needed to properly handle all versions of perl and the DBD::Pg module
# More details in the zonemaster backend issue #570
if (utf8::is_utf8($result->{params}) ) {
$result->{params} = decode_json( encode_utf8($result->{params}) );
$result->{params} = decode_json( encode_utf8($result->{params}) );
}
else {
$result->{params} = decode_json( $result->{params} );
$result->{params} = decode_json( $result->{params} );
}

if (utf8::is_utf8($result->{results} ) ) {
if (defined $result->{results} ) {
if (utf8::is_utf8($result->{results} ) ) {
$result->{results} = decode_json( encode_utf8($result->{results}) );
}
else {
}
else {
$result->{results} = decode_json( $result->{results} );
}
} else {
$result->{results} = [];
}
};
die "$@ \n" if $@;

die Zonemaster::Backend::Error::JsonError->new( reason => "$@", data => { test_id => $test_id }) if $@;

return $result;
}
Expand Down
22 changes: 19 additions & 3 deletions lib/Zonemaster/Backend/DB/SQLite.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use Digest::MD5 qw(md5_hex);
use JSON::PP;
use Log::Any qw( $log );

use Zonemaster::Backend::Errors;

with 'Zonemaster::Backend::DB';

has 'dbh' => (
Expand Down Expand Up @@ -244,12 +246,14 @@ sub get_test_params {

my ( $params_json ) = $self->dbh->selectrow_array( "SELECT params FROM test_results WHERE hash_id=?", undef, $test_id );

die Zonemaster::Backend::Error::ResourceNotFound->new( message => "Test not found", data => { test_id => $test_id } ) unless defined $params_json;

my $result;
eval {
$result = decode_json( $params_json );
};

$log->warn( "decoding of params_json failed (test_id: [$test_id]):".Dumper($params_json) ) if $@;
die Zonemaster::Backend::Error::JsonError->new( reason => "$@", data => { test_id => $test_id } ) if $@;

return $result;
}
Expand All @@ -265,8 +269,20 @@ sub test_results {
my $result;
my ( $hrefs ) = $self->dbh->selectall_hashref( "SELECT id, hash_id, creation_time, params, results FROM test_results WHERE hash_id=?", 'hash_id', undef, $test_id );
$result = $hrefs->{$test_id};
$result->{params} = decode_json( $result->{params} );
$result->{results} = decode_json( $result->{results} );

die Zonemaster::Backend::Error::ResourceNotFound->new( message => "Test not found", data => { test_id => $test_id } ) unless defined $result;

eval {
$result->{params} = decode_json( $result->{params} );

if (defined $result->{results}) {
$result->{results} = decode_json( $result->{results} );
} else {
$result->{results} = [];
}
};

die Zonemaster::Backend::Error::JsonError->new( reason => "$@", data => { test_id => $test_id } ) if $@;

return $result;
}
Expand Down
160 changes: 160 additions & 0 deletions lib/Zonemaster/Backend/Errors.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package Zonemaster::Backend::Error;
use Moose;
use Data::Dumper;


has 'message' => (
is => 'rw',
isa => 'Str',
required => 1,
);

has 'code' => (
is => 'rw',
isa => 'Int',
required => 1,
);

has 'data' => (
is => 'rw',
isa => 'Any',
default => undef,
);

sub as_hash {
my $self = shift;
my $error = {
code => $self->code,
message => $self->message,
error => ref($self),
};
$error->{data} = $self->data if defined $self->data;
return $error;
}

sub as_string {
my $self = shift;
my $str = sprintf "%s (code %d)", $self->message, $self->code;
if (defined $self->data) {
$str .= sprintf "; Context: %s", $self->_data_dump;
}
return $str;
}

sub _data_dump {
my $self = shift;
local $Data::Dumper::Indent = 0;
local $Data::Dumper::Terse = 1;
my $data = Dumper($self->data);
$data =~ s/[\n\r]/ /g;
return $data ;
}

package Zonemaster::Backend::Error::Internal;
use Moose;

extends 'Zonemaster::Backend::Error';

has '+message' => (
default => 'Internal server error'
);

has '+code' => (
default => -32603
);

has 'reason' => (
isa => 'Str',
is => 'rw',
initializer => 'reason',
);

has 'method' => (
is => 'rw',
isa => 'Str',
builder => '_build_method'
);

has 'id' => (
is => 'rw',
isa => 'Int',
default => 0,
);

sub _build_method {
my $s = 0;
while (my @c = caller($s)) {
$s ++;
last if $c[3] eq 'Moose::Object::new';
}
my @c = caller($s);
if ($c[3] =~ /^(.*)::handle_exception$/ ) {
@c = caller(++$s);
}

return $c[3];
}

around 'reason' => sub {
my $orig = shift;
my $self = shift;

my ( $value, $setter, $attr ) = @_;

# reader
return $self->$orig if not $value;

# trim new lines
$value =~ s/\n/ /g;
$value =~ s/^\s+|\s+$//g;

# initializer
return $setter->($value) if $setter;

# writer
$self->$orig($value);
};

around 'as_hash' => sub {
my $orig = shift;
my $self = shift;

my $href = $self->$orig;

$href->{exception_id} = $self->id;
$href->{reason} = $self->reason;
$href->{method} = $self->method;

return $href;
};


sub as_string {
my $self = shift;
my $str = sprintf "Internal error %0.3d (%s): Unexpected error in the `%s` method: [%s]", $self->id, ref($self), $self->method, $self->reason;
if (defined $self->data) {
$str .= sprintf "; Context: %s", $self->_data_dump;
}
return $str;
}


package Zonemaster::Backend::Error::ResourceNotFound;
use Moose;

extends 'Zonemaster::Backend::Error';

has '+message' => (
default => 'Resource not found'
);

has '+code' => (
default => -32000
);

package Zonemaster::Backend::Error::JsonError;
use Moose;

extends 'Zonemaster::Backend::Error::Internal';

1;
Loading