diff options
author | Dylan William Hardison <dylan@hardison.net> | 2018-08-26 07:55:24 +0200 |
---|---|---|
committer | Dylan William Hardison <dylan@hardison.net> | 2018-08-26 07:55:24 +0200 |
commit | 9263f397e701f25af395e8cdee48c87ee3327157 (patch) | |
tree | cc7f6b6beef8947090a108701ca34316a5c8edb8 /Bugzilla | |
parent | 23b94e8410d90e9e15584d3a9220b6bb214f4220 (diff) | |
parent | d57aefa118802606ea7cc424aaa62173be9eec41 (diff) | |
download | bugzilla-9263f397e701f25af395e8cdee48c87ee3327157.tar.gz bugzilla-9263f397e701f25af395e8cdee48c87ee3327157.tar.xz |
Merge remote-tracking branch 'bmo/mojo'
Diffstat (limited to 'Bugzilla')
-rw-r--r-- | Bugzilla/CGI.pm | 2 | ||||
-rw-r--r-- | Bugzilla/Config.pm | 37 | ||||
-rw-r--r-- | Bugzilla/DB/Sqlite.pm | 2 | ||||
-rw-r--r-- | Bugzilla/Install/Filesystem.pm | 52 | ||||
-rw-r--r-- | Bugzilla/Install/Localconfig.pm | 10 | ||||
-rw-r--r-- | Bugzilla/Quantum.pm | 4 | ||||
-rw-r--r-- | Bugzilla/Quantum/SES.pm | 79 | ||||
-rw-r--r-- | Bugzilla/Quantum/Static.pm | 2 | ||||
-rw-r--r-- | Bugzilla/Quantum/Stdout.pm | 3 | ||||
-rw-r--r-- | Bugzilla/Test/MockDB.pm | 120 | ||||
-rw-r--r-- | Bugzilla/Test/MockLocalconfig.pm | 18 | ||||
-rw-r--r-- | Bugzilla/Test/MockParams.pm | 71 | ||||
-rw-r--r-- | Bugzilla/Test/Util.pm | 2 | ||||
-rw-r--r-- | Bugzilla/Types.pm | 27 | ||||
-rw-r--r-- | Bugzilla/WebService/BugUserLastVisit.pm | 2 |
15 files changed, 339 insertions, 92 deletions
diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm index 9ac01c71e..ae997a5fe 100644 --- a/Bugzilla/CGI.pm +++ b/Bugzilla/CGI.pm @@ -39,7 +39,7 @@ sub DEFAULT_CSP { script_src => [ 'self', 'nonce', 'unsafe-inline', 'https://www.google-analytics.com' ], frame_src => [ 'none', ], worker_src => [ 'none', ], - img_src => [ 'self', 'https://secure.gravatar.com' ], + img_src => [ 'self', 'blob:', 'https://secure.gravatar.com' ], style_src => [ 'self', 'unsafe-inline' ], object_src => [ 'none' ], connect_src => [ diff --git a/Bugzilla/Config.pm b/Bugzilla/Config.pm index d050ff9e0..85779fa6b 100644 --- a/Bugzilla/Config.pm +++ b/Bugzilla/Config.pm @@ -251,28 +251,11 @@ sub write_params { my ($param_data) = @_; $param_data ||= Bugzilla->params; - my $datadir = bz_locations()->{'datadir'}; - my $param_file = "$datadir/params"; - local $Data::Dumper::Sortkeys = 1; - my ($fh, $tmpname) = File::Temp::tempfile('params.XXXXX', - DIR => $datadir ); - my %params = %$param_data; $params{urlbase} = Bugzilla->localconfig->{urlbase}; - print $fh (Data::Dumper->Dump([\%params], ['*param'])) - || die "Can't write param file: $!"; - - close $fh; - - rename $tmpname, $param_file - or die "Can't rename $tmpname to $param_file: $!"; - - # It's not common to edit parameters and loading - # Bugzilla::Install::Filesystem is slow. - require Bugzilla::Install::Filesystem; - Bugzilla::Install::Filesystem::fix_file_permissions($param_file); + __PACKAGE__->_write_file( Data::Dumper->Dump([\%params], ['*param']) ); # And now we have to reset the params cache so that Bugzilla will re-read # them. @@ -311,6 +294,24 @@ sub read_param_file { return \%params; } +sub _write_file { + my ($class, $str) = @_; + my $datadir = bz_locations()->{'datadir'}; + my $param_file = "$datadir/params"; + my ($fh, $tmpname) = File::Temp::tempfile('params.XXXXX', + DIR => $datadir ); + print $fh $str || die "Can't write param file: $!"; + close $fh || die "Can't close param file: $!"; + + rename $tmpname, $param_file + or die "Can't rename $tmpname to $param_file: $!"; + + # It's not common to edit parameters and loading + # Bugzilla::Install::Filesystem is slow. + require Bugzilla::Install::Filesystem; + Bugzilla::Install::Filesystem::fix_file_permissions($param_file); +} + 1; __END__ diff --git a/Bugzilla/DB/Sqlite.pm b/Bugzilla/DB/Sqlite.pm index 3890d0795..81ee7d888 100644 --- a/Bugzilla/DB/Sqlite.pm +++ b/Bugzilla/DB/Sqlite.pm @@ -73,7 +73,7 @@ sub BUILDARGS { my $db_name = $params->{db_name}; # Let people specify paths intead of data/ for the DB. - if ($db_name and $db_name !~ m{[\\/]}) { + if ($db_name && $db_name ne ':memory:' && $db_name !~ m{[\\/]}) { # When the DB is first created, there's a chance that the # data directory doesn't exist at all, because the Install::Filesystem # code happens after DB creation. So we create the directory ourselves diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm index 46e121779..1da33882b 100644 --- a/Bugzilla/Install/Filesystem.pm +++ b/Bugzilla/Install/Filesystem.pm @@ -67,55 +67,6 @@ use constant HTTPD_ENV => qw( NYTPROF_DIR ); -sub HTTPD_ENV_CONF { - my @env = (ENV_KEYS, HTTPD_ENV); - return join( "\n", map { "PerlPassEnv " . $_ } @env ) . "\n"; -} - -sub _error_page { - my ($code, $title, $description) = @_; - - return <<EOT; -<!DOCTYPE HTML> -<html> - <head> - <title>$title</title> - <style> - body { - margin: 1em 2em; - background-color: #455372; - color: #ddd; - font-family: sans-serif; - } - h1, h3 { - color: #fff; - } - a { - color: #fff; - text-decoration: none; - } - #buggie { - float: left; - } - #content { - margin-left: 100px; - padding-top: 20px; - } - </style> - </head> - <body> - <img src="/images/buggie.png" id="buggie" alt="buggie" width="78" height="215"> - <div id="content"> - <h1>$title</h1> - <p>$description</p> - <h3>Error $code</h3> - <p><a href="/">this site</a></p> - </div> - </body> -</html> -EOT -} - ############### # Permissions # ############### @@ -427,9 +378,6 @@ sub FILESYSTEM { "skins/yui3.css" => { perms => CGI_READ, overwrite => 1, contents => $yui3_all_css }, - "$confdir/env.conf" => { perms => CGI_READ, - overwrite => 1, - contents => \&HTTPD_ENV_CONF }, ); # Create static error pages. diff --git a/Bugzilla/Install/Localconfig.pm b/Bugzilla/Install/Localconfig.pm index 39063ee63..ac21a0cb7 100644 --- a/Bugzilla/Install/Localconfig.pm +++ b/Bugzilla/Install/Localconfig.pm @@ -186,7 +186,15 @@ use constant LOCALCONFIG_VARS => ( { name => 'shadowdb_pass', default => '', - } + }, + { + name => 'datadog_host', + default => '', + }, + { + name => 'datadog_port', + default => 8125, + }, ); diff --git a/Bugzilla/Quantum.pm b/Bugzilla/Quantum.pm index 8d46833c4..03dfcf0d0 100644 --- a/Bugzilla/Quantum.pm +++ b/Bugzilla/Quantum.pm @@ -61,10 +61,12 @@ sub startup { Bugzilla::WebService::Server::REST->preload; $r->any('/')->to('CGI#index_cgi'); + $r->any('/bug/<id:num>')->to('CGI#show_bug_cgi'); + $r->any('/<id:num>')->to('CGI#show_bug_cgi'); + $r->any('/rest')->to('CGI#rest_cgi'); $r->any('/rest.cgi/*PATH_INFO')->to( 'CGI#rest_cgi' => { PATH_INFO => '' } ); $r->any('/rest/*PATH_INFO')->to( 'CGI#rest_cgi' => { PATH_INFO => '' } ); - $r->any('/bug/:id')->to('CGI#show_bug_cgi'); $r->any('/extensions/BzAPI/bin/rest.cgi/*PATH_INFO')->to('CGI#bzapi_cgi'); $r->get( diff --git a/Bugzilla/Quantum/SES.pm b/Bugzilla/Quantum/SES.pm index 47c591fb5..03916075d 100644 --- a/Bugzilla/Quantum/SES.pm +++ b/Bugzilla/Quantum/SES.pm @@ -18,8 +18,25 @@ use JSON::MaybeXS qw(decode_json); use LWP::UserAgent (); use Try::Tiny qw(catch try); +use Types::Standard qw( :all ); +use Type::Utils; +use Type::Params qw( compile ); + +my $Invocant = class_type { class => __PACKAGE__ }; + sub main { my ($self) = @_; + try { + $self->_main; + } + catch { + FATAL("Error in SES Handler: ", $_); + $self->_respond( 400 => 'Bad Request' ); + }; +} + +sub _main { + my ($self) = @_; Bugzilla->error_mode(ERROR_MODE_DIE); my $message = $self->_decode_json_wrapper( $self->req->body ) // return; my $message_type = $self->req->headers->header('X-Amz-SNS-Message-Type') // '(missing)'; @@ -50,7 +67,8 @@ sub main { } sub _confirm_subscription { - my ($self, $message) = @_; + state $check = compile($Invocant, Dict[SubscribeURL => Str, slurpy Any]); + my ($self, $message) = $check->(@_); my $subscribe_url = $message->{SubscribeURL}; if ( !$subscribe_url ) { @@ -70,8 +88,17 @@ sub _confirm_subscription { $self->_respond( 200 => 'OK' ); } +my $NotificationType = Enum [qw( Bounce Complaint )]; +my $TypeField = Enum [qw(eventType notificationType)]; +my $Notification = Dict [ + eventType => Optional [$NotificationType], + notificationType => Optional [$NotificationType], + slurpy Any, +]; + sub _handle_notification { - my ( $self, $notification, $type_field ) = @_; + state $check = compile($Invocant, $Notification, $TypeField ); + my ( $self, $notification, $type_field ) = $check->(@_); if ( !exists $notification->{$type_field} ) { return 0; @@ -91,8 +118,28 @@ sub _handle_notification { return 1; } +my $BouncedRecipients = ArrayRef[ + Dict[ + emailAddress => Str, + action => Str, + diagnosticCode => Str, + slurpy Any, + ], +]; +my $BounceNotification = Dict [ + bounce => Dict [ + bouncedRecipients => $BouncedRecipients, + reportingMTA => Str, + bounceSubType => Str, + bounceType => Str, + slurpy Any, + ], + slurpy Any, +]; + sub _process_bounce { - my ($self, $notification) = @_; + state $check = compile($Invocant, $BounceNotification); + my ($self, $notification) = $check->(@_); # disable each account that is bouncing foreach my $recipient ( @{ $notification->{bounce}->{bouncedRecipients} } ) { @@ -132,11 +179,19 @@ sub _process_bounce { $self->_respond( 200 => 'OK' ); } -sub _process_complaint { - my ($self) = @_; +my $ComplainedRecipients = ArrayRef[Dict[ emailAddress => Str, slurpy Any ]]; +my $ComplaintNotification = Dict[ + complaint => Dict [ + complainedRecipients => $ComplainedRecipients, + complaintFeedbackType => Str, + slurpy Any, + ], + slurpy Any, +]; - # email notification to bugzilla admin - my ($notification) = @_; +sub _process_complaint { + state $check = compile($Invocant, $ComplaintNotification); + my ($self, $notification) = $check->(@_); my $template = Bugzilla->template_inner(); my $json = JSON::MaybeXS->new( pretty => 1, @@ -169,13 +224,9 @@ sub _respond { } sub _decode_json_wrapper { - my ($self, $json) = @_; + state $check = compile($Invocant, Str); + my ($self, $json) = $check->(@_); my $result; - if ( !defined $json ) { - WARN( 'Missing JSON from ' . $self->tx->remote_address ); - $self->_respond( 400 => 'Bad Request' ); - return undef; - } my $ok = try { $result = decode_json($json); } @@ -200,4 +251,4 @@ sub ua { return $ua; } -1;
\ No newline at end of file +1; diff --git a/Bugzilla/Quantum/Static.pm b/Bugzilla/Quantum/Static.pm index d687873ab..c01f062a4 100644 --- a/Bugzilla/Quantum/Static.pm +++ b/Bugzilla/Quantum/Static.pm @@ -11,7 +11,7 @@ use Bugzilla::Constants qw(bz_locations); my $LEGACY_RE = qr{ ^ (?:static/v[0-9]+\.[0-9]+/) ? - ( (?:extensions/[^/]+/web|(?:image|skin|j)s)/.+) + ( (?:extensions/[^/]+/web|(?:image|graph|skin|j)s)/.+) $ }xs; diff --git a/Bugzilla/Quantum/Stdout.pm b/Bugzilla/Quantum/Stdout.pm index be7b546ea..9cf19992c 100644 --- a/Bugzilla/Quantum/Stdout.pm +++ b/Bugzilla/Quantum/Stdout.pm @@ -11,6 +11,7 @@ use Moo; use Bugzilla::Logging; use Encode; +use English qw(-no_match_vars); has 'controller' => ( is => 'ro', @@ -41,7 +42,7 @@ sub PRINT { ## no critic (unpack) if ( $self->_encoding ) { $bytes = encode( $self->_encoding, $bytes ); } - $c->write($bytes.$\); + $c->write($bytes . ( $OUTPUT_RECORD_SEPARATOR // '' ) ); } sub BINMODE { diff --git a/Bugzilla/Test/MockDB.pm b/Bugzilla/Test/MockDB.pm new file mode 100644 index 000000000..fb7873ccf --- /dev/null +++ b/Bugzilla/Test/MockDB.pm @@ -0,0 +1,120 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. +package Bugzilla::Test::MockDB; +use 5.10.1; +use strict; +use warnings; +use Try::Tiny; +use Capture::Tiny qw(capture_merged); + +use Bugzilla::Test::MockLocalconfig ( + db_driver => 'sqlite', + db_name => ':memory:', +); +use Bugzilla; +BEGIN { Bugzilla->extensions }; +use Bugzilla::Test::MockParams ( + emailsuffix => '', + emailregexp => '.+', +); + +sub import { + require Bugzilla::Install; + require Bugzilla::Install::DB; + require Bugzilla::Field;; + + state $first_time = 0; + + return undef if $first_time++; + + return capture_merged { + Bugzilla->dbh->bz_setup_database(); + + # Populate the tables that hold the values for the <select> fields. + Bugzilla->dbh->bz_populate_enum_tables(); + + Bugzilla::Install::DB::update_fielddefs_definition(); + Bugzilla::Field::populate_field_definitions(); + Bugzilla::Install::init_workflow(); + Bugzilla::Install::DB->update_table_definitions({}); + Bugzilla::Install::update_system_groups(); + + Bugzilla->set_user(Bugzilla::User->super_user); + + Bugzilla::Install::update_settings(); + + my $dbh = Bugzilla->dbh; + if ( !$dbh->selectrow_array("SELECT 1 FROM priority WHERE value = 'P1'") ) { + $dbh->do("DELETE FROM priority"); + my $count = 100; + foreach my $priority (map { "P$_" } 1..5) { + $dbh->do( "INSERT INTO priority (value, sortkey) VALUES (?, ?)", undef, ( $priority, $count + 100 ) ); + } + } + my @flagtypes = ( + { + name => 'review', + desc => 'The patch has passed review by a module owner or peer.', + is_requestable => 1, + is_requesteeble => 1, + is_multiplicable => 1, + grant_group => '', + target_type => 'a', + cc_list => '', + inclusions => [''] + }, + { + name => 'feedback', + desc => 'A particular person\'s input is requested for a patch, ' . + 'but that input does not amount to an official review.', + is_requestable => 1, + is_requesteeble => 1, + is_multiplicable => 1, + grant_group => '', + target_type => 'a', + cc_list => '', + inclusions => [''] + } + ); + + foreach my $flag (@flagtypes) { + next if Bugzilla::FlagType->new({ name => $flag->{name} }); + my $grant_group_id = $flag->{grant_group} + ? Bugzilla::Group->new({ name => $flag->{grant_group} })->id + : undef; + my $request_group_id = $flag->{request_group} + ? Bugzilla::Group->new({ name => $flag->{request_group} })->id + : undef; + + $dbh->do('INSERT INTO flagtypes (name, description, cc_list, target_type, is_requestable, + is_requesteeble, is_multiplicable, grant_group_id, request_group_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', + undef, ($flag->{name}, $flag->{desc}, $flag->{cc_list}, $flag->{target_type}, + $flag->{is_requestable}, $flag->{is_requesteeble}, $flag->{is_multiplicable}, + $grant_group_id, $request_group_id)); + + my $type_id = $dbh->bz_last_key('flagtypes', 'id'); + + foreach my $inclusion (@{$flag->{inclusions}}) { + my ($product, $component) = split(':', $inclusion); + my ($prod_id, $comp_id); + if ($product) { + my $prod_obj = Bugzilla::Product->new({ name => $product }); + $prod_id = $prod_obj->id; + if ($component) { + $comp_id = Bugzilla::Component->new({ name => $component, product => $prod_obj})->id; + } + } + $dbh->do('INSERT INTO flaginclusions (type_id, product_id, component_id) + VALUES (?, ?, ?)', + undef, ($type_id, $prod_id, $comp_id)); + } + } + }; +} + +1; diff --git a/Bugzilla/Test/MockLocalconfig.pm b/Bugzilla/Test/MockLocalconfig.pm new file mode 100644 index 000000000..a32aea0d4 --- /dev/null +++ b/Bugzilla/Test/MockLocalconfig.pm @@ -0,0 +1,18 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. +package Bugzilla::Test::MockLocalconfig; +use 5.10.1; +use strict; +use warnings; + +sub import { + my ($class, %lc) = @_; + $ENV{LOCALCONFIG_ENV} = 'BMO'; + $ENV{"BMO_$_"} = $lc{$_} for keys %lc; +} + +1; diff --git a/Bugzilla/Test/MockParams.pm b/Bugzilla/Test/MockParams.pm new file mode 100644 index 000000000..2d064c616 --- /dev/null +++ b/Bugzilla/Test/MockParams.pm @@ -0,0 +1,71 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. +package Bugzilla::Test::MockParams; +use 5.10.1; +use strict; +use warnings; +use Try::Tiny; +use Capture::Tiny qw(capture_merged); +use Test2::Tools::Mock qw(mock); + +use Bugzilla::Config; +use Safe; + +our $Params; +BEGIN { + our $Mock = mock 'Bugzilla::Config' => ( + override => [ + 'read_param_file' => sub { + my ($class) = @_; + return {} unless $Params; + my $s = Safe->new; + $s->reval($Params); + die "Error evaluating params: $@" if $@; + return { %{ $s->varglob('param') } }; + }, + '_write_file' => sub { + my ($class, $str) = @_; + $Params = $str; + }, + ], + ); +} + +sub import { + my ($self, %answers) = @_; + state $first_time = 0; + + require Bugzilla::Field; + require Bugzilla::Status; + require Bugzilla; + my $Bugzilla = mock 'Bugzilla' => ( + override => [ + installation_answers => sub { \%answers }, + ], + ); + my $BugzillaField = mock 'Bugzilla::Field' => ( + override => [ + get_legal_field_values => sub { [] }, + ], + ); + my $BugzillaStatus = mock 'Bugzilla::Status' => ( + override => [ + closed_bug_statuses => sub { die "no database" }, + ], + ); + + if ($first_time++) { + capture_merged { + Bugzilla::Config::update_params(); + }; + } + else { + Bugzilla::Config::SetParam($_, $answers{$_}) for keys %answers; + } +} + +1;
\ No newline at end of file diff --git a/Bugzilla/Test/Util.pm b/Bugzilla/Test/Util.pm index 4c9981e52..02c842658 100644 --- a/Bugzilla/Test/Util.pm +++ b/Bugzilla/Test/Util.pm @@ -24,7 +24,7 @@ sub create_user { cryptpassword => $password, disabledtext => "", disable_mail => 0, - extern_id => 0, + extern_id => undef, %extra, }); } diff --git a/Bugzilla/Types.pm b/Bugzilla/Types.pm new file mode 100644 index 000000000..93d699f49 --- /dev/null +++ b/Bugzilla/Types.pm @@ -0,0 +1,27 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Types; + +use 5.10.1; +use strict; +use warnings; + +use Type::Library + -base, + -declare => qw( Bug User Group Attachment Comment JSONBool ); +use Type::Utils -all; +use Types::Standard -types; + +class_type Bug, { class => 'Bugzilla::Bug' }; +class_type User, { class => 'Bugzilla::User' }; +class_type Group, { class => 'Bugzilla::Group' }; +class_type Attachment, { class => 'Bugzilla::Attachment' }; +class_type Comment, { class => 'Bugzilla::Comment' }; +class_type JSONBool, { class => 'JSON::PP::Boolean' }; + +1; diff --git a/Bugzilla/WebService/BugUserLastVisit.pm b/Bugzilla/WebService/BugUserLastVisit.pm index 7b729c6c8..5e4c0d2ba 100644 --- a/Bugzilla/WebService/BugUserLastVisit.pm +++ b/Bugzilla/WebService/BugUserLastVisit.pm @@ -52,7 +52,7 @@ sub update { push( @results, $self->_bug_user_last_visit_to_hash( - $bug, $last_visit_ts, $params + $bug_id, $last_visit_ts, $params )); } $dbh->bz_commit_transaction(); |