diff options
83 files changed, 694 insertions, 1006 deletions
diff --git a/.gitignore b/.gitignore index 18f2d0a17..7bf2816b9 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,9 @@ /data /localconfig /localconfig.* +/conf/env.conf /index.html +/errors/ /error_reports /.DS_Store /template_cache diff --git a/.htaccess b/.htaccess deleted file mode 100644 index d9681baa6..000000000 --- a/.htaccess +++ /dev/null @@ -1,88 +0,0 @@ -# Don't allow people to retrieve non-cgi executable files or our private data -<FilesMatch (\.pm|\.pl|\.tmpl|\.swf|localconfig.*|cpanfile)$> - deny from all -</FilesMatch> - -AddType image/x-icon .ico -AddType application/font-woff .woff -AddType application/font-woff2 .woff2 - -Redirect permanent /queryhelp.cgi https://bugzilla.mozilla.org/query.cgi?format=advanced&help=1 -Redirect permanent /bug_status.html https://bugzilla.mozilla.org/page.cgi?id=fields.html -Redirect permanent /bugwritinghelp.html https://bugzilla.mozilla.org/page.cgi?id=bug-writing.html -Redirect permanent /etiquette.html https://bugzilla.mozilla.org/page.cgi?id=etiquette.html -Redirect permanent /duplicates.html https://bugzilla.mozilla.org/duplicates.cgi -Redirect permanent /quicksearch.html https://bugzilla.mozilla.org/page.cgi?id=quicksearch.html -Redirect permanent /bugwritinghelp.html https://bugzilla.mozilla.org/page.cgi?id=bug-writing.html - -RewriteEngine On -# This rewrite rule skips over the rest, which is good because the load balancers -# might hit this file once a second and we want apache to not take much time. -# Note that this file is generated by checksetup.pl -RewriteRule ^__lbheartbeat__$ - [L] - -# allow cloud-services to identify the version we're running. -# version.json is also generated by checksetup.pl -RewriteRule ^__version__$ version.json [L] - -# Unlike lbheartbeat, this endpoint is called less frequently (every five minutes or so) -# heartbeat.cgi returns 200 if the DB and memcached are both working, and 500 otherwise. -RewriteRule ^__heartbeat__$ heartbeat.cgi [L] - -RewriteRule ^static/v\d{4}\d{2}\d{2}\.\d+/(.+\.(?:js|css|woff2?|png|jpe?g|gif|ico|svg))$ $1 [NC,E=IMMUTABLE:1,L] -Header set Cache-Control "public, max-age=31536000" env=REDIRECT_IMMUTABLE - -RewriteRule ^robots\.txt$ robots.cgi [L] - -# New single page interface for filing bugs -RewriteRule ^new[-_]bug$ new_bug.cgi [L,QSA] - -RewriteRule ^template_cache/ - [F,L,NC] -RewriteRule ^template_cache.deleteme/ - [F,L,NC] -RewriteRule ^review$ page.cgi?id=splinter.html$1 [QSA] -RewriteRule ^user_?profile$ page.cgi?id=user_profile.html$1 [QSA] -RewriteRule ^request_defer$ page.cgi?id=request_defer.html$1 [QSA] -RewriteRule ^([0-9]+)$ show_bug.cgi?id=$1 [QSA] -RewriteRule ^favicon\.ico$ extensions/BMO/web/images/favicon.ico -RewriteRule ^form[\.:]itrequest$ enter_bug.cgi?product=Infrastructure+\%26+Operations&format=itrequest [QSA] -RewriteRule ^form[\.:](mozlist|poweredby|presentation|trademark|recoverykey)$ enter_bug.cgi?product=mozilla.org&format=$1 [QSA] -RewriteRule ^form[\.:]legal$ enter_bug.cgi?product=Legal&format=legal [QSA] -RewriteRule ^form[\.:]recruiting$ enter_bug.cgi?product=Recruiting&format=recruiting [QSA] -RewriteRule ^form[\.:]intern$ enter_bug.cgi?product=Recruiting&format=intern [QSA] -RewriteRule ^form[\.:]mozpr$ enter_bug.cgi?product=Mozilla+PR&format=mozpr [QSA] -RewriteRule ^form[\.:]reps[\.:]mentorship$ enter_bug.cgi?product=Mozilla+Reps&format=mozreps [QSA] -RewriteRule ^form[\.:]reps[\.:]budget$ enter_bug.cgi?product=Mozilla+Reps&format=remo-budget [QSA] -RewriteRule ^form[\.:]reps[\.:]swag$ enter_bug.cgi?product=Mozilla+Reps&format=remo-swag [QSA] -RewriteRule ^form[\.:]reps[\.:]payment$ page.cgi?id=remo-form-payment.html [QSA] -RewriteRule ^form[\.:]csa[\.:]discourse$ enter_bug.cgi?product=Infrastructure+\%26\+Operations&format=csa-discourse [QSA] -RewriteRule ^form[\.:]employee[\.\-:]incident$ enter_bug.cgi?product=mozilla.org&format=employee-incident [QSA] -RewriteRule ^form[\.:]brownbag$ https://air.mozilla.org/requests [QSA] -RewriteRule ^form[\.:]finance$ enter_bug.cgi?product=Finance&format=finance [QSA] -RewriteRule ^form[\.:]moz[\.\-:]project[\.\-:]review$ enter_bug.cgi?product=mozilla.org&format=moz-project-review [QSA] -RewriteRule ^form[\.:]docs?$ enter_bug.cgi?product=Developer+Documentation&format=doc [QSA] -RewriteRule ^form[\.:]mdn?$ enter_bug.cgi?product=developer.mozilla.org&format=mdn [QSA] -RewriteRule ^form[\.:](swag|gear)$ enter_bug.cgi?product=Marketing&format=swag [QSA] -RewriteRule ^form[\.:]costume$ enter_bug.cgi?product=Marketing&format=costume [QSA] -RewriteRule ^form[\.:]ipp$ enter_bug.cgi?product=Internet+Public+Policy&format=ipp [QSA] -RewriteRule ^form[\.:]creative$ enter_bug.cgi?product=Marketing&format=creative [QSA] -RewriteRule ^form[\.:]user[\.\-:]engagement$ enter_bug.cgi?product=Marketing&format=user-engagement [QSA] -RewriteRule ^form[\.:]dev[\.\-:]engagement[\.\-\:]event$ enter_bug.cgi?product=Developer+Engagement&format=dev-engagement-event [QSA] -RewriteRule ^form[\.:]mobile[\.\-:]compat$ enter_bug.cgi?product=Tech+Evangelism&format=mobile-compat [QSA] -RewriteRule ^form[\.:]web[\.:]bounty$ enter_bug.cgi?product=mozilla.org&format=web-bounty [QSA] -RewriteRule ^form[\.:]automative$ enter_bug.cgi?product=Testing&format=automative [QSA] -RewriteRule ^form[\.:]comm[\.:]newsletter$ enter_bug.cgi?product=Marketing&format=comm-newsletter [QSA] -RewriteRule ^form[\.:]screen[\.:]share[\.:]whitelist$ enter_bug.cgi?product=Firefox&format=screen-share-whitelist [QSA] -RewriteRule ^form[\.:]data[\.\-:]compliance$ enter_bug.cgi?product=Data+Compliance&format=data-compliance [QSA] -RewriteRule ^form[\.:]fsa[\.:]budget$ enter_bug.cgi?product=FSA&format=fsa-budget [QSA] -RewriteRule ^form[\.:]triage[\.\-]request$ page.cgi?id=triage_request.html [QSA] -RewriteRule ^form[\.:](crm|CRM)$ enter_bug.cgi?product=Marketing&format=crm [QSA] -RewriteRule ^form[\.:](ipc|IPC)$ https://airtable.com/shrcMqgbj1H9gXRlp [R,L] -RewriteRule ^form[\.:]nda$ enter_bug.cgi?product=Legal&format=nda [QSA] -RewriteRule ^form[\.:]name[\.:]clearance$ enter_bug.cgi?product=Legal&format=name-clearance [QSA] -RewriteRule ^form[\.:]shield[\.:]studies$ enter_bug.cgi?product=Shield&format=shield-studies [QSA] -RewriteRule ^form[\.:]client[\.:]bounty$ enter_bug.cgi?product=Firefox&format=client-bounty [QSA] -RewriteRule ^rest - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] -RewriteRule ^rest/(.*)$ rest.cgi/$1 [NE] -RewriteRule ^(?:latest|1\.2|1\.3)/(.*)$ extensions/BzAPI/bin/rest.cgi/$1 [NE] -RewriteRule ^bzapi/(.*)$ extensions/BzAPI/bin/rest.cgi/$1 [NE] -RewriteRule ^login$ index.cgi?GoAheadAndLogIn=1 [NE] diff --git a/Bugzilla.pm b/Bugzilla.pm index d8f13a3ad..1ea1e59a3 100644 --- a/Bugzilla.pm +++ b/Bugzilla.pm @@ -44,6 +44,7 @@ use File::Basename; use File::Spec::Functions; use Safe; use JSON::XS qw(decode_json); +use URI; use Scope::Guard; use parent qw(Bugzilla::CPAN); @@ -122,6 +123,14 @@ sub template_inner { } sub extensions { + # Guard against extensions querying the extension list during initialization + # (through this method or has_extension). + # The extension list is not fully populated at that point, + # so the results would not be meaningful. + state $recursive = 0; + die "Recursive attempt to load/query extensions" if $recursive; + $recursive = 1; + my $cache = request_cache; if (!$cache->{extensions}) { my $extension_packages = Bugzilla::Extension->load_all(); @@ -134,9 +143,20 @@ sub extensions { } $cache->{extensions} = \@extensions; } + $recursive = 0; return $cache->{extensions}; } +sub has_extension { + my ($class, $name) = @_; + my $cache = $class->request_cache; + if (!$cache->{extensions_hash}) { + my %extensions = map { $_->NAME => 1 } @{ Bugzilla->extensions }; + $cache->{extensions_hash} = \%extensions; + } + return exists $cache->{extensions_hash}{$name}; +} + sub cgi { return request_cache->{cgi} ||= Bugzilla::CGI->new; } @@ -161,6 +181,13 @@ sub localconfig { return $_[0]->process_cache->{localconfig} ||= read_localconfig(); } +sub urlbase { + my ($class) = @_; + + # Since this could be modified, we have to return a new one every time. + return URI->new($class->localconfig->{urlbase}); +} + sub params { return request_cache->{params} ||= Bugzilla::Config::read_param_file(); } diff --git a/Bugzilla/Config/General.pm b/Bugzilla/Config/General.pm index c870c7376..fa7cf2d08 100644 --- a/Bugzilla/Config/General.pm +++ b/Bugzilla/Config/General.pm @@ -25,6 +25,14 @@ use constant get_param_list => ( }, { + name => 'nobody_user', + type => 't', + no_reset => '1', + default => 'nobody@mozilla.org', + checker => \&check_email + }, + + { name => 'docs_urlbase', type => 't', default => 'docs/%lang%/html/', diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index d0b74b5e3..cd478c33e 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -196,6 +196,8 @@ use Memoize; EMAIL_LIMIT_EXCEPTION JOB_QUEUE_VIEW_MAX_JOBS + + BZ_PERSISTENT ); @Bugzilla::Constants::EXPORT_OK = qw(contenttypes); @@ -700,6 +702,8 @@ sub _bz_locations { }; } +use constant BZ_PERSISTENT => $main::BUGZILLA_PERSISTENT; + # This makes us not re-compute all the bz_locations data every time it's # called. BEGIN { memoize('_bz_locations') }; diff --git a/Bugzilla/Elastic/Role/HasClient.pm b/Bugzilla/Elastic/Role/HasClient.pm index 8e2687880..a971392e0 100644 --- a/Bugzilla/Elastic/Role/HasClient.pm +++ b/Bugzilla/Elastic/Role/HasClient.pm @@ -8,7 +8,6 @@ package Bugzilla::Elastic::Role::HasClient; use 5.10.1; use Moo::Role; -use Search::Elasticsearch; has 'client' => (is => 'lazy'); @@ -16,6 +15,7 @@ has 'client' => (is => 'lazy'); sub _build_client { my ($self) = @_; + require Search::Elasticsearch; return Search::Elasticsearch->new( nodes => [ split(/\s+/, Bugzilla->params->{elasticsearch_nodes}) ], cxn_pool => 'Sniff', diff --git a/Bugzilla/Error/disabled b/Bugzilla/Error/disabled new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/Bugzilla/Error/disabled diff --git a/Bugzilla/Group.pm b/Bugzilla/Group.pm index c941482f0..7f684ea15 100644 --- a/Bugzilla/Group.pm +++ b/Bugzilla/Group.pm @@ -26,17 +26,24 @@ use Scalar::Util qw(blessed); use constant IS_CONFIG => 1; -use constant DB_COLUMNS => qw( - groups.id - groups.name - groups.description - groups.isbuggroup - groups.userregexp - groups.isactive - groups.icon_url - groups.owner_user_id - groups.idle_member_removal -); +sub DB_COLUMNS { + my $class = shift; + my @columns = qw( + id + name + description + isbuggroup + userregexp + isactive + icon_url + owner_user_id + idle_member_removal + ); + my $dbh = Bugzilla->dbh; + my $table = $class->DB_TABLE; + + return map { "$table.$_" } grep { $dbh->bz_column_info($table, $_) } @columns; +} use constant DB_TABLE => 'groups'; diff --git a/Bugzilla/Install.pm b/Bugzilla/Install.pm index 8bce9b5e7..c9935f34d 100644 --- a/Bugzilla/Install.pm +++ b/Bugzilla/Install.pm @@ -31,21 +31,31 @@ use Bugzilla::Util qw(get_text); use Bugzilla::Version; use constant STATUS_WORKFLOW => ( - [undef, 'UNCONFIRMED'], - [undef, 'CONFIRMED'], - [undef, 'IN_PROGRESS'], - ['UNCONFIRMED', 'CONFIRMED'], - ['UNCONFIRMED', 'IN_PROGRESS'], - ['UNCONFIRMED', 'RESOLVED'], - ['CONFIRMED', 'IN_PROGRESS'], - ['CONFIRMED', 'RESOLVED'], - ['IN_PROGRESS', 'CONFIRMED'], - ['IN_PROGRESS', 'RESOLVED'], - ['RESOLVED', 'UNCONFIRMED'], - ['RESOLVED', 'CONFIRMED'], - ['RESOLVED', 'VERIFIED'], - ['VERIFIED', 'UNCONFIRMED'], - ['VERIFIED', 'CONFIRMED'], + [ undef, 'UNCONFIRMED' ], + [ undef, 'NEW' ], + [ undef, 'ASSIGNED' ], + [ 'UNCONFIRMED', 'NEW' ], + [ 'UNCONFIRMED', 'ASSIGNED' ], + [ 'UNCONFIRMED', 'RESOLVED' ], + [ 'NEW', 'UNCONFIRMED' ], + [ 'NEW', 'ASSIGNED' ], + [ 'NEW', 'RESOLVED' ], + [ 'ASSIGNED', 'UNCONFIRMED' ], + [ 'ASSIGNED', 'NEW' ], + [ 'ASSIGNED', 'RESOLVED' ], + [ 'REOPENED', 'UNCONFIRMED' ], + [ 'REOPENED', 'NEW' ], + [ 'REOPENED', 'ASSIGNED' ], + [ 'REOPENED', 'RESOLVED' ], + [ 'RESOLVED', 'UNCONFIRMED' ], + [ 'RESOLVED', 'REOPENED' ], + [ 'RESOLVED', 'VERIFIED' ], + [ 'VERIFIED', 'UNCONFIRMED' ], + [ 'VERIFIED', 'REOPENED' ], + [ 'VERIFIED', 'RESOLVED' ], + [ 'CLOSED', 'UNCONFIRMED' ], + [ 'CLOSED', 'REOPENED' ], + [ 'CLOSED', 'RESOLVED' ], ); sub SETTINGS { diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm index 2e5ae5ff2..8b3d4b8cc 100644 --- a/Bugzilla/Install/DB.pm +++ b/Bugzilla/Install/DB.pm @@ -3908,7 +3908,16 @@ sub _migrate_group_owners { my $dbh = Bugzilla->dbh; return if $dbh->bz_column_info('groups', 'owner_user_id'); $dbh->bz_add_column('groups', 'owner_user_id', {TYPE => 'INT3'}); - my $nobody = Bugzilla::User->check('nobody@mozilla.org'); + my $nobody = Bugzilla::User->new({ name => Bugzilla->params->{'nobody_user'}, cache => 1 }); + unless ($nobody) { + $nobody = Bugzilla::User->create( + { + login_name => Bugzilla->params->{'nobody_user'}, + realname => 'Nobody (ok to assign bugs to)', + cryptpassword => '*', + } + ); + } $dbh->do('UPDATE groups SET owner_user_id = ?', undef, $nobody->id); } diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm index 317152962..cb1b1ad15 100644 --- a/Bugzilla/Install/Filesystem.pm +++ b/Bugzilla/Install/Filesystem.pm @@ -164,6 +164,7 @@ sub FILESYSTEM { # users to be able to cron them or otherwise run # them as a secure user, like the webserver owner. '*.cgi' => { perms => WS_EXECUTE }, + '*.psgi' => { perms => CGI_READ }, 'whineatnews.pl' => { perms => WS_EXECUTE }, 'collectstats.pl' => { perms => WS_EXECUTE }, 'importxml.pl' => { perms => WS_EXECUTE }, @@ -295,7 +296,7 @@ sub FILESYSTEM { 'contrib' => { files => OWNER_EXECUTE, dirs => DIR_OWNER_WRITE, }, 'scripts' => { files => OWNER_EXECUTE, - dirs => DIR_OWNER_WRITE, }, + dirs => DIR_WS_SERVE, }, ); # --- FILES TO CREATE --- # @@ -379,6 +380,9 @@ sub FILESYSTEM { contents => $yui3_all_css }, ); + # Create static error pages. + $create_dirs{"errors"} = DIR_CGI_READ; + # Because checksetup controls the creation of index.html separately # from all other files, it gets its very own hash. my %index_html = ( @@ -464,7 +468,7 @@ sub update_filesystem { # Delete old files that no longer need to exist # 2001-04-29 jake@bugzilla.org - Remove oldemailtech - # http://bugzilla.mozilla.org/show_bugs.cgi?id=71552 + # http://bugzilla.mozilla.org/show_bug.cgi?id=71552 if (-d 'shadow') { print "Removing shadow directory...\n"; rmtree("shadow"); diff --git a/Bugzilla/PSGI.pm b/Bugzilla/PSGI.pm new file mode 100644 index 000000000..46352b319 --- /dev/null +++ b/Bugzilla/PSGI.pm @@ -0,0 +1,42 @@ +# 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::PSGI; +use 5.10.1; +use strict; +use warnings; + +use base qw(Exporter); + +use Bugzilla::Logging; +our @EXPORT_OK = qw(compile_cgi); + +sub compile_cgi { + my ($script) = @_; + require CGI::Compile; + require CGI::Emulate::PSGI; + + my $cgi = CGI::Compile->compile($script); + my $app = CGI::Emulate::PSGI->handler( + sub { + Bugzilla::init_page(); + $cgi->(); + } + ); + return sub { + my $env = shift; + if ($env->{'psgix.cleanup'}) { + push @{ $env->{'psgix.cleanup.handler'} }, \&Bugzilla::_cleanup; + } + my $res = $app->($env); + Bugzilla::_cleanup() if not $env->{'psgix.cleanup'}; + return $res; + }; +} + + +1;
\ No newline at end of file diff --git a/Bugzilla/Quantum/Plugin/BasicAuth.pm b/Bugzilla/Quantum/Plugin/BasicAuth.pm new file mode 100644 index 000000000..e17273404 --- /dev/null +++ b/Bugzilla/Quantum/Plugin/BasicAuth.pm @@ -0,0 +1,40 @@ +# 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::Quantum::Plugin::BasicAuth; +use 5.10.1; +use Mojo::Base qw(Mojolicious::Plugin); + +use Bugzilla::Logging; +use Carp; + +sub register { + my ( $self, $app, $conf ) = @_; + + $app->renderer->add_helper( + basic_auth => sub { + my ( $c, $realm, $auth_user, $auth_pass ) = @_; + my $req = $c->req; + my ( $user, $password ) = $req->url->to_abs->userinfo =~ /^([^:]+):(.*)/; + + unless ( $realm && $auth_user && $auth_pass ) { + croak 'basic_auth() called with missing parameters.'; + } + + unless ( $user eq $auth_user && $password eq $auth_pass ) { + WARN('username and password do not match'); + $c->res->headers->www_authenticate("Basic realm=\"$realm\""); + $c->res->code(401); + $c->rendered; + return 0; + } + + return 1; + } + ); +} + +1;
\ No newline at end of file diff --git a/Bugzilla/Quantum/Plugin/Hostage.pm b/Bugzilla/Quantum/Plugin/Hostage.pm index 63fad2be2..418b09a0c 100644 --- a/Bugzilla/Quantum/Plugin/Hostage.pm +++ b/Bugzilla/Quantum/Plugin/Hostage.pm @@ -1,85 +1,80 @@ package Bugzilla::Quantum::Plugin::Hostage; use 5.10.1; use Mojo::Base 'Mojolicious::Plugin'; -use Bugzilla::Logging; sub _attachment_root { - my ($base) = @_; - return undef unless $base; - return $base =~ m{^https?://(?:bug)?\%bugid\%\.([a-zA-Z\.-]+)} ? $1 : undef; + my ($base) = @_; + return undef unless $base; + return $base =~ m{^https?://(?:bug)?\%bugid\%\.([a-zA-Z\.-]+)} + ? $1 + : undef; } sub _attachment_host_regex { - my ($base) = @_; - return undef unless $base; - my $val = $base; - $val =~ s{^https?://}{}s; - $val =~ s{/$}{}s; - my $regex = quotemeta $val; - $regex =~ s/\\\%bugid\\\%/\\d+/g; - return qr/^$regex$/s; + my ($base) = @_; + return undef unless $base; + my $val = $base; + $val =~ s{^https?://}{}s; + $val =~ s{/$}{}s; + my $regex = quotemeta $val; + $regex =~ s/\\\%bugid\\\%/\\d+/g; + return qr/^$regex$/s; } sub register { - my ($self, $app, $conf) = @_; + my ( $self, $app, $conf ) = @_; - $app->hook(before_routes => \&_before_routes); + $app->hook(before_routes => \&_before_routes); } sub _before_routes { - my ($c) = @_; - state $urlbase = Bugzilla->localconfig->{urlbase}; - state $urlbase_uri = URI->new($urlbase); - state $urlbase_host = $urlbase_uri->host; - state $urlbase_host_regex = qr/^bug(\d+)\.\Q$urlbase_host\E$/; - state $attachment_base = Bugzilla->localconfig->{attachment_base}; - state $attachment_root = _attachment_root($attachment_base); - state $attachment_host_regex = _attachment_host_regex($attachment_base); + my ( $c ) = @_; + state $urlbase = Bugzilla->localconfig->{urlbase}; + state $urlbase_uri = URI->new($urlbase); + state $urlbase_host = $urlbase_uri->host; + state $urlbase_host_regex = qr/^bug(\d+)\.\Q$urlbase_host\E$/; + state $attachment_base = Bugzilla->localconfig->{attachment_base}; + state $attachment_root = _attachment_root($attachment_base); + state $attachment_host_regex = _attachment_host_regex($attachment_base); - my $stash = $c->stash; - my $req = $c->req; - my $url = $req->url->to_abs; + my $stash = $c->stash; + my $req = $c->req; + my $url = $req->url->to_abs; - return if $stash->{'mojo.static'}; + return if $stash->{'mojo.static'}; - my $hostname = $url->host; - return if $hostname eq $urlbase_host; + my $hostname = $url->host; + return if $hostname eq $urlbase_host; - my $path = $url->path; - return if $path eq '/__lbheartbeat__'; + my $path = $url->path; + return if $path eq '/__lbheartbeat__'; - if ($attachment_base && $hostname eq $attachment_root) { - DEBUG("redirecting to $urlbase because $hostname is $attachment_root"); - $c->redirect_to($urlbase); - return; - } - elsif ($attachment_base && $hostname =~ $attachment_host_regex) { - if ($path =~ m{^/attachment\.cgi}s) { - return; + if ($attachment_base && $hostname eq $attachment_root) { + $c->redirect_to($urlbase); + return; + } + elsif ($attachment_base && $hostname =~ $attachment_host_regex) { + if ($path =~ m{^/attachment\.cgi}s) { + return; + } else { + my $new_uri = $url->clone; + $new_uri->scheme($urlbase_uri->scheme); + $new_uri->host($urlbase_host); + $c->redirect_to($new_uri); + return; + } + } + elsif (my ($id) = $hostname =~ $urlbase_host_regex) { + my $new_uri = $urlbase_uri->clone; + $new_uri->path('/show_bug.cgi'); + $new_uri->query_form(id => $id); + $c->redirect_to($new_uri); + return; } else { - my $new_uri = $url->clone; - $new_uri->scheme($urlbase_uri->scheme); - $new_uri->host($urlbase_host); - DEBUG( - "redirecting to $new_uri because $hostname matches attachment regex"); - $c->redirect_to($new_uri); - return; + $c->redirect_to($urlbase); + return; } - } - elsif (my ($id) = $hostname =~ $urlbase_host_regex) { - my $new_uri = $urlbase_uri->clone; - $new_uri->path('/show_bug.cgi'); - $new_uri->query_form(id => $id); - DEBUG("redirecting to $new_uri because $hostname includes bug id"); - $c->redirect_to($new_uri); - return; - } - else { - DEBUG("redirecting to $urlbase because $hostname doesn't make sense"); - $c->redirect_to($urlbase); - return; - } } 1; diff --git a/Bugzilla/Quantum/SES.pm b/Bugzilla/Quantum/SES.pm index 2d19de240..03916075d 100644 --- a/Bugzilla/Quantum/SES.pm +++ b/Bugzilla/Quantum/SES.pm @@ -1,5 +1,4 @@ package Bugzilla::Quantum::SES; - # 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/. @@ -19,252 +18,237 @@ use JSON::MaybeXS qw(decode_json); use LWP::UserAgent (); use Try::Tiny qw(catch try); -use Type::Library -base, -declare => qw( - Self - Notification NotificationType TypeField - BounceNotification BouncedRecipients - ComplaintNotification ComplainedRecipients -); -use Type::Utils -all; -use Types::Standard -all; -use Type::Params qw(compile); - -class_type Self, {class => __PACKAGE__}; - -declare ComplainedRecipients, - as ArrayRef [Dict [emailAddress => Str, slurpy Any]]; -declare ComplaintNotification, - as Dict [ - complaint => Dict [ - complainedRecipients => ComplainedRecipients, - complaintFeedbackType => Str, - slurpy Any, - ], - slurpy Any, - ]; - -declare BouncedRecipients, - as ArrayRef [ - Dict [ - emailAddress => Str, - action => Optional [Str], - diagnosticCode => Optional [Str], - status => Optional [Str], - slurpy Any, - ], - ]; -declare BounceNotification, - as Dict [ - bounce => Dict [ - bouncedRecipients => BouncedRecipients, - reportingMTA => Str, - bounceSubType => Str, - bounceType => Str, - slurpy Any, - ], - slurpy Any, - ]; - -declare NotificationType, as Enum [qw( Bounce Complaint )]; -declare TypeField, as Enum [qw(eventType notificationType)]; -declare Notification, - as Dict [ - eventType => Optional [NotificationType], - notificationType => Optional [NotificationType], - slurpy Any, - ]; +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'); - }; + 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)'; - - if ($message_type eq 'SubscriptionConfirmation') { - $self->_confirm_subscription($message); - } - - elsif ($message_type eq 'Notification') { - my $notification = $self->_decode_json_wrapper($message->{Message}) - // return; - unless ( -# https://docs.aws.amazon.com/ses/latest/DeveloperGuide/event-publishing-retrieving-sns-contents.html - $self->_handle_notification($notification, 'eventType') - -# https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html - || $self->_handle_notification($notification, 'notificationType') - ) - { - WARN('Failed to find notification type'); - $self->_respond(400 => 'Bad Request'); + 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)'; + + if ( $message_type eq 'SubscriptionConfirmation' ) { + $self->_confirm_subscription($message); + } + + elsif ( $message_type eq 'Notification' ) { + my $notification = $self->_decode_json_wrapper( $message->{Message} ) // return; + unless ( + # https://docs.aws.amazon.com/ses/latest/DeveloperGuide/event-publishing-retrieving-sns-contents.html + $self->_handle_notification( $notification, 'eventType' ) + + # https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html + || $self->_handle_notification( $notification, 'notificationType' ) + ) + { + WARN('Failed to find notification type'); + $self->_respond( 400 => 'Bad Request' ); + } } - } - else { - WARN("Unsupported message-type: $message_type"); - $self->_respond(200 => 'OK'); - } + else { + WARN("Unsupported message-type: $message_type"); + $self->_respond( 200 => 'OK' ); + } } sub _confirm_subscription { - state $check = compile(Self, Dict [SubscribeURL => Str, slurpy Any]); - my ($self, $message) = $check->(@_); - - my $subscribe_url = $message->{SubscribeURL}; - if (!$subscribe_url) { - WARN('Bad SubscriptionConfirmation request: missing SubscribeURL'); - $self->_respond(400 => 'Bad Request'); - return; - } - - my $ua = ua(); - my $res = $ua->get($message->{SubscribeURL}); - if (!$res->is_success) { - WARN('Bad response from SubscribeURL: ' . $res->status_line); - $self->_respond(400 => 'Bad Request'); - return; - } - - $self->_respond(200 => 'OK'); + state $check = compile($Invocant, Dict[SubscribeURL => Str, slurpy Any]); + my ($self, $message) = $check->(@_); + + my $subscribe_url = $message->{SubscribeURL}; + if ( !$subscribe_url ) { + WARN('Bad SubscriptionConfirmation request: missing SubscribeURL'); + $self->_respond( 400 => 'Bad Request' ); + return; + } + + my $ua = ua(); + my $res = $ua->get( $message->{SubscribeURL} ); + if ( !$res->is_success ) { + WARN( 'Bad response from SubscribeURL: ' . $res->status_line ); + $self->_respond( 400 => 'Bad Request' ); + return; + } + + $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 { - state $check = compile(Self, Notification, TypeField); - my ($self, $notification, $type_field) = $check->(@_); - - if (!exists $notification->{$type_field}) { - return 0; - } - my $type = $notification->{$type_field}; - - if ($type eq 'Bounce') { - $self->_process_bounce($notification); - } - elsif ($type eq 'Complaint') { - $self->_process_complaint($notification); - } - else { - WARN("Unsupported notification-type: $type"); - $self->_respond(200 => 'OK'); - } - return 1; -} + state $check = compile($Invocant, $Notification, $TypeField ); + my ( $self, $notification, $type_field ) = $check->(@_); -sub _process_bounce { - state $check = compile(Self, BounceNotification); - my ($self, $notification) = $check->(@_); - - # disable each account that is bouncing - foreach my $recipient (@{$notification->{bounce}->{bouncedRecipients}}) { - my $address = $recipient->{emailAddress}; - my $reason = sprintf '(%s) %s', $recipient->{action} // 'error', - $recipient->{diagnosticCode} // 'unknown'; - - my $user = Bugzilla::User->new({name => $address, cache => 1}); - if ($user) { - - # never auto-disable admin accounts - if ($user->in_group('admin')) { - Bugzilla->audit("ignoring bounce for admin <$address>: $reason"); - } - - else { - my $template = Bugzilla->template_inner(); - my $vars = { - mta => $notification->{bounce}->{reportingMTA} // 'unknown', - reason => $reason, - }; - my $disable_text; - $template->process('admin/users/bounce-disabled.txt.tmpl', - $vars, \$disable_text) - || die $template->error(); - - $user->set_disabledtext($disable_text); - $user->set_disable_mail(1); - $user->update(); - Bugzilla->audit( - "bounce for <$address> disabled userid-" . $user->id . ": $reason"); - } + if ( !exists $notification->{$type_field} ) { + return 0; } + my $type = $notification->{$type_field}; + if ( $type eq 'Bounce' ) { + $self->_process_bounce($notification); + } + elsif ( $type eq 'Complaint' ) { + $self->_process_complaint($notification); + } else { - Bugzilla->audit("bounce for <$address> has no user: $reason"); + WARN("Unsupported notification-type: $type"); + $self->_respond( 200 => 'OK' ); + } + 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 { + state $check = compile($Invocant, $BounceNotification); + my ($self, $notification) = $check->(@_); + + # disable each account that is bouncing + foreach my $recipient ( @{ $notification->{bounce}->{bouncedRecipients} } ) { + my $address = $recipient->{emailAddress}; + my $reason = sprintf '(%s) %s', $recipient->{action} // 'error', $recipient->{diagnosticCode} // 'unknown'; + + my $user = Bugzilla::User->new( { name => $address, cache => 1 } ); + if ($user) { + + # never auto-disable admin accounts + if ( $user->in_group('admin') ) { + Bugzilla->audit("ignoring bounce for admin <$address>: $reason"); + } + + else { + my $template = Bugzilla->template_inner(); + my $vars = { + mta => $notification->{bounce}->{reportingMTA} // 'unknown', + reason => $reason, + }; + my $disable_text; + $template->process( 'admin/users/bounce-disabled.txt.tmpl', $vars, \$disable_text ) + || die $template->error(); + + $user->set_disabledtext($disable_text); + $user->set_disable_mail(1); + $user->update(); + Bugzilla->audit( "bounce for <$address> disabled userid-" . $user->id . ": $reason" ); + } + } + + else { + Bugzilla->audit("bounce for <$address> has no user: $reason"); + } } - } - $self->_respond(200 => 'OK'); + $self->_respond( 200 => 'OK' ); } +my $ComplainedRecipients = ArrayRef[Dict[ emailAddress => Str, slurpy Any ]]; +my $ComplaintNotification = Dict[ + complaint => Dict [ + complainedRecipients => $ComplainedRecipients, + complaintFeedbackType => Str, + slurpy Any, + ], + slurpy Any, +]; + sub _process_complaint { - state $check = compile(Self, ComplaintNotification); - my ($self, $notification) = $check->(@_); - my $template = Bugzilla->template_inner(); - my $json = JSON::MaybeXS->new(pretty => 1, utf8 => 1, canonical => 1,); - - foreach my $recipient (@{$notification->{complaint}->{complainedRecipients}}) - { - my $reason = $notification->{complaint}->{complaintFeedbackType} - // 'unknown'; - my $address = $recipient->{emailAddress}; - Bugzilla->audit("complaint for <$address> for '$reason'"); - my $vars = { - email => $address, - user => Bugzilla::User->new({name => $address, cache => 1}), - reason => $reason, - notification => $json->encode($notification), - }; - my $message; - $template->process('email/ses-complaint.txt.tmpl', $vars, \$message) - || die $template->error(); - MessageToMTA($message); - } + state $check = compile($Invocant, $ComplaintNotification); + my ($self, $notification) = $check->(@_); + my $template = Bugzilla->template_inner(); + my $json = JSON::MaybeXS->new( + pretty => 1, + utf8 => 1, + canonical => 1, + ); + + foreach my $recipient ( @{ $notification->{complaint}->{complainedRecipients} } ) { + my $reason = $notification->{complaint}->{complaintFeedbackType} // 'unknown'; + my $address = $recipient->{emailAddress}; + Bugzilla->audit("complaint for <$address> for '$reason'"); + my $vars = { + email => $address, + user => Bugzilla::User->new( { name => $address, cache => 1 } ), + reason => $reason, + notification => $json->encode($notification), + }; + my $message; + $template->process( 'email/ses-complaint.txt.tmpl', $vars, \$message ) + || die $template->error(); + MessageToMTA($message); + } - $self->_respond(200 => 'OK'); + $self->_respond( 200 => 'OK' ); } sub _respond { - my ($self, $code, $message) = @_; - $self->render(text => "$message\n", status => $code); + my ( $self, $code, $message ) = @_; + $self->render(text => "$message\n", status => $code); } sub _decode_json_wrapper { - state $check = compile(Self, Str); - my ($self, $json) = $check->(@_); - my $result; - my $ok = try { - $result = decode_json($json); - } - catch { - WARN('Malformed JSON from ' . $self->tx->remote_address); - $self->_respond(400 => 'Bad Request'); - return undef; - }; - return $ok ? $result : undef; + state $check = compile($Invocant, Str); + my ($self, $json) = $check->(@_); + my $result; + my $ok = try { + $result = decode_json($json); + } + catch { + WARN( 'Malformed JSON from ' . $self->tx->remote_address ); + $self->_respond( 400 => 'Bad Request' ); + return undef; + }; + return $ok ? $result : undef; } sub ua { - my $ua = LWP::UserAgent->new(); - $ua->timeout(10); - $ua->protocols_allowed(['http', 'https']); - if (my $proxy_url = Bugzilla->params->{'proxy_url'}) { - $ua->proxy(['http', 'https'], $proxy_url); - } - else { - $ua->env_proxy; - } - return $ua; + my $ua = LWP::UserAgent->new(); + $ua->timeout(10); + $ua->protocols_allowed( [ 'http', 'https' ] ); + if ( my $proxy_url = Bugzilla->params->{'proxy_url'} ) { + $ua->proxy( [ 'http', 'https' ], $proxy_url ); + } + else { + $ua->env_proxy; + } + return $ua; } 1; diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm index f419955dc..e15c60f7f 100644 --- a/Bugzilla/Search.pm +++ b/Bugzilla/Search.pm @@ -802,18 +802,20 @@ sub data { # BMO - to avoid massive amounts of joins, if we're selecting a lot of # tracking flags, replace them with placeholders. the values will be # retrieved later and injected into the result. - my %tf_map = map { $_ => 1 } Bugzilla::Extension::TrackingFlags::Flag->get_all_names(); - my @tf_selected = grep { exists $tf_map{$_} } @orig_fields; - # mysql has a limit of 61 joins, and we want to avoid massive amounts of joins - # 30 ensures we won't hit the limit, nor generate too many joins - if (scalar @tf_selected > 30) { - foreach my $column (@tf_selected) { - $self->COLUMNS->{$column}->{name} = "'---'"; + if (Bugzilla->has_extension('TrackingFlags')) { + my %tf_map = map { $_ => 1 } Bugzilla::Extension::TrackingFlags::Flag->get_all_names(); + my @tf_selected = grep { exists $tf_map{$_} } @orig_fields; + # mysql has a limit of 61 joins, and we want to avoid massive amounts of joins + # 30 ensures we won't hit the limit, nor generate too many joins + if (scalar @tf_selected > 30) { + foreach my $column (@tf_selected) { + $self->COLUMNS->{$column}->{name} = "'---'"; + } + $self->{tracking_flags} = \@tf_selected; + } + else { + $self->{tracking_flags} = []; } - $self->{tracking_flags} = \@tf_selected; - } - else { - $self->{tracking_flags} = []; } my $start_time = [gettimeofday()]; @@ -863,7 +865,7 @@ sub data { $self->{data} = [map { $data{$_} } @$bug_ids]; # BMO - get tracking flags values, and insert into result - if (@{ $self->{tracking_flags} }) { + if (Bugzilla->has_extension('TrackingFlags') && @{ $self->{tracking_flags} }) { # read values my $values; $sql = " diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm index c337b5af8..36435d637 100644 --- a/Bugzilla/Template.pm +++ b/Bugzilla/Template.pm @@ -995,6 +995,8 @@ sub create { 'feature_enabled' => sub { return Bugzilla->feature(@_); }, + 'has_extension' => sub { return Bugzilla->has_extension(@_); }, + # field_descs can be somewhat slow to generate, so we generate # it only once per-language no matter how many times # $template->process() is called. diff --git a/Makefile.PL b/Makefile.PL index 27a9e989e..f3772adf4 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -411,6 +411,7 @@ META.json: Makefile.PL \tmake distmeta 2>&1 /dev/null; mv */META.json . META.yml: Makefile.PL +1: hit EOF seeking end of quote/pattern starting at line 1 ending in / \tmake distmeta 2>&1 /dev/null; mv */META.yml . MAKE } diff --git a/docs/en/rst/integrating/templates.rst b/docs/en/rst/integrating/templates.rst index e631b7364..e563d8179 100644 --- a/docs/en/rst/integrating/templates.rst +++ b/docs/en/rst/integrating/templates.rst @@ -262,7 +262,7 @@ customizing for your installation. It needs a couple of lines of boilerplate at the top like this:: [% USE Bugzilla %] - [% cgi = Bugzilla.cgi % + [% cgi = Bugzilla.cgi %] Then, this template can reference the form fields you have created using the syntax ``[% cgi.param("field_name") %]``. When a bug report is diff --git a/editusers.cgi b/editusers.cgi index d2ad3a82f..beb9b3a4c 100755 --- a/editusers.cgi +++ b/editusers.cgi @@ -32,8 +32,7 @@ my $dbh = Bugzilla->dbh; my $userid = $user->id; my $editusers = $user->in_group('editusers'); my $disableusers = $user->in_group('disableusers'); - -local our $vars = {}; +local our $vars = {}; # Reject access if there is no sense in continuing. $editusers diff --git a/enter_bug.cgi b/enter_bug.cgi index 33cdf8535..5b8a97dba 100755 --- a/enter_bug.cgi +++ b/enter_bug.cgi @@ -37,6 +37,8 @@ use Bugzilla::Field; use Bugzilla::Status; use Bugzilla::UserAgent; +use List::Util qw(any); + my $user = Bugzilla->login(LOGIN_REQUIRED); my $cloned_bug; @@ -299,8 +301,13 @@ else { $default{'bug_severity'} = formvalue('bug_severity', Bugzilla->params->{'defaultseverity'}); # BMO - use per-product default hw/os - $default{'rep_platform'} = formvalue('rep_platform', $product->default_platform // detect_platform()); - $default{'op_sys'} = formvalue('op_sys', $product->default_op_sys // detect_op_sys()); + if (any { $_->NAME eq 'BMO' } @{ Bugzilla->extensions }) { + $default{'rep_platform'} = formvalue('rep_platform', $product->default_platform // detect_platform()); + $default{'op_sys'} = formvalue('op_sys', $product->default_op_sys // detect_op_sys()); + } else { + $default{'rep_platform'} = formvalue('rep_platform', detect_platform()); + $default{'op_sys'} = formvalue('op_sys', detect_op_sys()); + } $vars->{'rep_platform'} = detect_platform(); $vars->{'rep_op_sys'} = detect_op_sys(); diff --git a/errors/401.html b/errors/401.html deleted file mode 100644 index 8242b549f..000000000 --- a/errors/401.html +++ /dev/null @@ -1,40 +0,0 @@ -<!DOCTYPE HTML> -<html> - <head> - <title>Access Denied</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>Authentication Required</h1> - <p>This server could not verify that you are authorized to access - that url. you either supplied the wrong credentials (e.g., bad - password), or your browser doesn't understand how to supply the - credentials required.</p> - <h3>Error 401</h3> - <p><a href="/">bugzilla.mozilla.org</a></p> - </div> - </body> -</html> diff --git a/errors/403.html b/errors/403.html deleted file mode 100644 index e2faf8522..000000000 --- a/errors/403.html +++ /dev/null @@ -1,37 +0,0 @@ -<!DOCTYPE HTML> -<html> - <head> - <title>Access Denied</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>Access Denied</h1> - <p>Access to the requested resource has been denied.</p> - <h3>Error 403</h3> - <p><a href="/">bugzilla.mozilla.org</a></p> - </div> - </body> -</html> diff --git a/errors/404.html b/errors/404.html deleted file mode 100644 index 3b476471c..000000000 --- a/errors/404.html +++ /dev/null @@ -1,37 +0,0 @@ -<!DOCTYPE HTML> -<html> - <head> - <title>Object Not Found</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>Object Not Found</h1> - <p>The requested URL was not found on this server.</p> - <h3>Error 404</h3> - <p><a href="/">bugzilla.mozilla.org</a></p> - </div> - </body> -</html> diff --git a/errors/500.html b/errors/500.html deleted file mode 100644 index e0657001d..000000000 --- a/errors/500.html +++ /dev/null @@ -1,37 +0,0 @@ -<!DOCTYPE HTML> -<html> - <head> - <title>Internal Server Error</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>Internal Server Error</h1> - <p>The server encountered an internal error and was unable to complete your request.</p> - <h3>Error 500</h3> - <p><a href="/">bugzilla.mozilla.org</a></p> - </div> - </body> -</html> diff --git a/extensions/AntiSpam/lib/Config.pm b/extensions/AntiSpam/lib/Config.pm index e35a7f001..278baea8f 100644 --- a/extensions/AntiSpam/lib/Config.pm +++ b/extensions/AntiSpam/lib/Config.pm @@ -55,7 +55,7 @@ sub get_param_list { "This account has been automatically disabled as a result of " . "a high number of comments tagged as abusive.<br>\n<br>\n" . "All interactions on Bugzilla should follow our " . - "<a href=\"https://bugzilla.mozilla.org/page.cgi?id=etiquette.html\">" . + "<a href=\"" . Bugzilla->localconfig->{'urlbase'} . "page.cgi?id=etiquette.html\">" . "etiquette guidelines</a>.<br>\n<br>\n" . "Please contact the address at the end of this message if you " . "believe this to be an error, or if you would like your account " . diff --git a/extensions/BMO/Extension.pm b/extensions/BMO/Extension.pm index 6c4ad2ef2..7499f0d1c 100644 --- a/extensions/BMO/Extension.pm +++ b/extensions/BMO/Extension.pm @@ -46,6 +46,7 @@ use Bugzilla::User; use Bugzilla::UserAgent qw(detect_platform detect_op_sys); use Bugzilla::User::Setting; use Bugzilla::Util; +use Bugzilla::PSGI qw(compile_cgi); use Date::Parse; use DateTime; @@ -878,7 +879,7 @@ sub object_end_of_create { # Add default searches to new user's footer my $dbh = Bugzilla->dbh; - my $sharer = Bugzilla::User->new({ name => 'nobody@mozilla.org' }) + my $sharer = Bugzilla::User->new({ name => Bugzilla->params->{'nobody_user'} }) or return; my $group = Bugzilla::Group->new({ name => 'everyone' }) or return; @@ -919,7 +920,7 @@ sub _bug_reporters_hw_os { sub _bug_is_unassigned { my ($self) = @_; my $assignee = $self->assigned_to->login; - return $assignee eq 'nobody@mozilla.org' || $assignee =~ /\.bugs$/; + return $assignee eq Bugzilla->params->{'nobody_user'} || $assignee =~ /\.bugs$/; } sub _bug_has_current_patch { @@ -1100,7 +1101,7 @@ sub object_start_of_update { # and the assignee isn't a real person return unless - $new_bug->assigned_to->login eq 'nobody@mozilla.org' + $new_bug->assigned_to->login eq Bugzilla->params->{'nobody_user'} || $new_bug->assigned_to->login =~ /\.bugs$/; # and the user can set the status to NEW @@ -1527,15 +1528,15 @@ sub install_update_db { "www.mozilla.org" => 'websites-security', ); # 1. Set all to core-security by default - my $core_sec_group = Bugzilla::Group->new({ name => 'core-security' }); + my $core_sec_group = Bugzilla::Group->new({ name => Bugzilla->params->{insidergroup} }); $dbh->do("UPDATE products SET security_group_id = ?", undef, $core_sec_group->id); # 2. Update the ones that have explicit security groups foreach my $prod_name (keys %product_sec_groups) { my $group_name = $product_sec_groups{$prod_name}; - next if $group_name eq 'core-security'; # already done + next if $group_name eq Bugzilla->params->{insidergroup}; # already done my $group = Bugzilla::Group->new({ name => $group_name, cache => 1 }); if (!$group) { - warn "Security group $group_name not found. Using core-security instead.\n"; + warn "Security group $group_name not found. Using insider group instead.\n"; next; } $dbh->do("UPDATE products SET security_group_id = ? WHERE name = ?", undef, $group->id, $prod_name); @@ -1595,7 +1596,7 @@ sub field_end_of_create { my $name = $field->name; if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) { - Bugzilla->set_user(Bugzilla::User->check({ name => 'nobody@mozilla.org' })); + Bugzilla->set_user(Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} })); print "Creating IT permission grant bug for new field '$name'..."; } @@ -1666,6 +1667,28 @@ sub webservice { $dispatch->{BMO} = "Bugzilla::Extension::BMO::WebService"; } +sub psgi_builder { + my ($self, $args) = @_; + my $mount = $args->{mount}; + + my $ses_index = Plack::Builder::builder(sub { + my $auth_user = Bugzilla->localconfig->{ses_username}; + my $auth_pass = Bugzilla->localconfig->{ses_password}; + Plack::Builder::enable("Auth::Basic", authenticator => sub { + my ($username, $password, $env) = @_; + return ( $auth_user + && $auth_pass + && $username + && $password + && $username eq $auth_user + && $password eq $auth_pass ); + }); + compile_cgi("ses/index.cgi"); + }); + + $mount->{'ses/index.cgi'} = $ses_index; +} + our $search_content_matches; BEGIN { $search_content_matches = \&Bugzilla::Search::_content_matches; @@ -1951,7 +1974,7 @@ sub _post_employee_incident_bug { my ($investigate_bug, $ssh_key_bug); my $old_user = Bugzilla->user; eval { - Bugzilla->set_user(Bugzilla::User->new({ name => 'nobody@mozilla.org' })); + Bugzilla->set_user(Bugzilla::User->new({ name => Bugzilla->params->{'nobody_user'} })); my $new_user = Bugzilla->user; # HACK: User needs to be in the editbugs and primary bug's group to allow diff --git a/extensions/BMO/bin/bug_1093952.pl b/extensions/BMO/bin/bug_1093952.pl index 735c6a37a..fd891f4ae 100755 --- a/extensions/BMO/bin/bug_1093952.pl +++ b/extensions/BMO/bin/bug_1093952.pl @@ -52,7 +52,7 @@ printf "About to fix %s bugs\n", scalar(@$bugs); print "Press <Ctrl-C> to stop or <Enter> to continue...\n"; getc(); -my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org' }); +my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} }); my $field = Bugzilla::Field->check({ name => 'status_whiteboard' }); my $when = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)'); diff --git a/extensions/BMO/bin/bug_1141452.pl b/extensions/BMO/bin/bug_1141452.pl index 869593802..155c4704c 100755 --- a/extensions/BMO/bin/bug_1141452.pl +++ b/extensions/BMO/bin/bug_1141452.pl @@ -50,7 +50,7 @@ printf "About to fix %s bugs\n", scalar(@$flags); print "Press <Ctrl-C> to stop or <Enter> to continue...\n"; getc(); -my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org' }); +my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} }); my $when = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)'); $dbh->bz_start_transaction(); diff --git a/extensions/BMO/bin/migrate-github-pull-requests.pl b/extensions/BMO/bin/migrate-github-pull-requests.pl index 53c1727b5..c39778a4a 100755 --- a/extensions/BMO/bin/migrate-github-pull-requests.pl +++ b/extensions/BMO/bin/migrate-github-pull-requests.pl @@ -23,7 +23,7 @@ use Bugzilla::User; use Bugzilla::Util qw(trim); my $dbh = Bugzilla->dbh; -my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org' }); +my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} }); my $field = Bugzilla::Field->check({ name => 'attachments.mimetype' }); # grab list of suitable attachments diff --git a/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl index 697542ead..0bd1c94d7 100644 --- a/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl +++ b/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl @@ -297,7 +297,7 @@ function validate_form() { <input type="hidden" name="version" value="unspecified"> <input type="hidden" name="bug_severity" value="normal"> <input type="hidden" name="group" value="pr-private"> -<input type="hidden" name="assigned_to" id="assigned_to" value="nobody@mozilla.org"> +<input type="hidden" name="assigned_to" id="assigned_to" value="[% Param('nobody_user') FILTER html %]"> <input type="hidden" name="token" value="[% token FILTER html %]"> <div class="head"> diff --git a/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl index d6243c73b..9c0c4780d 100644 --- a/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl +++ b/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl @@ -43,7 +43,7 @@ please provide some information about your application or product.</p> <input type="hidden" name="priority" value="--"> <input type="hidden" name="op_sys" value="Other"> <input type="hidden" name="version" value="unspecified"> - <input type="hidden" name="assigned_to" value="nobody@mozilla.org"> + <input type="hidden" name="assigned_to" value="[% Param('nobody_user') FILTER html %]"> <input type="hidden" name="cc" value="liz@mozilla.com"> <input type="hidden" name="groups" value="marketing-private"> <input type="hidden" name="token" value="[% token FILTER html %]"> diff --git a/extensions/BMO/template/en/default/bug/create/create-web-bounty.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-web-bounty.html.tmpl index 92517cb80..803f2a746 100644 --- a/extensions/BMO/template/en/default/bug/create/create-web-bounty.html.tmpl +++ b/extensions/BMO/template/en/default/bug/create/create-web-bounty.html.tmpl @@ -88,7 +88,7 @@ function validateAndSubmit() { <input type="hidden" name="token" value="[% token FILTER html %]"> <div class="head_desc"> - <a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines"> + <a href="[% terms.BugWritingGuidelinesURL %]"> [% terms.Bug %] writing guidelines</a> </div> diff --git a/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl b/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl index 6ecd0bc75..d3c7412bf 100644 --- a/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl +++ b/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl @@ -17,7 +17,7 @@ [% END +%] [% UNLESS no_bug_guidelines %] Before reporting a [% terms.bug %], make sure you've read our - <a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines"> + <a href="[% terms.BugWritingGuidelinesURL %]"> [% terms.bug %] writing guidelines</a> and double checked that your [% terms.bug %] hasn't already been reported. Consult our list of <a href="https://bugzilla.mozilla.org/duplicates.cgi"> most frequently reported [% terms.bugs %]</a> and <a href="https://bugzilla.mozilla.org/query.cgi"> diff --git a/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl b/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl index e1c67605f..dc253ee03 100644 --- a/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl +++ b/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl @@ -7,5 +7,5 @@ #%] [% PROCESS global/redirect.html.tmpl - url = "https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines" + url = terms.BugWritingGuidelinesURL %] diff --git a/extensions/BMO/template/en/default/pages/etiquette.html.tmpl b/extensions/BMO/template/en/default/pages/etiquette.html.tmpl index 45dd5bd65..fe7d2cd3d 100644 --- a/extensions/BMO/template/en/default/pages/etiquette.html.tmpl +++ b/extensions/BMO/template/en/default/pages/etiquette.html.tmpl @@ -173,7 +173,7 @@ <h2>See Also</h2> <p> - <a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines">The [% terms.Bug %] Writing Guidelines</a>. + <a href="[% terms.BugWritingGuidelinesURL %]">The [% terms.Bug %] Writing Guidelines</a>. </p> [% INCLUDE global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/pages/group_admins.html.tmpl b/extensions/BMO/template/en/default/pages/group_admins.html.tmpl index cfa3bd3ea..838a1e84a 100644 --- a/extensions/BMO/template/en/default/pages/group_admins.html.tmpl +++ b/extensions/BMO/template/en/default/pages/group_admins.html.tmpl @@ -39,7 +39,7 @@ [% group.name FILTER html %]</span> </td> <td nowrap> - [% IF group.owner.login == 'nobody@mozilla.org' %] + [% IF group.owner.login == Param('nobody_user') %] – [% ELSE %] [% INCLUDE global/user.html.tmpl who = group.owner %] diff --git a/extensions/BugModal/Extension.pm b/extensions/BugModal/Extension.pm index 1291fca21..ef9c93a37 100644 --- a/extensions/BugModal/Extension.pm +++ b/extensions/BugModal/Extension.pm @@ -188,10 +188,12 @@ sub template_before_process { return if exists $bug->{error}; # trigger loading of tracking flags - Bugzilla::Extension::TrackingFlags->template_before_process({ - file => 'bug/edit.html.tmpl', - vars => $vars, - }); + if (Bugzilla->has_extension('TrackingFlags')) { + Bugzilla::Extension::TrackingFlags->template_before_process({ + file => 'bug/edit.html.tmpl', + vars => $vars, + }); + } if (any { $bug->product eq $_ } READABLE_BUG_STATUS_PRODUCTS) { my @flags = map { { name => $_->name, status => $_->status } } @{$bug->flags}; diff --git a/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl index 099e06c5e..f4cc83c6e 100644 --- a/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl +++ b/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl @@ -19,7 +19,7 @@ # these are used in a few places is_cced = bug.cc.contains(user.login); - unassigned = (bug.assigned_to.login == "nobody@mozilla.org") + unassigned = (bug.assigned_to.login == Param('nobody_user')) || (bug.assigned_to.login.search('\.bugs$')); # custom fields that have custom rendering, or should not be rendered diff --git a/extensions/BzAPI/Extension.pm b/extensions/BzAPI/Extension.pm index d812a01c4..ac9502fcb 100644 --- a/extensions/BzAPI/Extension.pm +++ b/extensions/BzAPI/Extension.pm @@ -15,6 +15,7 @@ use base qw(Bugzilla::Extension); use Bugzilla::Extension::BzAPI::Constants; use Bugzilla::Extension::BzAPI::Util qw(fix_credentials filter_wants_nocache); +use Bugzilla::PSGI qw(compile_cgi); use Bugzilla::Error; use Bugzilla::Util qw(trick_taint datetime_from); @@ -189,6 +190,14 @@ sub webservice_status_code_map { $status_code_map->{51} = STATUS_BAD_REQUEST; } +sub psgi_builder { + my ($self, $args) = @_; + my $mount = $args->{mount}; + + $mount->{'bzapi'} = compile_cgi('extensions/BzAPI/bin/rest.cgi'); +} + + ##################### # Utility Functions # ##################### diff --git a/extensions/ComponentWatching/Extension.pm b/extensions/ComponentWatching/Extension.pm index 25155f90b..fdeedff98 100644 --- a/extensions/ComponentWatching/Extension.pm +++ b/extensions/ComponentWatching/Extension.pm @@ -23,7 +23,7 @@ use Bugzilla::Util qw(detaint_natural trim trick_taint); our $VERSION = '2'; use constant REQUIRE_WATCH_USER => 1; -use constant DEFAULT_ASSIGNEE => 'nobody@mozilla.org'; +use constant DEFAULT_ASSIGNEE => Bugzilla->params->{'nobody_user'}; use constant REL_COMPONENT_WATCHER => 15; @@ -158,7 +158,9 @@ sub object_columns { my $columns = $args->{columns}; return unless $class->isa('Bugzilla::Component'); - push(@$columns, 'watch_user'); + if (Bugzilla->dbh->bz_column_info($class->DB_TABLE, 'watch_user')) { + push @$columns, 'watch_user'; + } } sub object_update_columns { diff --git a/extensions/ContributorEngagement/Extension.pm b/extensions/ContributorEngagement/Extension.pm index 949517ecf..35eba24ab 100644 --- a/extensions/ContributorEngagement/Extension.pm +++ b/extensions/ContributorEngagement/Extension.pm @@ -70,7 +70,10 @@ sub object_columns { my ($self, $args) = @_; my ($class, $columns) = @$args{qw(class columns)}; if ($class->isa('Bugzilla::User')) { - push(@$columns, 'first_patch_reviewed_id'); + my $dbh = Bugzilla->dbh; + if ($dbh->bz_column_info($class->DB_TABLE, 'first_patch_reviewed_id')) { + push @$columns, 'first_patch_reviewed_id'; + } } } diff --git a/extensions/EditComments/Extension.pm b/extensions/EditComments/Extension.pm index ab19ab6e7..e2ace3f23 100644 --- a/extensions/EditComments/Extension.pm +++ b/extensions/EditComments/Extension.pm @@ -191,7 +191,9 @@ sub object_columns { my ($self, $args) = @_; my ($class, $columns) = @$args{qw(class columns)}; if ($class->isa('Bugzilla::Comment')) { - push(@$columns, 'edit_count'); + if (Bugzilla->dbh->bz_column_info($class->DB_TABLE, 'edit_count')) { + push @$columns, 'edit_count'; + } } } diff --git a/extensions/FlagTypeComment/Extension.pm b/extensions/FlagTypeComment/Extension.pm index 3ec506176..e7b34113d 100644 --- a/extensions/FlagTypeComment/Extension.pm +++ b/extensions/FlagTypeComment/Extension.pm @@ -127,13 +127,18 @@ sub _set_ftc_states { 'active_or_has_flags' => $bug->id, }); - my $types = join(',', map { $_->id } @$flag_types); - my $states = "'" . join("','", FLAGTYPE_COMMENT_STATES) . "'"; - $db_result = $dbh->selectall_arrayref( - "SELECT type_id AS flagtype, on_status AS state, comment AS text - FROM flagtype_comments - WHERE type_id IN ($types) AND on_status IN ($states)", - { Slice => {} }); + if (@$flag_types) { + my $types = join(',', map { $_->id } @$flag_types); + my $states = "'" . join("','", FLAGTYPE_COMMENT_STATES) . "'"; + $db_result = $dbh->selectall_arrayref( + "SELECT type_id AS flagtype, on_status AS state, comment AS text + FROM flagtype_comments + WHERE type_id IN ($types) AND on_status IN ($states)", + { Slice => {} }); + } + else { + $db_result = []; + } } foreach my $row (@$db_result) { diff --git a/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl b/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl index 7e34e9920..07d814839 100644 --- a/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl +++ b/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl @@ -355,7 +355,7 @@ Product: <b><span id="dupes_product_name">?</span></b>: <ul> <li>Please fill out this form clearly, precisely and in as much detail as you can manage.</li> <li>Please report only a single problem at a time.</li> -<li><a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines" target="_blank" rel="noopener noreferrer">These guidelines</a> +<li><a href="[% terms.BugWritingGuidelinesURL %]" target="_blank" rel="noopener noreferrer">These guidelines</a> explain how to write effective [% terms.bug %] reports.</li> </ul> diff --git a/extensions/MozProjectReview/disabled b/extensions/MozProjectReview/disabled new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/extensions/MozProjectReview/disabled diff --git a/extensions/PhabBugz/disabled b/extensions/PhabBugz/disabled new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/extensions/PhabBugz/disabled diff --git a/extensions/PhabBugz/lib/Util.pm b/extensions/PhabBugz/lib/Util.pm index 67b29f27c..32f860413 100644 --- a/extensions/PhabBugz/lib/Util.pm +++ b/extensions/PhabBugz/lib/Util.pm @@ -101,7 +101,7 @@ sub get_bug_role_phids { my @bug_users = ( $bug->reporter ); push(@bug_users, $bug->assigned_to) - if $bug->assigned_to->email !~ /^nobody\@mozilla\.org$/; + if $bug->assigned_to->email != Bugzilla->params->{'nobody_user'}; push(@bug_users, $bug->qa_contact) if $bug->qa_contact; push(@bug_users, @{ $bug->cc_users }) if @{ $bug->cc_users }; diff --git a/extensions/Push/Config.pm b/extensions/Push/Config.pm index 860e31a23..59b78d5a2 100644 --- a/extensions/Push/Config.pm +++ b/extensions/Push/Config.pm @@ -42,12 +42,6 @@ use constant REQUIRED_MODULES => [ ]; use constant OPTIONAL_MODULES => [ - # connectors need the ability to extend this - { - package => 'Net-SFTP', - module => 'Net::SFTP', - version => '0' - }, { package => 'XML-Simple', module => 'XML::Simple', diff --git a/extensions/Push/disabled b/extensions/Push/disabled new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/extensions/Push/disabled diff --git a/extensions/Push/lib/Connector/TCL.pm b/extensions/Push/lib/Connector/TCL.pm deleted file mode 100644 index f5b430e47..000000000 --- a/extensions/Push/lib/Connector/TCL.pm +++ /dev/null @@ -1,353 +0,0 @@ -# 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::Extension::Push::Connector::TCL; - -use 5.10.1; -use strict; -use warnings; - -use base 'Bugzilla::Extension::Push::Connector::Base'; - -use Bugzilla::Constants; -use Bugzilla::Extension::Push::Constants; -use Bugzilla::Extension::Push::Serialise; -use Bugzilla::Extension::Push::Util; -use Bugzilla::User; -use Bugzilla::Attachment; - -use Digest::MD5 qw(md5_hex); -use Encode qw(encode_utf8); - -sub options { - return ( - { - name => 'tcl_user', - label => 'Bugzilla TCL User', - type => 'string', - default => 'tcl@bugzilla.tld', - required => 1, - validate => sub { - Bugzilla::User->new({ name => $_[0] }) - || die "Invalid Bugzilla user ($_[0])\n"; - }, - }, - { - name => 'sftp_host', - label => 'SFTP Host', - type => 'string', - default => '', - required => 1, - }, - { - name => 'sftp_port', - label => 'SFTP Port', - type => 'string', - default => '22', - required => 1, - validate => sub { - $_[0] =~ /\D/ && die "SFTP Port must be an integer\n"; - }, - }, - { - name => 'sftp_user', - label => 'SFTP Username', - type => 'string', - default => '', - required => 1, - }, - { - name => 'sftp_pass', - label => 'SFTP Password', - type => 'password', - default => '', - required => 1, - }, - { - name => 'sftp_remote_path', - label => 'SFTP Remote Path', - type => 'string', - default => '', - required => 0, - }, - ); -} - -my $_instance; - -sub init { - my ($self) = @_; - $_instance = $self; -} - -sub load_config { - my ($self) = @_; - $self->SUPER::load_config(@_); -} - -sub should_send { - my ($self, $message) = @_; - - my $data = $message->payload_decoded; - my $bug_data = $self->_get_bug_data($data) - || return 0; - - # sanity check user - $self->{tcl_user} ||= Bugzilla::User->new({ name => $self->config->{tcl_user} }); - if (!$self->{tcl_user} || !$self->{tcl_user}->is_enabled) { - return 0; - } - - # only send bugs created by the tcl user - unless ($bug_data->{reporter}->{id} == $self->{tcl_user}->id) { - return 0; - } - - # don't push changes made by the tcl user - if ($data->{event}->{user}->{id} == $self->{tcl_user}->id) { - return 0; - } - - # send comments - if ($data->{event}->{routing_key} eq 'comment.create') { - return 0 if $data->{comment}->{is_private}; - return 1; - } - - # send status and resolution updates - foreach my $change (@{ $data->{event}->{changes} }) { - return 1 if $change->{field} eq 'bug_status' - || $change->{field} eq 'resolution' - || $change->{field} eq 'cf_blocking_b2g'; - } - - # send attachments - if ($data->{event}->{routing_key} =~ /^attachment\./) { - return 0 if $data->{attachment}->{is_private}; - return 1; - } - - # and nothing else - return 0; -} - -sub send { - my ($self, $message) = @_; - my $logger = Bugzilla->push_ext->logger; - my $config = $self->config; - - require XML::Simple; - require Net::SFTP; - - $self->{tcl_user} ||= Bugzilla::User->new({ name => $self->config->{tcl_user} }); - if (!$self->{tcl_user}) { - return (PUSH_RESULT_TRANSIENT, "Invalid bugzilla-user (" . $self->config->{tcl_user} . ")"); - } - - # load the bug - my $data = $message->payload_decoded; - my $bug_data = $self->_get_bug_data($data); - - # build payload - my $attachment; - my %xml = ( - Mozilla_ID => $bug_data->{id}, - When => $data->{event}->{time}, - Who => $data->{event}->{user}->{login}, - Status => $bug_data->{status}->{name}, - Resolution => $bug_data->{resolution}, - Blocking_B2G => $bug_data->{cf_blocking_b2g}, - ); - if ($data->{event}->{routing_key} eq 'comment.create') { - $xml{Comment} = $data->{comment}->{body}; - } elsif ($data->{event}->{routing_key} =~ /^attachment\.(\w+)/) { - my $is_update = $1 eq 'modify'; - if (!$is_update) { - $attachment = Bugzilla::Attachment->new($data->{attachment}->{id}); - } - $xml{Attach} = { - Attach_ID => $data->{attachment}->{id}, - Filename => $data->{attachment}->{file_name}, - Description => $data->{attachment}->{description}, - ContentType => $data->{attachment}->{content_type}, - IsPatch => $data->{attachment}->{is_patch} ? 'true' : 'false', - IsObsolete => $data->{attachment}->{is_obsolete} ? 'true' : 'false', - IsUpdate => $is_update ? 'true' : 'false', - }; - } - - # convert to xml - my $xml = XML::Simple::XMLout( - \%xml, - NoAttr => 1, - RootName => 'sync', - XMLDecl => 1, - ); - $xml = encode_utf8($xml); - - # generate md5 - my $md5 = md5_hex($xml); - - # build filename - my ($sec, $min, $hour, $day, $mon, $year) = localtime(time); - my $change_set = $data->{event}->{change_set}; - $change_set =~ s/\.//g; - my $filename = sprintf( - '%04s%02d%02d%02d%02d%02d%s', - $year + 1900, - $mon + 1, - $day, - $hour, - $min, - $sec, - $change_set, - ); - - # create temp files; - my $temp_dir = File::Temp::Directory->new(); - my $local_dir = $temp_dir->dirname; - _write_file("$local_dir/$filename.sync", $xml); - _write_file("$local_dir/$filename.sync.check", $md5); - _write_file("$local_dir/$filename.done", ''); - if ($attachment) { - _write_file("$local_dir/$filename.sync.attach", $attachment->data); - } - - my $remote_dir = $self->config->{sftp_remote_path} eq '' - ? '' - : $self->config->{sftp_remote_path} . '/'; - - # send files via sftp - $logger->debug("Connecting to " . $self->config->{sftp_host} . ":" . $self->config->{sftp_port}); - my $sftp = Net::SFTP->new( - $self->config->{sftp_host}, - ssh_args => { - port => $self->config->{sftp_port}, - }, - user => $self->config->{sftp_user}, - password => $self->config->{sftp_pass}, - ); - - $logger->debug("Uploading $local_dir/$filename.sync"); - $sftp->put("$local_dir/$filename.sync", "$remote_dir$filename.sync") - or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.sync"); - - $logger->debug("Uploading $local_dir/$filename.sync.check"); - $sftp->put("$local_dir/$filename.sync.check", "$remote_dir$filename.sync.check") - or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.sync.check"); - - if ($attachment) { - $logger->debug("Uploading $local_dir/$filename.sync.attach"); - $sftp->put("$local_dir/$filename.sync.attach", "$remote_dir$filename.sync.attach") - or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.sync.attach"); - } - - $logger->debug("Uploading $local_dir/$filename.done"); - $sftp->put("$local_dir/$filename.done", "$remote_dir$filename.done") - or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.done"); - - # success - return (PUSH_RESULT_OK, "uploaded $filename.sync"); -} - -sub _get_bug_data { - my ($self, $data) = @_; - my $target = $data->{event}->{target}; - if ($target eq 'bug') { - return $data->{bug}; - } elsif (exists $data->{$target}->{bug}) { - return $data->{$target}->{bug}; - } else { - return; - } -} - -sub _write_file { - my ($filename, $content) = @_; - open(my $fh, ">", $filename) or die "Failed to write to $filename: $!\n"; - binmode($fh); - print $fh $content; - close($fh) or die "Failed to write to $filename: $!\n"; -} - -1; - -# File::Temp->newdir() requires a newer version of File::Temp than we have on -# production, so here's a small inline package which performs the same task. - -package File::Temp::Directory; - -use strict; -use warnings; - -use File::Temp; -use File::Path qw(rmtree); -use File::Spec; - -my @chars; - -sub new { - my ($class) = @_; - my $self = {}; - bless($self, $class); - - @chars = qw/ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z - a b c d e f g h i j k l m n o p q r s t u v w x y z - 0 1 2 3 4 5 6 7 8 9 _ - /; - - $self->{TEMPLATE} = File::Spec->catdir(File::Spec->tmpdir, 'X' x 10); - $self->{DIRNAME} = $self->_mktemp(); - return $self; -} - -sub _mktemp { - my ($self) = @_; - my $path = $self->_random_name(); - while(1) { - if (mkdir($path, 0700)) { - # in case of odd umask - chmod(0700, $path); - return $path; - } else { - # abort with error if the reason for failure was anything except eexist - die "Could not create directory $path: $!\n" unless ($!{EEXIST}); - # loop round for another try - } - $path = $self->_random_name(); - } - - return $path; -} - -sub _random_name { - my ($self) = @_; - my $path = $self->{TEMPLATE}; - $path =~ s/X/$chars[int(rand(@chars))]/ge; - return $path; -} - -sub dirname { - my ($self) = @_; - return $self->{DIRNAME}; -} - -sub DESTROY { - my ($self) = @_; - local($., $@, $!, $^E, $?); - if (-d $self->{DIRNAME}) { - # Some versions of rmtree will abort if you attempt to remove the - # directory you are sitting in. We protect that and turn it into a - # warning. We do this because this occurs during object destruction and - # so can not be caught by the user. - eval { rmtree($self->{DIRNAME}, 0, 0); }; - warn $@ if ($@ && $^W); - } -} - -1; - diff --git a/extensions/RestrictComments/Extension.pm b/extensions/RestrictComments/Extension.pm index 213a1c44a..e93540d5a 100644 --- a/extensions/RestrictComments/Extension.pm +++ b/extensions/RestrictComments/Extension.pm @@ -68,7 +68,9 @@ sub object_columns { my ($self, $args) = @_; my ($class, $columns) = @$args{qw(class columns)}; if ($class->isa('Bugzilla::Bug')) { - push(@$columns, 'restrict_comments'); + if (Bugzilla->dbh->bz_column_info($class->DB_TABLE, 'restrict_comments')) { + push @$columns, 'restrict_comments'; + } } } diff --git a/extensions/Review/Extension.pm b/extensions/Review/Extension.pm index 406c29c7c..a918a5ca5 100644 --- a/extensions/Review/Extension.pm +++ b/extensions/Review/Extension.pm @@ -286,10 +286,14 @@ sub object_columns { my ($self, $args) = @_; my ($class, $columns) = @$args{qw(class columns)}; if ($class->isa('Bugzilla::Product')) { - push @$columns, 'reviewer_required'; + my $dbh = Bugzilla->dbh; + my @new_columns = qw(reviewer_required); + push @$columns, grep { $dbh->bz_column_info($class->DB_TABLE, $_) } @new_columns; } elsif ($class->isa('Bugzilla::User')) { - push @$columns, qw(review_request_count feedback_request_count needinfo_request_count); + my $dbh = Bugzilla->dbh; + my @new_columns = qw(review_request_count feedback_request_count needinfo_request_count); + push @$columns, grep { $dbh->bz_column_info($class->DB_TABLE, $_) } @new_columns; } } diff --git a/extensions/Review/bin/migrate_mentor_from_whiteboard.pl b/extensions/Review/bin/migrate_mentor_from_whiteboard.pl index c6b69006f..debf173a7 100755 --- a/extensions/Review/bin/migrate_mentor_from_whiteboard.pl +++ b/extensions/Review/bin/migrate_mentor_from_whiteboard.pl @@ -36,7 +36,7 @@ EOF <>; # we need to be logged in to do user searching and update bugs -my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org' }); +my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} }); $nobody->{groups} = [ Bugzilla::Group->get_all ]; Bugzilla->set_user($nobody); diff --git a/extensions/Review/lib/WebService.pm b/extensions/Review/lib/WebService.pm index 3f6816916..0c54d725a 100644 --- a/extensions/Review/lib/WebService.pm +++ b/extensions/Review/lib/WebService.pm @@ -51,7 +51,7 @@ sub suggestions { # we always need to be authentiated to perform user matching my $user = Bugzilla->user; if (!$user->id) { - Bugzilla->set_user(Bugzilla::User->check({ name => 'nobody@mozilla.org' })); + Bugzilla->set_user(Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} })); push @reviewers, @{ $bug->mentors }; Bugzilla->set_user($user); } else { diff --git a/extensions/SecureMail/Extension.pm b/extensions/SecureMail/Extension.pm index 508b1f5e8..2b5e1bdd6 100644 --- a/extensions/SecureMail/Extension.pm +++ b/extensions/SecureMail/Extension.pm @@ -104,7 +104,10 @@ sub object_columns { my $columns = $args->{'columns'}; if ($class->isa('Bugzilla::Group')) { - push(@$columns, 'secure_mail'); + my $dbh = Bugzilla->dbh; + if ($dbh->bz_column_info($class->DB_TABLE, 'secure_mail')) { + push @$columns, 'secure_mail'; + } } } diff --git a/extensions/TagNewUsers/Extension.pm b/extensions/TagNewUsers/Extension.pm index b94873979..1810f204f 100644 --- a/extensions/TagNewUsers/Extension.pm +++ b/extensions/TagNewUsers/Extension.pm @@ -123,7 +123,9 @@ sub object_columns { my ($self, $args) = @_; my ($class, $columns) = @$args{qw(class columns)}; if ($class->isa('Bugzilla::User')) { - push(@$columns, qw(comment_count creation_ts first_patch_bug_id)); + my $dbh = Bugzilla->dbh; + my @new_columns = qw(comment_count creation_ts first_patch_bug_id); + push @$columns, grep { $dbh->bz_column_info($class->DB_TABLE, $_) } @new_columns; } } @@ -131,9 +133,14 @@ sub object_before_create { my ($self, $args) = @_; my ($class, $params) = @$args{qw(class params)}; if ($class->isa('Bugzilla::User')) { - my ($timestamp) = Bugzilla->dbh->selectrow_array("SELECT NOW()"); - $params->{comment_count} = 0; - $params->{creation_ts} = $timestamp; + my $dbh = Bugzilla->dbh; + my ($timestamp) = $dbh->selectrow_array("SELECT NOW()"); + if ($dbh->bz_column_info($class->DB_TABLE, 'comment_count')) { + $params->{comment_count} = 0; + } + if ($dbh->bz_column_info($class->DB_TABLE, 'creation_ts')) { + $params->{creation_ts} = $timestamp; + } } elsif ($class->isa('Bugzilla::Attachment')) { if ($params->{ispatch} && !Bugzilla->user->first_patch_bug_id) { Bugzilla->user->first_patch_bug_id($params->{bug}->id); diff --git a/extensions/TrackingFlags/bin/bug_825946.pl b/extensions/TrackingFlags/bin/bug_825946.pl index 3f380b7ac..896dc5448 100755 --- a/extensions/TrackingFlags/bin/bug_825946.pl +++ b/extensions/TrackingFlags/bin/bug_825946.pl @@ -24,7 +24,7 @@ use Bugzilla::Bug qw(LogActivityEntry); Bugzilla->usage_mode(USAGE_MODE_CMDLINE); my $dbh = Bugzilla->dbh; -my $user = Bugzilla::User->check({name => 'nobody@mozilla.org'}); +my $user = Bugzilla::User->check({name => Bugzilla->params->{'nobody_user'}}); my $tf_vis = $dbh->selectall_arrayref(<<SQL); SELECT diff --git a/extensions/TrackingFlags/bin/bulk_flag_clear.pl b/extensions/TrackingFlags/bin/bulk_flag_clear.pl index 1745018d5..305fbf883 100755 --- a/extensions/TrackingFlags/bin/bulk_flag_clear.pl +++ b/extensions/TrackingFlags/bin/bulk_flag_clear.pl @@ -110,7 +110,7 @@ if (!$config->{update_db}) { # update bugs -my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org' }); +my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} }); # put our nobody user into all groups to avoid permissions issues $nobody->{groups} = [Bugzilla::Group->get_all]; Bugzilla->set_user($nobody); diff --git a/extensions/TrackingFlags/disabled b/extensions/TrackingFlags/disabled new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/extensions/TrackingFlags/disabled diff --git a/extensions/UserProfile/Extension.pm b/extensions/UserProfile/Extension.pm index 079f7a948..9171b942d 100644 --- a/extensions/UserProfile/Extension.pm +++ b/extensions/UserProfile/Extension.pm @@ -385,7 +385,9 @@ sub object_columns { my ($self, $args) = @_; my ($class, $columns) = @$args{qw(class columns)}; if ($class->isa('Bugzilla::User')) { - push(@$columns, qw(last_activity_ts last_statistics_ts)); + my $dbh = Bugzilla->dbh; + my @new_columns = qw(last_activity_ts last_statistics_ts); + push @$columns, grep { $dbh->bz_column_info($class->DB_TABLE, $_) } @new_columns; } } diff --git a/js/instant-search.js b/js/instant-search.js index 6ce3516a7..93c0ef599 100644 --- a/js/instant-search.js +++ b/js/instant-search.js @@ -191,7 +191,7 @@ YAHOO.bugzilla.instantSearch = { var result = []; var name = Dom.get('product').value; result.push(name); - if (products[name] && products[name].related) { + if (typeof products !== 'undefined' && products[name] && products[name].related) { for (var i = 0, n = products[name].related.length; i < n; i++) { result.push(products[name].related[i]); } diff --git a/scripts/eject-users-from-groups.pl b/scripts/eject-users-from-groups.pl index 52e2bbbf3..4b27be83d 100755 --- a/scripts/eject-users-from-groups.pl +++ b/scripts/eject-users-from-groups.pl @@ -23,7 +23,7 @@ Bugzilla->usage_mode(USAGE_MODE_CMDLINE); my $dbh = Bugzilla->dbh; my @remove_group_names; -my $nobody_name = 'nobody@mozilla.org'; +my $nobody_name = Bugzilla->params->{'nobody_user'}; my $admin_name = 'automation@bmo.tld'; GetOptions( diff --git a/scripts/entrypoint.pl b/scripts/entrypoint.pl index 21d9aebb1..f5c52f6a6 100755 --- a/scripts/entrypoint.pl +++ b/scripts/entrypoint.pl @@ -57,11 +57,6 @@ check_env(qw( BMO_urlbase )); -if ( $ENV{BMO_urlbase} eq 'AUTOMATIC' ) { - $ENV{BMO_urlbase} = sprintf 'http://%s:%d/%s', hostname(), $ENV{PORT}, $ENV{BZ_QA_LEGACY_MODE} ? 'bmo/' : ''; - $ENV{BZ_BASE_URL} = sprintf 'http://%s:%d', hostname(), $ENV{PORT}; -} - $func->($opts->()); sub cmd_demo { @@ -110,6 +105,11 @@ sub cmd_dev_httpd { exit $httpd_exit_f->get; } +sub cmd_checksetup_gen_files { + my (@args) = @_; + run( 'perl', 'checksetup.pl', '--no-database', @args); +} + sub cmd_checksetup { check_data_dir(); wait_for_db(); @@ -140,7 +140,7 @@ sub cmd_test_webservices { check_data_dir(); copy_qa_extension(); assert_database()->get; - my $httpd_exit_f = run_cereal_and_httpd('-DHTTPD_IN_SUBDIR', '-DACCESS_LOGS'); + my $httpd_exit_f = run_cereal_and_httpd('-DHTTPD_IN_SUBDIR'); my $prove_exit_f = run_prove( httpd_url => $conf->{browser_url}, prove_cmd => [ @@ -195,7 +195,7 @@ sub cmd_test_bmo { $ENV{BZ_TEST_NEWBIE2} = 'newbie2@mozilla.example'; $ENV{BZ_TEST_NEWBIE2_PASS} = 'captain.space.pants.time.lord'; - my $httpd_exit_f = run_cereal_and_httpd('-DACCESS_LOGS'); + my $httpd_exit_f = run_cereal_and_httpd(); my $prove_exit_f = run_prove( httpd_url => $ENV{BZ_BASE_URL}, prove_cmd => [ 'prove', '-I/app', '-I/app/local/lib/perl5', @prove_args ], @@ -244,6 +244,10 @@ sub copy_qa_extension { dircopy('/app/qa/extensions/QA', '/app/extensions/QA'); } +sub cmd_wait_for_db { + wait_for_db(); +} + sub wait_for_db { assert_database()->get; } diff --git a/scripts/generate_bmo_data.pl b/scripts/generate_bmo_data.pl index 6356762c8..8a9f72d17 100755 --- a/scripts/generate_bmo_data.pl +++ b/scripts/generate_bmo_data.pl @@ -158,7 +158,7 @@ $group->update(); my @users = ( { - login => 'nobody@mozilla.org', + login => Bugzilla->params->{'nobody_user'}, realname => 'Nobody; OK to take it and work on it', password => '*' }, @@ -267,7 +267,7 @@ my @products = ( name => 'General', description => 'For bugs in Firefox which do not fit into ' . 'other more specific Firefox components', - initialowner => 'nobody@mozilla.org', + initialowner => Bugzilla->params->{'nobody_user'}, initialqaowner => '', initial_cc => [], watch_user => 'general@firefox.bugs' @@ -287,7 +287,7 @@ my @products = ( name => 'General', description => 'This is the component for issues specific to bugzilla.mozilla.org ' . 'that do not belong in other components.', - initialowner => 'nobody@mozilla.org', + initialowner => Bugzilla->params->{'nobody_user'}, initialqaowner => '', initial_cc => [], watch_user => 'general@bugzilla.bugs' diff --git a/scripts/move_os.pl b/scripts/move_os.pl index 546b47c7e..963188261 100755 --- a/scripts/move_os.pl +++ b/scripts/move_os.pl @@ -40,7 +40,7 @@ my $dbh = Bugzilla->dbh; my $timestamp = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)'); my $bug_ids = $dbh->selectcol_arrayref(q{SELECT bug_id FROM bugs WHERE bugs.op_sys = ?}, undef, $from_os); my $field = Bugzilla::Field->check({ name => 'op_sys', cache => 1 }); -my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org', cache => 1 }); +my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'}, cache => 1 }); my $bug_count = @$bug_ids; if ($bug_count == 0) { diff --git a/scripts/movebugs.pl b/scripts/movebugs.pl index 2c643cdfb..55a43d943 100755 --- a/scripts/movebugs.pl +++ b/scripts/movebugs.pl @@ -73,10 +73,12 @@ my $component_field_id = $dbh->selectrow_array( $component_field_id or die "Can't find field ID for 'component' field\n"; +my $nobody = Bugzilla->params->{'nobody_user'}; my $user_id = $dbh->selectrow_array( - "SELECT userid FROM profiles WHERE login_name='nobody\@mozilla.org'"); + "SELECT userid FROM profiles WHERE login_name=?", + undef, $nobody); $user_id - or die "Can't find user ID for 'nobody\@mozilla.org'\n"; + or die "Can't find user ID for '$nobody'\n"; $dbh->bz_start_transaction(); diff --git a/scripts/nagios_blocker_checker.pl b/scripts/nagios_blocker_checker.pl index a02a1602a..01a7b7348 100755 --- a/scripts/nagios_blocker_checker.pl +++ b/scripts/nagios_blocker_checker.pl @@ -28,7 +28,7 @@ my $config = { assignee => '', product => '', component => '', - unassigned => 'nobody@mozilla.org', + unassigned => Bugzilla->params->{'nobody_user'}, # severities severity => 'major,critical,blocker', # time in hours to wait before paging/warning diff --git a/scripts/remove_idle_group_members.pl b/scripts/remove_idle_group_members.pl index 74e8658ff..e4ef88bc1 100755 --- a/scripts/remove_idle_group_members.pl +++ b/scripts/remove_idle_group_members.pl @@ -78,7 +78,7 @@ foreach my $group_id (keys %remove_data) { $dbh->bz_commit_transaction(); # nobody@mozilla.org cannot recieve email - next if $group->owner->login eq 'nobody@mozilla.org'; + next if $group->owner->login eq Bugzilla->params->{'nobody_user'}; _send_email($group, \@users_removed); } diff --git a/scripts/reset_default_user.pl b/scripts/reset_default_user.pl index d0d2534f2..942afda17 100755 --- a/scripts/reset_default_user.pl +++ b/scripts/reset_default_user.pl @@ -52,7 +52,7 @@ if (!$product || $help } # We will need these for entering into bugs_activity -my $who = Bugzilla::User->new({ name => 'nobody@mozilla.org' }); +my $who = Bugzilla::User->new({ name => Bugzilla->params->{'nobody_user'} }); my $field = Bugzilla::Field->new({ name => $field_name }); trick_taint($product); diff --git a/scripts/rewrite2mojo.pl b/scripts/rewrite2mojo.pl new file mode 100755 index 000000000..bae6d514b --- /dev/null +++ b/scripts/rewrite2mojo.pl @@ -0,0 +1,70 @@ +#!/usr/bin/perl +# 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. + +use 5.10.1; +use strict; +use warnings; +use Mojo::Parameters; +use Data::Dumper; + +while (<>) { + my ($cmd, @args) = split /\s+/, $_; + next unless $cmd; + if (lc($cmd) eq "\LRewriteRule") { + my ($regex, $target, $flags) = @args; + $flags //= ''; + next if $flags =~ /E=HTTP/; + next if $target eq '-'; + my $action = 'rewrite_query'; + if ($flags =~ /R/) { + next; + } + my ($script, $query) = $target =~ /^([^?]+)(?:\?(.+))?$/; + my $name = _file_to_method($script); + $regex =~ s/^\^//; + $regex =~ s/\$$//; + my $regex_name = _regex_to_name($regex); + my $param_hash = Mojo::Parameters->new($query)->to_hash; + my $param_str = Data::Dumper->new([$param_hash])->Terse(1)->Indent(0)->Dump; + say "\$r->any('/:$regex_name' => [$regex_name => qr{$regex}])->to("; + say " 'CGI#$name' => $param_str"; + say ");"; + + } + # elsif (lc($cmd) eq "\LRedirect") { + # my ($type, $path, $url) = @args; + # if ($type eq 'permanent') { + # say "if (\$path =~ m{^\Q$path\E}s) {"; + # say " redirect(\$c, q{$url});"; + # say " return;"; + # say "}"; + # } + # else { + # warn "I don't understand Redirect $type\n"; + # } + # } +} + +sub _file_to_method { + my ($name) = @_; + $name =~ s/\./_/s; + $name =~ s/\W+/_/gs; + return $name; +} + +sub _regex_to_name { + my ($name) = @_; + $name =~ s/\./_/s; + $name =~ s/\W+/_/gs; + $name =~ s/_+/_/g; + $name =~ s/^_//s; + $name =~ s/_$//s; + return $name; +} + + diff --git a/t/bmo/comments.t b/t/bmo/comments.t index 4b0bb8177..00002040c 100644 --- a/t/bmo/comments.t +++ b/t/bmo/comments.t @@ -35,7 +35,7 @@ my $bug_1 = Bugzilla::Bug->create( keywords => [], cc => [], comment => 'This is a brand new bug', - assigned_to => 'nobody@mozilla.org', + assigned_to => Bugzilla->params->{'nobody_user'}, } ); ok($bug_1->id, "got a new bug"); @@ -55,7 +55,7 @@ my $bug_2 = Bugzilla::Bug->create( keywords => [], cc => [], comment => "This is related to ${urlbase}show_bug.cgi?id=$bug_1_id", - assigned_to => 'nobody@mozilla.org', + assigned_to => Bugzilla->params->{'nobody_user'}, } ); diff --git a/t/docker.t b/t/docker.t index 3c8cd055b..c1f85088c 100644 --- a/t/docker.t +++ b/t/docker.t @@ -28,7 +28,7 @@ while (my $line = readline $dockerfile_fh) { close $dockerfile_fh; my ($image, $version) = split(/:/ms, $base, 2); -is($image, 'mozillabteam/bmo-slim', "base image is mozillabteam/bmo-slim"); +is($image, 'bugzilla/harmony-slim', "base image is bugzilla/harmony-slim"); like($version, qr/\d{4}\d{2}\d{2}\.\d+/ms, "version is YYYYMMDD.x"); my $regex = qr{ @@ -49,4 +49,4 @@ while (my $line = readline $ci_config_fh) { } close $ci_config_fh; -done_testing;
\ No newline at end of file +done_testing; diff --git a/template/en/default/account/prefs/account.html.tmpl b/template/en/default/account/prefs/account.html.tmpl index 1e7bc25db..61ce80011 100644 --- a/template/en/default/account/prefs/account.html.tmpl +++ b/template/en/default/account/prefs/account.html.tmpl @@ -138,7 +138,7 @@ <td></td> <td> <p> - Your contributions on bugzilla.mozilla.org will still be visible; + Your contributions on [% terms.Bugzilla %] will still be visible; however, your email address and name will be removed in most locations. We are not able to remove your details that are part of comment text. </p> diff --git a/template/en/default/attachment/create.html.tmpl b/template/en/default/attachment/create.html.tmpl index 5e996041c..95336ed8e 100644 --- a/template/en/default/attachment/create.html.tmpl +++ b/template/en/default/attachment/create.html.tmpl @@ -74,7 +74,7 @@ <td> <em>If you want to assign this [% terms.bug %] to yourself, check the box below.</em><br> - [% IF bug.assigned_to.login == "nobody@mozilla.org" || bug.assigned_to.login.search('.bugs$') %] + [% IF bug.assigned_to.login == Param('nobody_user') || bug.assigned_to.login.search('.bugs$') %] [% take_if_patch = 1 %] [% END %] <input type="checkbox" id="takebug" name="takebug" value="1" [% IF take_if_patch %] data-take-if-patch="1" [% END %]> diff --git a/template/en/default/bug/new_bug.html.tmpl b/template/en/default/bug/new_bug.html.tmpl index b642be3c7..80a603944 100644 --- a/template/en/default/bug/new_bug.html.tmpl +++ b/template/en/default/bug/new_bug.html.tmpl @@ -27,10 +27,10 @@ <h2>Create New [% terms.Bug %]</h2> <p> Before reporting a [% terms.bug %], make sure you've read our - <a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines"> + <a href="[% terms.BugWritingGuidelinesURL %]"> [% terms.bug %] writing guidelines</a> and double checked that your [% terms.bug %] hasn't already - been reported. Consult our list of <a href="https://bugzilla.mozilla.org/duplicates.cgi"> - most frequently reported [% terms.bugs %]</a> and <a href="https://bugzilla.mozilla.org/query.cgi"> + been reported. Consult our list of <a href="duplicates.cgi"> + most frequently reported [% terms.bugs %]</a> and <a href="query.cgi"> search through descriptions</a> of previously reported [% terms.bugs %]. </p> </div> diff --git a/template/en/default/global/variables.none.tmpl b/template/en/default/global/variables.none.tmpl index 5ebf695c0..c57dac890 100644 --- a/template/en/default/global/variables.none.tmpl +++ b/template/en/default/global/variables.none.tmpl @@ -37,7 +37,9 @@ "bugs" => "bugs", "Bugs" => "Bugs", "zeroSearchResults" => "Zarro Boogs found", - "Bugzilla" => "Bugzilla" + "Bugzilla" => "Bugzilla", + + "BugWritingGuidelinesURL" => "https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines", } %] diff --git a/template/en/default/index.html.tmpl b/template/en/default/index.html.tmpl index d6a4f2105..6dbdabc0c 100644 --- a/template/en/default/index.html.tmpl +++ b/template/en/default/index.html.tmpl @@ -105,7 +105,7 @@ <a href="page.cgi?id=etiquette.html">[%- terms.Bugzilla %] Etiquette</a> </li> <li> - | <a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines">[%- terms.Bug %] Writing Guidelines</a> + | <a href="[% terms.BugWritingGuidelinesURL %]">[%- terms.Bug %] Writing Guidelines</a> </li> [% Hook.process('additional_links') %] </ul> diff --git a/template/en/default/list/edit-multiple.html.tmpl b/template/en/default/list/edit-multiple.html.tmpl index ada635b09..ae1dade52 100644 --- a/template/en/default/list/edit-multiple.html.tmpl +++ b/template/en/default/list/edit-multiple.html.tmpl @@ -437,7 +437,6 @@ [% FOREACH r = resolutions %] [% NEXT IF !r %] [% NEXT IF r == "DUPLICATE" || r == "MOVED" %] - [% NEXT IF r == "EXPIRED" AND user.login != "gerv@mozilla.org" %] <option value="[% r FILTER html %]">[% display_value("resolution", r) FILTER html %]</option> [% END %] </select> diff --git a/template/en/default/list/table.html.tmpl b/template/en/default/list/table.html.tmpl index 2453c3774..66ce442b9 100644 --- a/template/en/default/list/table.html.tmpl +++ b/template/en/default/list/table.html.tmpl @@ -90,7 +90,9 @@ <th class="sorttable_nosort"> </th> [% END %] <th colspan="[% splitheader ? 2 : 1 %]" class="first-child - sorted_[% lsearch(order_columns, 'bug_id') FILTER html %]"> + [% order_columns.defined + ? 'sorted_' _ lsearch(order_columns, 'bug_id') + : '' FILTER html %]"> <a href="buglist.cgi? [% urlquerypart FILTER html %]&order= [% PROCESS new_order id='bug_id' %] @@ -136,7 +138,9 @@ [% BLOCK columnheader %] <th colspan="[% splitheader ? 2 : 1 %]" class="sortable_column_[% key FILTER html %] - sorted_[% lsearch(order_columns, id) FILTER html %]"> + [% order_columns.defined + ? 'sorted_' _ lsearch(order_columns, id) + : '' FILTER html %]"> <a href="buglist.cgi?[% urlquerypart FILTER html %]&order= [% PROCESS new_order %] [%-#%]&query_based_on= diff --git a/template/en/default/search/search-google.html.tmpl b/template/en/default/search/search-google.html.tmpl index 7fdc1daaa..1b07320ce 100644 --- a/template/en/default/search/search-google.html.tmpl +++ b/template/en/default/search/search-google.html.tmpl @@ -32,7 +32,7 @@ <p> <form method="get" action="https://www.google.com/search" data-no-csrf> -<input type="hidden" name="sitesearch" value="bugzilla.mozilla.org"> +<input type="hidden" name="sitesearch" value="[% urlbase.match('^([^:]*://)?(.*?)/?$').1 %]"> <nobr> <input type="text" name="q" size="60" maxlength="255" value=""> <input type="submit" value="Search"> diff --git a/template/en/default/search/search-instant.html.tmpl b/template/en/default/search/search-instant.html.tmpl index e7d87084f..95d40a5eb 100644 --- a/template/en/default/search/search-instant.html.tmpl +++ b/template/en/default/search/search-instant.html.tmpl @@ -11,8 +11,7 @@ [% PROCESS global/header.html.tmpl title = "Instant Search" generate_api_token = 1 - javascript_urls = [ 'extensions/GuidedBugEntry/web/js/products.js', - 'js/instant-search.js', ] + javascript_urls = javascript_urls %] [% UNLESS default.exists('product') && default.product.size %] @@ -30,8 +30,7 @@ use lib qw(. lib local/lib/perl5); use Bugzilla; use Bugzilla::Error; -my $is_enabled = grep { $_->NAME eq 'Voting' } @{ Bugzilla->extensions }; -$is_enabled || ThrowCodeError('extension_disabled', { name => 'Voting' }); +Bugzilla->has_extension('Voting') || ThrowCodeError('extension_disabled', { name => 'Voting' }); my $cgi = Bugzilla->cgi; my $action = $cgi->param('action') || 'show_user'; |