summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Bugzilla/Quantum.pm199
-rw-r--r--Bugzilla/Quantum/CGI.pm245
-rw-r--r--Bugzilla/Quantum/Home.pm18
-rw-r--r--Bugzilla/Quantum/Plugin/BlockIP.pm38
-rw-r--r--Bugzilla/Quantum/Plugin/Glue.pm234
-rw-r--r--Bugzilla/Quantum/Plugin/Helpers.pm82
-rw-r--r--Bugzilla/Quantum/Plugin/Hostage.pm117
-rw-r--r--Bugzilla/Quantum/SES.pm367
-rw-r--r--Bugzilla/Quantum/Static.pm16
-rw-r--r--Bugzilla/Quantum/Stdout.pm50
10 files changed, 687 insertions, 679 deletions
diff --git a/Bugzilla/Quantum.pm b/Bugzilla/Quantum.pm
index 014663bd0..4fddb8da9 100644
--- a/Bugzilla/Quantum.pm
+++ b/Bugzilla/Quantum.pm
@@ -34,110 +34,113 @@ use Bugzilla::WebService::Server::REST;
has 'static' => sub { Bugzilla::Quantum::Static->new };
sub startup {
- my ($self) = @_;
-
- DEBUG('Starting up');
- $self->plugin('Bugzilla::Quantum::Plugin::Glue');
- $self->plugin('Bugzilla::Quantum::Plugin::Hostage') unless $ENV{BUGZILLA_DISABLE_HOSTAGE};
- $self->plugin('Bugzilla::Quantum::Plugin::BlockIP');
- $self->plugin('Bugzilla::Quantum::Plugin::Helpers');
-
- # hypnotoad is weird and doesn't look for MOJO_LISTEN itself.
- $self->config(
- hypnotoad => {
- proxy => $ENV{MOJO_REVERSE_PROXY} // 1,
- heartbeat_interval => $ENV{MOJO_HEARTBEAT_INTERVAL} // 10,
- heartbeat_timeout => $ENV{MOJO_HEARTBEAT_TIMEOUT} // 120,
- inactivity_timeout => $ENV{MOJO_INACTIVITY_TIMEOUT} // 120,
- workers => $ENV{MOJO_WORKERS} // 15,
- clients => $ENV{MOJO_CLIENTS} // 10,
- spare => $ENV{MOJO_SPARE} // 5,
- listen => [ $ENV{MOJO_LISTEN} // 'http://*:3000' ],
- },
+ my ($self) = @_;
+
+ DEBUG('Starting up');
+ $self->plugin('Bugzilla::Quantum::Plugin::Glue');
+ $self->plugin('Bugzilla::Quantum::Plugin::Hostage')
+ unless $ENV{BUGZILLA_DISABLE_HOSTAGE};
+ $self->plugin('Bugzilla::Quantum::Plugin::BlockIP');
+ $self->plugin('Bugzilla::Quantum::Plugin::Helpers');
+
+ # hypnotoad is weird and doesn't look for MOJO_LISTEN itself.
+ $self->config(
+ hypnotoad => {
+ proxy => $ENV{MOJO_REVERSE_PROXY} // 1,
+ heartbeat_interval => $ENV{MOJO_HEARTBEAT_INTERVAL} // 10,
+ heartbeat_timeout => $ENV{MOJO_HEARTBEAT_TIMEOUT} // 120,
+ inactivity_timeout => $ENV{MOJO_INACTIVITY_TIMEOUT} // 120,
+ workers => $ENV{MOJO_WORKERS} // 15,
+ clients => $ENV{MOJO_CLIENTS} // 10,
+ spare => $ENV{MOJO_SPARE} // 5,
+ listen => [$ENV{MOJO_LISTEN} // 'http://*:3000'],
+ },
+ );
+
+ # Make sure each httpd child receives a different random seed (bug 476622).
+ # Bugzilla::RNG has one srand that needs to be called for
+ # every process, and Perl has another. (Various Perl modules still use
+ # the built-in rand(), even though we never use it in Bugzilla itself,
+ # so we need to srand() both of them.)
+ # Also, ping the dbh to force a reconnection.
+ Mojo::IOLoop->next_tick(sub {
+ Bugzilla::RNG::srand();
+ srand();
+ eval { Bugzilla->dbh->ping };
+ });
+
+ Bugzilla::Extension->load_all();
+ if ($self->mode ne 'development') {
+ Bugzilla->preload_features();
+ DEBUG('preloading templates');
+ Bugzilla->preload_templates();
+ DEBUG('done preloading templates');
+ require_module($_) for find_modules('Bugzilla::User::Setting');
+
+ $self->hook(
+ after_static => sub {
+ my ($c) = @_;
+ $c->res->headers->cache_control('public, max-age=31536000');
+ }
);
+ }
+ Bugzilla::WebService::Server::REST->preload;
- # Make sure each httpd child receives a different random seed (bug 476622).
- # Bugzilla::RNG has one srand that needs to be called for
- # every process, and Perl has another. (Various Perl modules still use
- # the built-in rand(), even though we never use it in Bugzilla itself,
- # so we need to srand() both of them.)
- # Also, ping the dbh to force a reconnection.
- Mojo::IOLoop->next_tick(
- sub {
- Bugzilla::RNG::srand();
- srand();
- eval { Bugzilla->dbh->ping };
- }
- );
-
- Bugzilla::Extension->load_all();
- if ( $self->mode ne 'development' ) {
- Bugzilla->preload_features();
- DEBUG('preloading templates');
- Bugzilla->preload_templates();
- DEBUG('done preloading templates');
- require_module($_) for find_modules('Bugzilla::User::Setting');
-
- $self->hook(
- after_static => sub {
- my ($c) = @_;
- $c->res->headers->cache_control('public, max-age=31536000');
- }
- );
- }
- Bugzilla::WebService::Server::REST->preload;
-
- $self->setup_routes;
+ $self->setup_routes;
- Bugzilla::Hook::process( 'app_startup', { app => $self } );
+ Bugzilla::Hook::process('app_startup', {app => $self});
}
sub setup_routes {
- my ($self) = @_;
-
- my $r = $self->routes;
- Bugzilla::Quantum::CGI->load_all($r);
- Bugzilla::Quantum::CGI->load_one( 'bzapi_cgi', 'extensions/BzAPI/bin/rest.cgi' );
-
- $r->get('/home')->to('Home#index');
- $r->any('/')->to('CGI#index_cgi');
- $r->any('/bug/<id:num>')->to('CGI#show_bug_cgi');
- $r->any('/<id:num>')->to('CGI#show_bug_cgi');
- $r->get('/testagent.cgi' => sub {
- my $c = shift;
- $c->render(text => "OK Mojolicious");
- });
-
- $r->any('/rest')->to('CGI#rest_cgi');
- $r->any('/rest.cgi/*PATH_INFO')->to( 'CGI#rest_cgi' => { PATH_INFO => '' } );
- $r->any('/rest/*PATH_INFO')->to( 'CGI#rest_cgi' => { PATH_INFO => '' } );
- $r->any('/extensions/BzAPI/bin/rest.cgi/*PATH_INFO')->to('CGI#bzapi_cgi');
- $r->any('/latest/*PATH_INFO')->to('CGI#bzapi_cgi');
- $r->any('/bzapi/*PATH_INFO')->to('CGI#bzapi_cgi');
-
- $r->static_file('/__lbheartbeat__');
- $r->static_file('/__version__' => { file => 'version.json', content_type => 'application/json' });
- $r->static_file('/version.json', { content_type => 'application/json' });
-
- $r->page('/review', 'splinter.html');
- $r->page('/user_profile', 'user_profile.html');
- $r->page('/userprofile', 'user_profile.html');
- $r->page('/request_defer', 'request_defer.html');
-
- $r->get('/__heartbeat__')->to('CGI#heartbeat_cgi');
- $r->get('/robots.txt')->to('CGI#robots_cgi');
- $r->any('/login')->to( 'CGI#index_cgi' => { 'GoAheadAndLogIn' => '1' } );
- $r->any( '/:new_bug' => [ new_bug => qr{new[-_]bug} ] )->to('CGI#new_bug_cgi');
-
- my $ses_auth = $r->under(
- '/ses' => sub {
- my ($c) = @_;
- my $lc = Bugzilla->localconfig;
-
- return $c->basic_auth( 'SES', $lc->{ses_username}, $lc->{ses_password} );
- }
- );
- $ses_auth->any('/index.cgi')->to('SES#main');
+ my ($self) = @_;
+
+ my $r = $self->routes;
+ Bugzilla::Quantum::CGI->load_all($r);
+ Bugzilla::Quantum::CGI->load_one('bzapi_cgi',
+ 'extensions/BzAPI/bin/rest.cgi');
+
+ $r->get('/home')->to('Home#index');
+ $r->any('/')->to('CGI#index_cgi');
+ $r->any('/bug/<id:num>')->to('CGI#show_bug_cgi');
+ $r->any('/<id:num>')->to('CGI#show_bug_cgi');
+ $r->get(
+ '/testagent.cgi' => sub {
+ my $c = shift;
+ $c->render(text => "OK Mojolicious");
+ }
+ );
+
+ $r->any('/rest')->to('CGI#rest_cgi');
+ $r->any('/rest.cgi/*PATH_INFO')->to('CGI#rest_cgi' => {PATH_INFO => ''});
+ $r->any('/rest/*PATH_INFO')->to('CGI#rest_cgi' => {PATH_INFO => ''});
+ $r->any('/extensions/BzAPI/bin/rest.cgi/*PATH_INFO')->to('CGI#bzapi_cgi');
+ $r->any('/latest/*PATH_INFO')->to('CGI#bzapi_cgi');
+ $r->any('/bzapi/*PATH_INFO')->to('CGI#bzapi_cgi');
+
+ $r->static_file('/__lbheartbeat__');
+ $r->static_file('/__version__' =>
+ {file => 'version.json', content_type => 'application/json'});
+ $r->static_file('/version.json', {content_type => 'application/json'});
+
+ $r->page('/review', 'splinter.html');
+ $r->page('/user_profile', 'user_profile.html');
+ $r->page('/userprofile', 'user_profile.html');
+ $r->page('/request_defer', 'request_defer.html');
+
+ $r->get('/__heartbeat__')->to('CGI#heartbeat_cgi');
+ $r->get('/robots.txt')->to('CGI#robots_cgi');
+ $r->any('/login')->to('CGI#index_cgi' => {'GoAheadAndLogIn' => '1'});
+ $r->any('/:new_bug' => [new_bug => qr{new[-_]bug}])->to('CGI#new_bug_cgi');
+
+ my $ses_auth = $r->under(
+ '/ses' => sub {
+ my ($c) = @_;
+ my $lc = Bugzilla->localconfig;
+
+ return $c->basic_auth('SES', $lc->{ses_username}, $lc->{ses_password});
+ }
+ );
+ $ses_auth->any('/index.cgi')->to('SES#main');
}
1;
diff --git a/Bugzilla/Quantum/CGI.pm b/Bugzilla/Quantum/CGI.pm
index 317c189cc..beb849687 100644
--- a/Bugzilla/Quantum/CGI.pm
+++ b/Bugzilla/Quantum/CGI.pm
@@ -25,146 +25,151 @@ our $C;
my %SEEN;
sub load_all {
- my ( $class, $r ) = @_;
+ my ($class, $r) = @_;
- foreach my $file ( glob '*.cgi' ) {
- my $name = _file_to_method($file);
- $class->load_one( $name, $file );
- $r->any("/$file")->to("CGI#$name");
- }
+ foreach my $file (glob '*.cgi') {
+ my $name = _file_to_method($file);
+ $class->load_one($name, $file);
+ $r->any("/$file")->to("CGI#$name");
+ }
}
sub load_one {
- my ( $class, $name, $file ) = @_;
- my $package = __PACKAGE__ . "::$name", my $inner_name = "_$name";
- my $content = read_text( catfile( bz_locations->{cgi_path}, $file ) );
- $content = "package $package; $content";
- untaint($content);
- my %options = (
- package => $package,
- file => $file,
- line => 1,
- no_defer => 1,
- );
- die "Tried to load $file more than once" if $SEEN{$file}++;
- my $inner = quote_sub $inner_name, $content, {}, \%options;
- my $wrapper = sub {
- my ($c) = @_;
- my $stdin = $c->_STDIN;
- local $C = $c;
- local %ENV = $c->_ENV($file);
- local $CGI::Compile::USE_REAL_EXIT = 0;
- local $PROGRAM_NAME = $file;
- local *STDIN; ## no critic (local)
- open STDIN, '<', $stdin->path or die "STDIN @{[$stdin->path]}: $!" if -s $stdin->path;
- tie *STDOUT, 'Bugzilla::Quantum::Stdout', controller => $c; ## no critic (tie)
-
- # the finally block calls cleanup.
- $c->stash->{cleanup_guard}->dismiss;
- Bugzilla->usage_mode(USAGE_MODE_BROWSER);
- try {
- Bugzilla->init_page();
- $inner->();
- }
- catch {
- die $_ unless _is_exit($_);
- }
- finally {
- my $error = shift;
- untie *STDOUT;
- $c->finish if !$error || _is_exit($error);
- Bugzilla->cleanup;
- CGI::initialize_globals();
- };
+ my ($class, $name, $file) = @_;
+ my $package = __PACKAGE__ . "::$name", my $inner_name = "_$name";
+ my $content = read_text(catfile(bz_locations->{cgi_path}, $file));
+ $content = "package $package; $content";
+ untaint($content);
+ my %options = (package => $package, file => $file, line => 1, no_defer => 1,);
+ die "Tried to load $file more than once" if $SEEN{$file}++;
+ my $inner = quote_sub $inner_name, $content, {}, \%options;
+ my $wrapper = sub {
+ my ($c) = @_;
+ my $stdin = $c->_STDIN;
+ local $C = $c;
+ local %ENV = $c->_ENV($file);
+ local $CGI::Compile::USE_REAL_EXIT = 0;
+ local $PROGRAM_NAME = $file;
+ local *STDIN; ## no critic (local)
+ open STDIN, '<', $stdin->path
+ or die "STDIN @{[$stdin->path]}: $!"
+ if -s $stdin->path;
+ tie *STDOUT, 'Bugzilla::Quantum::Stdout',
+ controller => $c; ## no critic (tie)
+
+ # the finally block calls cleanup.
+ $c->stash->{cleanup_guard}->dismiss;
+ Bugzilla->usage_mode(USAGE_MODE_BROWSER);
+ try {
+ Bugzilla->init_page();
+ $inner->();
+ }
+ catch {
+ die $_ unless _is_exit($_);
+ }
+ finally {
+ my $error = shift;
+ untie *STDOUT;
+ $c->finish if !$error || _is_exit($error);
+ Bugzilla->cleanup;
+ CGI::initialize_globals();
};
+ };
- no strict 'refs'; ## no critic (strict)
- *{$name} = subname( $name, $wrapper );
- return 1;
+ no strict 'refs'; ## no critic (strict)
+ *{$name} = subname($name, $wrapper);
+ return 1;
}
sub _ENV {
- my ( $c, $script_name ) = @_;
- my $tx = $c->tx;
- my $req = $tx->req;
- my $headers = $req->headers;
- my $content_length = $req->content->is_multipart ? $req->body_size : $headers->content_length;
- my %env_headers = ( HTTP_COOKIE => '', HTTP_REFERER => '' );
-
- for my $name ( @{ $headers->names } ) {
- my $key = uc "http_$name";
- $key =~ s/\W/_/g;
- $env_headers{$key} = $headers->header($name);
- }
-
- my $remote_user;
- if ( my $userinfo = $req->url->to_abs->userinfo ) {
- $remote_user = $userinfo =~ /([^:]+)/ ? $1 : '';
- }
- elsif ( my $authenticate = $headers->authorization ) {
- $remote_user = $authenticate =~ /Basic\s+(.*)/ ? b64_decode $1 : '';
- $remote_user = $remote_user =~ /([^:]+)/ ? $1 : '';
+ my ($c, $script_name) = @_;
+ my $tx = $c->tx;
+ my $req = $tx->req;
+ my $headers = $req->headers;
+ my $content_length
+ = $req->content->is_multipart ? $req->body_size : $headers->content_length;
+ my %env_headers = (HTTP_COOKIE => '', HTTP_REFERER => '');
+
+ for my $name (@{$headers->names}) {
+ my $key = uc "http_$name";
+ $key =~ s/\W/_/g;
+ $env_headers{$key} = $headers->header($name);
+ }
+
+ my $remote_user;
+ if (my $userinfo = $req->url->to_abs->userinfo) {
+ $remote_user = $userinfo =~ /([^:]+)/ ? $1 : '';
+ }
+ elsif (my $authenticate = $headers->authorization) {
+ $remote_user = $authenticate =~ /Basic\s+(.*)/ ? b64_decode $1 : '';
+ $remote_user = $remote_user =~ /([^:]+)/ ? $1 : '';
+ }
+ my $path_info = $c->stash->{'mojo.captures'}{'PATH_INFO'};
+ my %captures = %{$c->stash->{'mojo.captures'} // {}};
+ foreach my $key (keys %captures) {
+ if ( $key eq 'controller'
+ || $key eq 'action'
+ || $key eq 'PATH_INFO'
+ || $key =~ /^REWRITE_/)
+ {
+ delete $captures{$key};
}
- my $path_info = $c->stash->{'mojo.captures'}{'PATH_INFO'};
- my %captures = %{ $c->stash->{'mojo.captures'} // {} };
- foreach my $key ( keys %captures ) {
- if ( $key eq 'controller' || $key eq 'action' || $key eq 'PATH_INFO' || $key =~ /^REWRITE_/ ) {
- delete $captures{$key};
- }
- }
- my $cgi_query = Mojo::Parameters->new(%captures);
- $cgi_query->append( $req->url->query );
- my $prefix = $c->stash->{bmo_prefix} ? '/bmo/' : '/';
-
- return (
- %ENV,
- CONTENT_LENGTH => $content_length || 0,
- CONTENT_TYPE => $headers->content_type || '',
- GATEWAY_INTERFACE => 'CGI/1.1',
- HTTPS => $req->is_secure ? 'on' : 'off',
- %env_headers,
- QUERY_STRING => $cgi_query->to_string,
- PATH_INFO => $path_info ? "/$path_info" : '',
- REMOTE_ADDR => $tx->original_remote_address,
- REMOTE_HOST => $tx->original_remote_address,
- REMOTE_PORT => $tx->remote_port,
- REMOTE_USER => $remote_user || '',
- REQUEST_METHOD => $req->method,
- SCRIPT_NAME => "$prefix$script_name",
- SERVER_NAME => hostname,
- SERVER_PORT => $tx->local_port,
- SERVER_PROTOCOL => $req->is_secure ? 'HTTPS' : 'HTTP', # TODO: Version is missing
- SERVER_SOFTWARE => __PACKAGE__,
- );
+ }
+ my $cgi_query = Mojo::Parameters->new(%captures);
+ $cgi_query->append($req->url->query);
+ my $prefix = $c->stash->{bmo_prefix} ? '/bmo/' : '/';
+
+ return (
+ %ENV,
+ CONTENT_LENGTH => $content_length || 0,
+ CONTENT_TYPE => $headers->content_type || '',
+ GATEWAY_INTERFACE => 'CGI/1.1',
+ HTTPS => $req->is_secure ? 'on' : 'off',
+ %env_headers,
+ QUERY_STRING => $cgi_query->to_string,
+ PATH_INFO => $path_info ? "/$path_info" : '',
+ REMOTE_ADDR => $tx->original_remote_address,
+ REMOTE_HOST => $tx->original_remote_address,
+ REMOTE_PORT => $tx->remote_port,
+ REMOTE_USER => $remote_user || '',
+ REQUEST_METHOD => $req->method,
+ SCRIPT_NAME => "$prefix$script_name",
+ SERVER_NAME => hostname,
+ SERVER_PORT => $tx->local_port,
+ SERVER_PROTOCOL => $req->is_secure
+ ? 'HTTPS'
+ : 'HTTP', # TODO: Version is missing
+ SERVER_SOFTWARE => __PACKAGE__,
+ );
}
sub _STDIN {
- my $c = shift;
- my $stdin;
-
- if ( $c->req->content->is_multipart ) {
- $stdin = Mojo::Asset::File->new;
- $stdin->add_chunk( $c->req->build_body );
- }
- else {
- $stdin = $c->req->content->asset;
- }
-
- return $stdin if $stdin->isa('Mojo::Asset::File');
- return Mojo::Asset::File->new->add_chunk( $stdin->slurp );
+ my $c = shift;
+ my $stdin;
+
+ if ($c->req->content->is_multipart) {
+ $stdin = Mojo::Asset::File->new;
+ $stdin->add_chunk($c->req->build_body);
+ }
+ else {
+ $stdin = $c->req->content->asset;
+ }
+
+ return $stdin if $stdin->isa('Mojo::Asset::File');
+ return Mojo::Asset::File->new->add_chunk($stdin->slurp);
}
sub _file_to_method {
- my ($name) = @_;
- $name =~ s/\./_/s;
- $name =~ s/\W+/_/gs;
- return $name;
+ my ($name) = @_;
+ $name =~ s/\./_/s;
+ $name =~ s/\W+/_/gs;
+ return $name;
}
sub _is_exit {
- my ($error) = @_;
- return ref $error eq 'ARRAY' && $error->[0] eq "EXIT\n";
+ my ($error) = @_;
+ return ref $error eq 'ARRAY' && $error->[0] eq "EXIT\n";
}
1;
diff --git a/Bugzilla/Quantum/Home.pm b/Bugzilla/Quantum/Home.pm
index b3f1ec1d1..48d5e47bd 100644
--- a/Bugzilla/Quantum/Home.pm
+++ b/Bugzilla/Quantum/Home.pm
@@ -13,14 +13,16 @@ use Try::Tiny;
use Bugzilla::Constants;
sub index {
- my ($c) = @_;
- $c->bugzilla->login(LOGIN_REQUIRED) or return;
- try {
- ThrowUserError('invalid_username', { login => 'batman' }) if $c->param('error');
- $c->render(handler => 'bugzilla', template => 'index');
- } catch {
- $c->bugzilla->error_page($_);
- };
+ my ($c) = @_;
+ $c->bugzilla->login(LOGIN_REQUIRED) or return;
+ try {
+ ThrowUserError('invalid_username', {login => 'batman'})
+ if $c->param('error');
+ $c->render(handler => 'bugzilla', template => 'index');
+ }
+ catch {
+ $c->bugzilla->error_page($_);
+ };
}
1;
diff --git a/Bugzilla/Quantum/Plugin/BlockIP.pm b/Bugzilla/Quantum/Plugin/BlockIP.pm
index 058ecbf64..974eebff9 100644
--- a/Bugzilla/Quantum/Plugin/BlockIP.pm
+++ b/Bugzilla/Quantum/Plugin/BlockIP.pm
@@ -9,35 +9,35 @@ use constant BLOCK_TIMEOUT => 60 * 60;
my $MEMCACHED = Bugzilla::Memcached->new()->{memcached};
sub register {
- my ( $self, $app, $conf ) = @_;
+ my ($self, $app, $conf) = @_;
- $app->hook( before_routes => \&_before_routes );
- $app->helper( block_ip => \&_block_ip );
- $app->helper( unblock_ip => \&_unblock_ip );
+ $app->hook(before_routes => \&_before_routes);
+ $app->helper(block_ip => \&_block_ip);
+ $app->helper(unblock_ip => \&_unblock_ip);
}
sub _block_ip {
- my ( $class, $ip ) = @_;
- $MEMCACHED->set( "block_ip:$ip" => 1, BLOCK_TIMEOUT ) if $MEMCACHED;
+ my ($class, $ip) = @_;
+ $MEMCACHED->set("block_ip:$ip" => 1, BLOCK_TIMEOUT) if $MEMCACHED;
}
sub _unblock_ip {
- my ( $class, $ip ) = @_;
- $MEMCACHED->delete("block_ip:$ip") if $MEMCACHED;
+ my ($class, $ip) = @_;
+ $MEMCACHED->delete("block_ip:$ip") if $MEMCACHED;
}
sub _before_routes {
- my ($c) = @_;
- return if $c->stash->{'mojo.static'};
-
- my $ip = $c->tx->remote_address;
- if ( $MEMCACHED && $MEMCACHED->get("block_ip:$ip") ) {
- $c->block_ip($ip);
- $c->res->code(429);
- $c->res->message('Too Many Requests');
- $c->res->body('Too Many Requests');
- $c->finish;
- }
+ my ($c) = @_;
+ return if $c->stash->{'mojo.static'};
+
+ my $ip = $c->tx->remote_address;
+ if ($MEMCACHED && $MEMCACHED->get("block_ip:$ip")) {
+ $c->block_ip($ip);
+ $c->res->code(429);
+ $c->res->message('Too Many Requests');
+ $c->res->body('Too Many Requests');
+ $c->finish;
+ }
}
1;
diff --git a/Bugzilla/Quantum/Plugin/Glue.pm b/Bugzilla/Quantum/Plugin/Glue.pm
index 8f4144589..f04b9c025 100644
--- a/Bugzilla/Quantum/Plugin/Glue.pm
+++ b/Bugzilla/Quantum/Plugin/Glue.pm
@@ -20,141 +20,145 @@ use Scalar::Util qw(blessed);
use Scope::Guard;
sub register {
- my ( $self, $app, $conf ) = @_;
-
- my %D;
- if ( $ENV{BUGZILLA_HTTPD_ARGS} ) {
- my $args = decode_json( $ENV{BUGZILLA_HTTPD_ARGS} );
- foreach my $arg (@$args) {
- if ( $arg =~ /^-D(\w+)$/ ) {
- $D{$1} = 1;
- }
- else {
- die "Unknown httpd arg: $arg";
- }
+ my ($self, $app, $conf) = @_;
+
+ my %D;
+ if ($ENV{BUGZILLA_HTTPD_ARGS}) {
+ my $args = decode_json($ENV{BUGZILLA_HTTPD_ARGS});
+ foreach my $arg (@$args) {
+ if ($arg =~ /^-D(\w+)$/) {
+ $D{$1} = 1;
+ }
+ else {
+ die "Unknown httpd arg: $arg";
+ }
+ }
+ }
+
+ $app->hook(
+ before_dispatch => sub {
+ my ($c) = @_;
+ if ($D{HTTPD_IN_SUBDIR}) {
+ my $path = $c->req->url->path;
+ if ($path =~ s{^/bmo}{}s) {
+ $c->stash->{bmo_prefix} = 1;
+ $c->req->url->path($path);
}
+ }
+ Log::Log4perl::MDC->put(request_id => $c->req->request_id);
+ $c->stash->{cleanup_guard} = Scope::Guard->new(\&Bugzilla::cleanup);
+ Bugzilla->usage_mode(USAGE_MODE_MOJO);
}
+ );
- $app->hook(
- before_dispatch => sub {
- my ($c) = @_;
- if ( $D{HTTPD_IN_SUBDIR} ) {
- my $path = $c->req->url->path;
- if ( $path =~ s{^/bmo}{}s ) {
- $c->stash->{bmo_prefix} = 1;
- $c->req->url->path($path);
- }
- }
- Log::Log4perl::MDC->put( request_id => $c->req->request_id );
- $c->stash->{cleanup_guard} = Scope::Guard->new( \&Bugzilla::cleanup );
- Bugzilla->usage_mode(USAGE_MODE_MOJO);
- }
- );
+ $app->secrets([Bugzilla->localconfig->{side_wide_secret}]);
- $app->secrets( [ Bugzilla->localconfig->{side_wide_secret} ] );
+ $app->renderer->add_handler(
+ 'bugzilla' => sub {
+ my ($renderer, $c, $output, $options) = @_;
- $app->renderer->add_handler(
- 'bugzilla' => sub {
- my ( $renderer, $c, $output, $options ) = @_;
+ my %params;
- my %params;
- # Helpers
- foreach my $method (grep { m/^\w+\z/ } keys %{$renderer->helpers}) {
- my $sub = $renderer->helpers->{$method};
- $params{$method} = sub { $c->$sub(@_) };
- }
- # Stash values
- $params{$_} = $c->stash->{$_} for grep { m/^\w+\z/ } keys %{$c->stash};
+ # Helpers
+ foreach my $method (grep {m/^\w+\z/} keys %{$renderer->helpers}) {
+ my $sub = $renderer->helpers->{$method};
+ $params{$method} = sub { $c->$sub(@_) };
+ }
- $params{self} = $params{c} = $c;
+ # Stash values
+ $params{$_} = $c->stash->{$_} for grep {m/^\w+\z/} keys %{$c->stash};
- my $name = sprintf '%s.%s.tmpl', $options->{template}, $options->{format};
- my $template = Bugzilla->template;
- $template->process( $name, \%params, $output )
- or die $template->error;
- }
- );
- $app->helper(
- 'bugzilla.login_redirect_if_required' => sub {
- my ( $c, $type ) = @_;
-
- if ( $type == LOGIN_REQUIRED ) {
- $c->redirect_to('/login');
- return undef;
- }
- else {
- return Bugzilla->user;
- }
- }
- );
- $app->helper(
- 'bugzilla.login' => sub {
- my ( $c, $type ) = @_;
- $type //= LOGIN_NORMAL;
+ $params{self} = $params{c} = $c;
- return Bugzilla->user if Bugzilla->user->id;
+ my $name = sprintf '%s.%s.tmpl', $options->{template}, $options->{format};
+ my $template = Bugzilla->template;
+ $template->process($name, \%params, $output) or die $template->error;
+ }
+ );
+ $app->helper(
+ 'bugzilla.login_redirect_if_required' => sub {
+ my ($c, $type) = @_;
+
+ if ($type == LOGIN_REQUIRED) {
+ $c->redirect_to('/login');
+ return undef;
+ }
+ else {
+ return Bugzilla->user;
+ }
+ }
+ );
+ $app->helper(
+ 'bugzilla.login' => sub {
+ my ($c, $type) = @_;
+ $type //= LOGIN_NORMAL;
- $type = LOGIN_REQUIRED if $c->param('GoAheadAndLogIn') || Bugzilla->params->{requirelogin};
+ return Bugzilla->user if Bugzilla->user->id;
- # Allow templates to know that we're in a page that always requires
- # login.
- if ( $type == LOGIN_REQUIRED ) {
- Bugzilla->request_cache->{page_requires_login} = 1;
- }
+ $type = LOGIN_REQUIRED
+ if $c->param('GoAheadAndLogIn') || Bugzilla->params->{requirelogin};
- my $login_cookie = $c->cookie("Bugzilla_logincookie");
- my $user_id = $c->cookie("Bugzilla_login");
- my $ip_addr = $c->tx->remote_address;
+ # Allow templates to know that we're in a page that always requires
+ # login.
+ if ($type == LOGIN_REQUIRED) {
+ Bugzilla->request_cache->{page_requires_login} = 1;
+ }
- return $c->bugzilla->login_redirect_if_required($type) unless ( $login_cookie && $user_id );
+ my $login_cookie = $c->cookie("Bugzilla_logincookie");
+ my $user_id = $c->cookie("Bugzilla_login");
+ my $ip_addr = $c->tx->remote_address;
- my $db_cookie = Bugzilla->dbh->selectrow_array(
- q{
+ return $c->bugzilla->login_redirect_if_required($type)
+ unless ($login_cookie && $user_id);
+
+ my $db_cookie = Bugzilla->dbh->selectrow_array(
+ q{
SELECT cookie
FROM logincookies
WHERE cookie = ?
AND userid = ?
AND (restrict_ipaddr = 0 OR ipaddr = ?)
- },
- undef,
- ( $login_cookie, $user_id, $ip_addr )
- );
-
- if ( defined $db_cookie && secure_compare( $login_cookie, $db_cookie ) ) {
- my $user = Bugzilla::User->check( { id => $user_id, cache => 1 } );
-
- # If we logged in successfully, then update the lastused
- # time on the login cookie
- with_writable_database {
- Bugzilla->dbh->do( q{ UPDATE logincookies SET lastused = NOW() WHERE cookie = ? },
- undef, $login_cookie );
- };
- Bugzilla->set_user($user);
- return $user;
- }
- else {
- return $c->bugzilla->login_redirect_if_required($type);
- }
- }
- );
- $app->helper(
- 'bugzilla.error_page' => sub {
- my ( $c, $error ) = @_;
- if ( blessed $error && $error->isa('Bugzilla::Error::Base') ) {
- $c->render(
- handler => 'bugzilla',
- template => $error->template,
- error => $error->message,
- %{ $error->vars }
- );
- }
- else {
- $c->reply->exception($error);
- }
- }
- );
+ }, undef, ($login_cookie, $user_id, $ip_addr)
+ );
+
+ if (defined $db_cookie && secure_compare($login_cookie, $db_cookie)) {
+ my $user = Bugzilla::User->check({id => $user_id, cache => 1});
+
+ # If we logged in successfully, then update the lastused
+ # time on the login cookie
+ with_writable_database {
+ Bugzilla->dbh->do(
+ q{ UPDATE logincookies SET lastused = NOW() WHERE cookie = ? },
+ undef, $login_cookie);
+ };
+ Bugzilla->set_user($user);
+ return $user;
+ }
+ else {
+ return $c->bugzilla->login_redirect_if_required($type);
+ }
+ }
+ );
+ $app->helper(
+ 'bugzilla.error_page' => sub {
+ my ($c, $error) = @_;
+ if (blessed $error && $error->isa('Bugzilla::Error::Base')) {
+ $c->render(
+ handler => 'bugzilla',
+ template => $error->template,
+ error => $error->message,
+ %{$error->vars}
+ );
+ }
+ else {
+ $c->reply->exception($error);
+ }
+ }
+ );
- $app->log( MojoX::Log::Log4perl::Tiny->new( logger => Log::Log4perl->get_logger( ref $app ) ) );
+ $app->log(MojoX::Log::Log4perl::Tiny->new(
+ logger => Log::Log4perl->get_logger(ref $app)
+ ));
}
1;
diff --git a/Bugzilla/Quantum/Plugin/Helpers.pm b/Bugzilla/Quantum/Plugin/Helpers.pm
index 0aedca338..72dd96cf9 100644
--- a/Bugzilla/Quantum/Plugin/Helpers.pm
+++ b/Bugzilla/Quantum/Plugin/Helpers.pm
@@ -12,53 +12,55 @@ use Bugzilla::Logging;
use Carp;
sub register {
- my ( $self, $app, $conf ) = @_;
+ my ($self, $app, $conf) = @_;
- $app->helper(
- basic_auth => sub {
- my ( $c, $realm, $auth_user, $auth_pass ) = @_;
- my $req = $c->req;
- my ( $user, $password ) = $req->url->to_abs->userinfo =~ /^([^:]+):(.*)/;
+ $app->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 ($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;
- }
+ 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;
- }
- );
- $app->routes->add_shortcut(
- static_file => sub {
- my ($r, $path, $option) = @_;
- my $file = $option->{file};
- my $content_type = $option->{content_type} // 'text/plain';
- unless ($file) {
- $file = $path;
- $file =~ s!^/!!;
- }
+ return 1;
+ }
+ );
+ $app->routes->add_shortcut(
+ static_file => sub {
+ my ($r, $path, $option) = @_;
+ my $file = $option->{file};
+ my $content_type = $option->{content_type} // 'text/plain';
+ unless ($file) {
+ $file = $path;
+ $file =~ s!^/!!;
+ }
- return $r->get($path => sub {
- my ($c) = @_;
- $c->res->headers->content_type($content_type);
- $c->reply->file( $c->app->home->child($file) );
- })
+ return $r->get(
+ $path => sub {
+ my ($c) = @_;
+ $c->res->headers->content_type($content_type);
+ $c->reply->file($c->app->home->child($file));
}
- );
- $app->routes->add_shortcut(
- page => sub {
- my ($r, $path, $id) = @_;
+ );
+ }
+ );
+ $app->routes->add_shortcut(
+ page => sub {
+ my ($r, $path, $id) = @_;
- return $r->any($path)->to('CGI#page_cgi' => { id => $id });
- }
- );
+ return $r->any($path)->to('CGI#page_cgi' => {id => $id});
+ }
+ );
}
1;
diff --git a/Bugzilla/Quantum/Plugin/Hostage.pm b/Bugzilla/Quantum/Plugin/Hostage.pm
index cbde7b5ee..63fad2be2 100644
--- a/Bugzilla/Quantum/Plugin/Hostage.pm
+++ b/Bugzilla/Quantum/Plugin/Hostage.pm
@@ -4,83 +4,82 @@ 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;
- }
- 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;
- }
- }
- 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;
+ 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;
}
else {
- DEBUG("redirecting to $urlbase because $hostname doesn't make sense");
- $c->redirect_to($urlbase);
- return;
+ 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;
}
+ }
+ 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 03916075d..750da4e77 100644
--- a/Bugzilla/Quantum/SES.pm
+++ b/Bugzilla/Quantum/SES.pm
@@ -1,4 +1,5 @@
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/.
@@ -22,233 +23,231 @@ use Types::Standard qw( :all );
use Type::Utils;
use Type::Params qw( compile );
-my $Invocant = class_type { class => __PACKAGE__ };
+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);
+ 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');
}
+ }
- 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($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' );
+ 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,
+my $Notification = Dict [
+ eventType => Optional [$NotificationType],
+ notificationType => Optional [$NotificationType],
+ slurpy Any,
];
sub _handle_notification {
- state $check = compile($Invocant, $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->(@_);
+
+ 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;
}
-my $BouncedRecipients = ArrayRef[
- Dict[
- emailAddress => Str,
- action => Str,
- diagnosticCode => Str,
- slurpy Any,
- ],
+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,
- ],
+ 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");
- }
+ 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,
- ],
+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($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);
- }
+ 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($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;
+ 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/Quantum/Static.pm b/Bugzilla/Quantum/Static.pm
index 4543d1b84..6ac803e96 100644
--- a/Bugzilla/Quantum/Static.pm
+++ b/Bugzilla/Quantum/Static.pm
@@ -16,15 +16,15 @@ my $LEGACY_RE = qr{
}xs;
sub file {
- my ( $self, $rel ) = @_;
+ my ($self, $rel) = @_;
- if ( my ($legacy_rel) = $rel =~ $LEGACY_RE ) {
- local $self->{paths} = [ bz_locations->{cgi_path} ];
- return $self->SUPER::file($legacy_rel);
- }
- else {
- return $self->SUPER::file($rel);
- }
+ if (my ($legacy_rel) = $rel =~ $LEGACY_RE) {
+ local $self->{paths} = [bz_locations->{cgi_path}];
+ return $self->SUPER::file($legacy_rel);
+ }
+ else {
+ return $self->SUPER::file($rel);
+ }
}
1;
diff --git a/Bugzilla/Quantum/Stdout.pm b/Bugzilla/Quantum/Stdout.pm
index 9cf19992c..10be0b664 100644
--- a/Bugzilla/Quantum/Stdout.pm
+++ b/Bugzilla/Quantum/Stdout.pm
@@ -13,48 +13,42 @@ use Bugzilla::Logging;
use Encode;
use English qw(-no_match_vars);
-has 'controller' => (
- is => 'ro',
- required => 1,
-);
+has 'controller' => (is => 'ro', required => 1,);
-has '_encoding' => (
- is => 'rw',
- default => '',
-);
+has '_encoding' => (is => 'rw', default => '',);
sub TIEHANDLE { ## no critic (unpack)
- my $class = shift;
+ my $class = shift;
- return $class->new(@_);
+ return $class->new(@_);
}
sub PRINTF { ## no critic (unpack)
- my $self = shift;
- $self->PRINT( sprintf @_ );
+ my $self = shift;
+ $self->PRINT(sprintf @_);
}
sub PRINT { ## no critic (unpack)
- my $self = shift;
- my $c = $self->controller;
- my $bytes = join '', @_;
- return unless $bytes;
- if ( $self->_encoding ) {
- $bytes = encode( $self->_encoding, $bytes );
- }
- $c->write($bytes . ( $OUTPUT_RECORD_SEPARATOR // '' ) );
+ my $self = shift;
+ my $c = $self->controller;
+ my $bytes = join '', @_;
+ return unless $bytes;
+ if ($self->_encoding) {
+ $bytes = encode($self->_encoding, $bytes);
+ }
+ $c->write($bytes . ($OUTPUT_RECORD_SEPARATOR // ''));
}
sub BINMODE {
- my ( $self, $mode ) = @_;
- if ($mode) {
- if ( $mode eq ':bytes' or $mode eq ':raw' ) {
- $self->_encoding('');
- }
- elsif ( $mode eq ':utf8' ) {
- $self->_encoding('utf8');
- }
+ my ($self, $mode) = @_;
+ if ($mode) {
+ if ($mode eq ':bytes' or $mode eq ':raw') {
+ $self->_encoding('');
+ }
+ elsif ($mode eq ':utf8') {
+ $self->_encoding('utf8');
}
+ }
}
1;