Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom error handling #847

Merged
merged 17 commits into from
Sep 7, 2021
Merged
1 change: 1 addition & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ lib/Zonemaster/Backend/DB.pm
lib/Zonemaster/Backend/DB/MySQL.pm
lib/Zonemaster/Backend/DB/PostgreSQL.pm
lib/Zonemaster/Backend/DB/SQLite.pm
lib/Zonemaster/Backend/Errors.pm
lib/Zonemaster/Backend/RPCAPI.pm
lib/Zonemaster/Backend/TestAgent.pm
lib/Zonemaster/Backend/Translator.pm
13 changes: 8 additions & 5 deletions lib/Zonemaster/Backend/DB.pm
Original file line number Diff line number Diff line change
@@ -51,22 +51,25 @@ sub get_db_class {
sub user_exists {
my ( $self, $user ) = @_;

die "username not provided to the method user_exists\n" unless ( $user );
die Zonemaster::Backend::Error::Internal->new( reason => "username not provided to the method user_exists")
unless ( $user );

return $self->user_exists_in_db( $user );
}

sub add_api_user {
my ( $self, $username, $api_key ) = @_;

die "username or api_key not provided to the method add_api_user\n"
unless ( $username && $api_key );
die Zonemaster::Backend::Error::Internal->new( reason => "username or api_key not provided to the method add_api_user")
unless ( $username && $api_key );

die "User already exists\n" if ( $self->user_exists( $username ) );
die Zonemaster::Backend::Error::Conflict->new( message => 'User already exists', data => { username => $username } )
if ( $self->user_exists( $username ) );

my $result = $self->add_api_user_to_db( $username, $api_key );

die "add_api_user_to_db not successful\n" unless ( $result );
die Zonemaster::Backend::Error::Internal->new( reason => "add_api_user_to_db not successful")
unless ( $result );

return $result;
}
32 changes: 26 additions & 6 deletions lib/Zonemaster/Backend/DB/MySQL.pm
Original file line number Diff line number Diff line change
@@ -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';

@@ -128,7 +129,7 @@ sub user_authorized {
sub create_new_batch_job {
my ( $self, $username ) = @_;

my ( $batch_id, $creaton_time ) = $self->dbh->selectrow_array( "
my ( $batch_id, $creation_time ) = $self->dbh->selectrow_array( "
SELECT
batch_id,
batch_jobs.creation_time AS batch_creation_time
@@ -142,7 +143,8 @@ sub create_new_batch_job {
LIMIT 1
", undef, $username );

die "You can't create a new batch job, job:[$batch_id] started on:[$creaton_time] still running \n" if ( $batch_id );
die Zonemaster::Backend::Error::Conflict->new( message => 'Batch job still running', data => { batch_id => $batch_id, creation_time => $creation_time } )
if ( $batch_id );

$self->dbh->do( "INSERT INTO batch_jobs (username) VALUES(?)", undef, $username );
my ( $new_batch_id ) = $self->dbh->{mysql_insertid};
@@ -228,12 +230,16 @@ 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 );
}
@@ -249,8 +255,22 @@ 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;
}
@@ -370,7 +390,7 @@ sub add_batch_job {
$dbh->{AutoCommit} = 1;
}
else {
die "User $params->{username} not authorized to use batch mode\n";
die Zonemaster::Backend::Error::PermissionDenied->new( message => 'User not authorized to use batch mode', data => { username => $params->{username}} );
}

return $batch_id;
42 changes: 29 additions & 13 deletions lib/Zonemaster/Backend/DB/PostgreSQL.pm
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ use Encode;
use JSON::PP;

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

with 'Zonemaster::Backend::DB';

@@ -153,8 +154,8 @@ sub create_new_batch_job {
test_results.progress<>100
LIMIT 1
", undef, $username );

die "You can't create a new batch job, job:[$batch_id] started on:[$creation_time] still running \n" if ( $batch_id );
die Zonemaster::Backend::Error::Conflict->new( message => 'Batch job still running', data => { batch_id => $batch_id, creation_time => $creation_time } )
if ( $batch_id );

my ( $new_batch_id ) =
$dbh->selectrow_array( "INSERT INTO batch_jobs (username) VALUES (?) RETURNING id", undef, $username );
@@ -207,8 +208,14 @@ 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;
}
@@ -222,27 +229,36 @@ 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;
}
@@ -342,7 +358,7 @@ sub add_batch_job {
$dbh->commit();
}
else {
die "User $params->{username} not authorized to use batch mode\n";
die Zonemaster::Backend::Error::PermissionDenied->new( message => 'User not authorized to use batch mode', data => { username => $params->{username}} );
}

return $batch_id;
33 changes: 27 additions & 6 deletions lib/Zonemaster/Backend/DB/SQLite.pm
Original file line number Diff line number Diff line change
@@ -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' => (
@@ -145,7 +147,7 @@ sub user_authorized {
sub create_new_batch_job {
my ( $self, $username ) = @_;

my ( $batch_id, $creaton_time ) = $self->dbh->selectrow_array( "
my ( $batch_id, $creation_time ) = $self->dbh->selectrow_array( "
SELECT
batch_id,
batch_jobs.creation_time AS batch_creation_time
@@ -158,7 +160,8 @@ sub create_new_batch_job {
LIMIT 1
" );

die "You can't create a new batch job, job:[$batch_id] started on:[$creaton_time] still running \n" if ( $batch_id );
die Zonemaster::Backend::Error::Conflict->new( message => 'Batch job still running', data => { batch_id => $batch_id, creation_time => $creation_time } )
if ( $batch_id );

$self->dbh->do("INSERT INTO batch_jobs (username) VALUES(" . $self->dbh->quote( $username ) . ")" );
my ( $new_batch_id ) = $self->dbh->sqlite_last_insert_rowid;
@@ -244,12 +247,16 @@ 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;
}
@@ -265,8 +272,22 @@ 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;
}
@@ -363,7 +384,7 @@ sub add_batch_job {
$dbh->{AutoCommit} = 1;
}
else {
die "User $params->{username} not authorized to use batch mode\n";
die Zonemaster::Backend::Error::PermissionDenied->new( message => 'User not authorized to use batch mode', data => { username => $params->{username}} );
}

return $batch_id;
Loading