diff --git a/Changes b/Changes index 7166dbde3..12f02194e 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,14 @@ Release history for Zonemaster component Zonemaster-Backend + +v9.0.1 2022-07-08 (public fix release) + + [Fixes] + - Corrects a bug where Zonemaster-Backend does not respect the IPv4 or + IPV6 setting in a custom profile (#1046, #1039) + - Updates the Danish translation (#1034) + + v9.0.0 2022-06-09 (public release release) [Deprecation] diff --git a/Makefile.PL b/Makefile.PL index 247069fda..de48397a1 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -33,7 +33,7 @@ requires 'Starman' => 0, 'String::ShellQuote' => 0, 'Try::Tiny' => 0.12, - 'Zonemaster::Engine' => 4.005, + 'Zonemaster::Engine' => 4.005001, 'Zonemaster::LDNS' => 2.002002, 'Plack::Middleware::ReverseProxy' => 0, 'Locale::TextDomain' => 1.20, diff --git a/lib/Zonemaster/Backend.pm b/lib/Zonemaster/Backend.pm index a1d6443ff..ade20f5e2 100644 --- a/lib/Zonemaster/Backend.pm +++ b/lib/Zonemaster/Backend.pm @@ -1,6 +1,6 @@ package Zonemaster::Backend; -our $VERSION = '9.0.0'; +our $VERSION = '9.0.1'; use strict; use warnings; diff --git a/lib/Zonemaster/Backend/Config.pm b/lib/Zonemaster/Backend/Config.pm index b7ab31532..fa0f0fcce 100644 --- a/lib/Zonemaster/Backend/Config.pm +++ b/lib/Zonemaster/Backend/Config.pm @@ -17,7 +17,7 @@ use Zonemaster::Backend::DB; Readonly my @SIG_NAME => split ' ', $Config{sig_name}; -=head1 STATIC METHODS +=head1 CLASS METHODS =head2 get_default_path @@ -63,6 +63,50 @@ sub get_default_path { return $path // croak "File not found: backend_config.ini\n"; } +=head2 load_profiles + +Loads and returns a set of named profiles. + + my %all_profiles = ( + $config->PUBLIC_PROFILES, + $config->PRIVATE_PROFILES, + ); + my %profiles = %{ Zonemaster::Backend::Config->load_profiles( %all_profiles ) }; + +Takes a hash mapping profile names to profile paths. +An `undef` path value means the default profile. + +Returns a hashref mapping profile names to profile objects. + +The returned profiles have omitted values filled in with defaults from the +default profile. + +Dies if any of the given paths cannot be read or their contents cannot be parsed +as JSON. + +=cut + +sub load_profiles { + my ( $class, %profile_paths ) = @_; + + my %profiles; + foreach my $name ( keys %profile_paths ) { + my $path = $profile_paths{$name}; + + my $full_profile = Zonemaster::Engine::Profile->default; + if ( defined $path ) { + my $json = eval { read_file( $path, err_mode => 'croak' ) } # + // die "Error loading profile '$name': $@"; + my $named_profile = eval { Zonemaster::Engine::Profile->from_json( $json ) } # + // die "Error loading profile '$name' at '$path': $@"; + $full_profile->merge( $named_profile ); + } + $profiles{$name} = $full_profile; + } + + return \%profiles; +} + =head1 CONSTRUCTORS =head2 load_config diff --git a/lib/Zonemaster/Backend/DB.pm b/lib/Zonemaster/Backend/DB.pm index a2b6ecc85..1252d1c66 100644 --- a/lib/Zonemaster/Backend/DB.pm +++ b/lib/Zonemaster/Backend/DB.pm @@ -14,7 +14,6 @@ use Log::Any qw( $log ); use POSIX qw( strftime ); use Try::Tiny; -use Zonemaster::Engine::Profile; use Zonemaster::Backend::Errors; requires qw( @@ -612,13 +611,11 @@ sub _normalize_domain { sub _project_params { my ( $self, $params ) = @_; - my $profile = Zonemaster::Engine::Profile->effective; - my %projection = (); $projection{domain} = _normalize_domain( $$params{domain} // "" ); - $projection{ipv4} = $$params{ipv4} // $profile->get( 'net.ipv4' ); - $projection{ipv6} = $$params{ipv6} // $profile->get( 'net.ipv6' ); + $projection{ipv4} = $$params{ipv4}; + $projection{ipv6} = $$params{ipv6}; $projection{profile} = lc( $$params{profile} // "default" ); my $array_ds_info = $$params{ds_info} // []; diff --git a/lib/Zonemaster/Backend/RPCAPI.pm b/lib/Zonemaster/Backend/RPCAPI.pm index 244de734f..6f3bf811f 100644 --- a/lib/Zonemaster/Backend/RPCAPI.pm +++ b/lib/Zonemaster/Backend/RPCAPI.pm @@ -23,6 +23,7 @@ use Encode; # Zonemaster Modules use Zonemaster::Engine; +use Zonemaster::Engine::Profile; use Zonemaster::Engine::Recursor; use Zonemaster::Backend; use Zonemaster::Backend::Config; @@ -59,6 +60,11 @@ sub new { $self->_init_db($dbtype); + $self->{_profiles} = Zonemaster::Backend::Config->load_profiles( # + $self->{config}->PUBLIC_PROFILES, + $self->{config}->PRIVATE_PROFILES, + ); + return ( $self ); } @@ -257,8 +263,13 @@ sub start_domain_test { die "No domain in parameters\n" unless ( defined $params->{domain} && length($params->{domain}) ); - $params->{priority} //= 10; - $params->{queue} //= 0; + $params->{profile} //= "default"; + $params->{priority} //= 10; + $params->{queue} //= 0; + + my $profile = $self->{_profiles}{ $params->{profile} }; + $params->{ipv4} //= $profile->get( "net.ipv4" ); + $params->{ipv6} //= $profile->get( "net.ipv6" ); $result = $self->{db}->create_new_test( $params->{domain}, $params, $self->{config}->ZONEMASTER_age_reuse_previous_test ); }; @@ -514,8 +525,13 @@ sub add_batch_job { my $results; eval { - $params->{test_params}->{priority} //= 5; - $params->{test_params}->{queue} //= 0; + $params->{test_params}{profile} //= "default"; + $params->{test_params}{priority} //= 5; + $params->{test_params}{queue} //= 0; + + my $profile = $self->{_profiles}{ $params->{test_params}{profile} }; + $params->{test_params}{ipv4} //= $profile->get( "net.ipv4" ); + $params->{test_params}{ipv6} //= $profile->get( "net.ipv6" ); $results = $self->{db}->add_batch_job( $params ); }; diff --git a/lib/Zonemaster/Backend/TestAgent.pm b/lib/Zonemaster/Backend/TestAgent.pm index fcf4fedf0..514818f5e 100644 --- a/lib/Zonemaster/Backend/TestAgent.pm +++ b/lib/Zonemaster/Backend/TestAgent.pm @@ -40,20 +40,10 @@ sub new { my $dbclass = Zonemaster::Backend::DB->get_db_class( $dbtype ); $self->{_db} = $dbclass->from_config( $config ); - my %all_profiles = ( $config->PUBLIC_PROFILES, $config->PRIVATE_PROFILES ); - foreach my $name ( keys %all_profiles ) { - my $path = $all_profiles{$name}; - - my $full_profile = Zonemaster::Engine::Profile->default; - if ( defined $path ) { - my $json = eval { read_file( $path, err_mode => 'croak' ) } # - // die "Error loading profile '$name': $@"; - my $named_profile = eval { Zonemaster::Engine::Profile->from_json( $json ) } # - // die "Error loading profile '$name' at '$path': $@"; - $full_profile->merge( $named_profile ); - } - $self->{_profiles}{$name} = $full_profile; - } + $self->{_profiles} = Zonemaster::Backend::Config->load_profiles( # + $config->PUBLIC_PROFILES, + $config->PRIVATE_PROFILES, + ); bless( $self, $class ); return $self; diff --git a/share/da.po b/share/da.po index 8ea1dd935..1f6853e63 100644 --- a/share/da.po +++ b/share/da.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-12-07 15:34+0000\n" -"PO-Revision-Date: 2021-10-14 11:25+0200\n" +"POT-Creation-Date: 2022-06-08 14:31+0000\n" +"PO-Revision-Date: 2022-06-08 14:26+0000\n" "Last-Translator: haarbo@dk-hostmaster.dk\n" "Language-Team: Zonemaster project\n" "Language: da\n" @@ -11,29 +11,54 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +msgid "Invalid method parameter(s)." +msgstr "Invalid metodeparametre" + +msgid "Missing property" +msgstr "Manglende egenskab" + +msgid "" +"Warning: Zonemaster::LDNS not compiled with IDN support, cannot handle non-" +"ASCII names correctly." +msgstr "" +"Advarsel: Zonemaster::LDNS ikke kompileret med IDN-support, og kan derfor " +"ikke håndtere ikke-ascii-navne korrekt" + +msgid "Invalid digest format" +msgstr "Invalid digest-format" + +msgid "Algorithm must be a positive integer" +msgstr "Algoritmen skal være et positivt heltal" + +msgid "Digest type must be a positive integer" +msgstr "Digest type skal være et positivt heltal" + +msgid "Keytag must be a positive integer" +msgstr "Keytag skal være et positivt heltal" + msgid "Domain name required" msgstr "Domænenavn påkrævet" +msgid "The domain name is IDNA invalid" +msgstr "Domænenavnet er IDNA ugyldigt" + msgid "" -"The domain name is not a valid IDNA string and cannot be converted to an A-" -"label" +"The domain name contains non-ascii characters and IDNA support is not " +"installed" msgstr "" -"Domænenavnet er ikke en valid IDNA-streng og kan ikke konverteres til en A-label" - -msgid "The domain name contains non-ascii characters and IDNA is not installed" -msgstr "Domænenavnet indeholder ikke-ascii-tegn og IDNA er ikke installeret" +"Domænenavnet indeholder ikke-ascii-tegn og IDNA-support er ikke installeret" msgid "The domain name character(s) are not supported" msgstr "Domænenavnets tegn er ikke understøttet" +msgid "The domain name contains consecutive dots" +msgstr "Domænenavnet indeholder flere dots (.) efter hinanden" + msgid "The domain name or label is too long" msgstr "Domænenavnet eller labelen er for lang" -msgid "Unknown profile" -msgstr "Ukendt profil" - -msgid "Invalid IP address" -msgstr "Invalid IP-adresse" +msgid "Invalid language tag format" +msgstr "Invalidt sprogkode-format" msgid "Unkown language string" msgstr "Ukendt sprogstreng" @@ -41,32 +66,11 @@ msgstr "Ukendt sprogstreng" msgid "Language string not unique" msgstr "Sprogstreng ikke unik" -msgid "Invalid method parameter(s)." -msgstr "Invalid metodeparametre" - -msgid "Missing property" -msgstr "Manglende egenskab" - -msgid "" -"Warning: Zonemaster::LDNS not compiled with libidn2, cannot handle non-ASCII " -"names correctly." -msgstr "Advarsel: Zonemaster::LDNS ikke kompileret med libidn2 - kan ikke " -"håndtere ikke-ascii-navne korrekt" - -msgid "The domain name contains a character or characters not supported" -msgstr "Domænenavnet indeholder et eller flere ikke understøttede tegn" - -msgid "Invalid digest format" -msgstr "Invalid digest format" - -msgid "Algorithm must be a positive integer" -msgstr "Algoritmen skal være et positivt heltal" - -msgid "Digest type must be a positive integer" -msgstr "Digest type skal være et positivt heltal" +msgid "Invalid IP address" +msgstr "Invalid IP-adresse" -msgid "Keytag must be a positive integer" -msgstr "Keytag skal være et positivt heltal" +msgid "Invalid profile format" +msgstr "Invalidt profil-format" -msgid "Invalid language tag format" -msgstr "Invalidt sprogkodeformat" +msgid "Unknown profile" +msgstr "Ukendt profil" diff --git a/t/db.t b/t/db.t index 865831734..6d85faed8 100644 --- a/t/db.t +++ b/t/db.t @@ -20,18 +20,18 @@ sub encode_and_fingerprint { subtest 'encoding and fingerprint' => sub { subtest 'missing properties' => sub { - my $expected_encoded_params = '{"domain":"example.com","ds_info":[],"ipv4":true,"ipv6":true,"nameservers":[],"profile":"default"}'; - my %params = ( domain => "example.com" ); + my $expected_encoded_params = '{"domain":"example.com","ds_info":[],"ipv4":null,"ipv6":null,"nameservers":[],"profile":"default"}'; my ( $encoded_params, $fingerprint ) = encode_and_fingerprint( \%params ); is $encoded_params, $expected_encoded_params, 'domain only: the encoded strings should match'; #diag ($fingerprint); + my $expected_encoded_params_v4_true = '{"domain":"example.com","ds_info":[],"ipv4":true,"ipv6":null,"nameservers":[],"profile":"default"}'; $params{ipv4} = JSON::PP->true; my ( $encoded_params_ipv4, $fingerprint_ipv4 ) = encode_and_fingerprint( \%params ); - is $encoded_params_ipv4, $expected_encoded_params, 'add ipv4: the encoded strings should match'; - is $fingerprint_ipv4, $fingerprint, 'fingerprints should match'; + is $encoded_params_ipv4, $expected_encoded_params_v4_true, 'add ipv4: the encoded strings should match'; + isnt $fingerprint_ipv4, $fingerprint, 'fingerprints should not match'; }; subtest 'array properties' => sub { @@ -121,7 +121,7 @@ subtest 'encoding and fingerprint' => sub { }; subtest 'garbage properties set' => sub { - my $expected_encoded_params = '{"client":"GUI v3.3.0","domain":"example.com","ds_info":[],"ipv4":true,"ipv6":true,"nameservers":[],"profile":"default"}'; + my $expected_encoded_params = '{"client":"GUI v3.3.0","domain":"example.com","ds_info":[],"ipv4":null,"ipv6":null,"nameservers":[],"profile":"default"}'; my %params1 = ( domain => "example.com", ); @@ -174,6 +174,8 @@ subtest 'encoding and fingerprint' => sub { my $expected_fingerprint = '8c64f7feaa3f13b77e769720991f2a79'; my %params = ( domain => "café.example" ); + $params{ipv4} = JSON::PP->true; + $params{ipv6} = JSON::PP->true; my ( $encoded_params, $fingerprint ) = encode_and_fingerprint( \%params ); is $encoded_params, $expected_encoded_params, 'IDN domain: the encoded strings should match'; @@ -184,7 +186,7 @@ subtest 'encoding and fingerprint' => sub { subtest 'in domain' => sub { my %params1 = ( domain => "example.com" ); my %params2 = ( domain => "example.com." ); - my $expected_encoded_params = encode_utf8( '{"domain":"example.com","ds_info":[],"ipv4":true,"ipv6":true,"nameservers":[],"profile":"default"}' ); + my $expected_encoded_params = encode_utf8( '{"domain":"example.com","ds_info":[],"ipv4":null,"ipv6":null,"nameservers":[],"profile":"default"}' ); my ( $encoded_params1, $fingerprint1 ) = encode_and_fingerprint( \%params1 ); my ( $encoded_params2, $fingerprint2 ) = encode_and_fingerprint( \%params2 ); @@ -196,7 +198,7 @@ subtest 'encoding and fingerprint' => sub { subtest 'in nameserver' => sub { my %params1 = ( domain => "example.com", nameservers => [ { ns => "ns1.example.com." } ] ); my %params2 = ( domain => "example.com", nameservers => [ { ns => "ns1.example.com" } ] ); - my $expected_encoded_params = encode_utf8( '{"domain":"example.com","ds_info":[],"ipv4":true,"ipv6":true,"nameservers":[{"ns":"ns1.example.com"}],"profile":"default"}' ); + my $expected_encoded_params = encode_utf8( '{"domain":"example.com","ds_info":[],"ipv4":null,"ipv6":null,"nameservers":[{"ns":"ns1.example.com"}],"profile":"default"}' ); my ( $encoded_params1, $fingerprint1 ) = encode_and_fingerprint( \%params1 ); my ( $encoded_params2, $fingerprint2 ) = encode_and_fingerprint( \%params2 ); @@ -207,7 +209,7 @@ subtest 'encoding and fingerprint' => sub { subtest 'root is not modified' => sub { my %params = ( domain => "." ); - my $expected_encoded_params = encode_utf8( '{"domain":".","ds_info":[],"ipv4":true,"ipv6":true,"nameservers":[],"profile":"default"}' ); + my $expected_encoded_params = encode_utf8( '{"domain":".","ds_info":[],"ipv4":null,"ipv6":null,"nameservers":[],"profile":"default"}' ); my ( $encoded_params, $fingerprint ) = encode_and_fingerprint( \%params ); is $encoded_params, $expected_encoded_params, 'the encoded strings should match';