summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Bugzilla.pm35
-rw-r--r--Bugzilla/CGI.pm4
-rw-r--r--Bugzilla/Config/GroupSecurity.pm26
-rw-r--r--Bugzilla/Constants.pm4
-rw-r--r--Bugzilla/DB/Schema.pm12
-rw-r--r--Bugzilla/Install.pm9
-rw-r--r--Bugzilla/Logging.pm2
-rw-r--r--Bugzilla/PSGI.pm42
-rw-r--r--Bugzilla/Product.pm60
-rw-r--r--Bugzilla/Template.pm4
-rwxr-xr-xMakefile.PL34
-rw-r--r--app.psgi115
-rwxr-xr-xeditproducts.cgi26
-rwxr-xr-xeditusers.cgi5
-rw-r--r--extensions/BMO/Extension.pm235
-rw-r--r--extensions/BMO/lib/Data.pm24
-rw-r--r--extensions/BzAPI/Extension.pm9
-rw-r--r--extensions/Push/lib/Logger.pm2
-rwxr-xr-xheartbeat.cgi2
-rw-r--r--mod_perl.pl3
-rwxr-xr-xscripts/migrate-database.pl47
-rw-r--r--template/en/default/admin/params/groupsecurity.html.tmpl5
-rwxr-xr-xtoken.cgi2
-rwxr-xr-xuserprefs.cgi2
24 files changed, 434 insertions, 275 deletions
diff --git a/Bugzilla.pm b/Bugzilla.pm
index 4a3dcb114..3e969a99d 100644
--- a/Bugzilla.pm
+++ b/Bugzilla.pm
@@ -57,6 +57,7 @@ use File::Basename;
use File::Spec::Functions;
use Safe;
use Sys::Syslog qw(:DEFAULT);
+use List::Util qw(any);
use JSON::XS qw(decode_json);
use parent qw(Bugzilla::CPAN);
@@ -117,20 +118,6 @@ sub init_page {
# 001compile.t test).
return if $^C;
- # IIS prints out warnings to the webpage, so ignore them, or log them
- # to a file if the file exists.
- if ($ENV{SERVER_SOFTWARE} && $ENV{SERVER_SOFTWARE} =~ /microsoft-iis/i) {
- $SIG{__WARN__} = sub {
- my ($msg) = @_;
- my $datadir = bz_locations()->{'datadir'};
- if (-w "$datadir/errorlog") {
- my $warning_log = new IO::File(">>$datadir/errorlog");
- print $warning_log $msg;
- $warning_log->close();
- }
- };
- }
-
my $script = basename($0);
# BMO - init metrics collection if required
@@ -369,7 +356,7 @@ sub login {
return $class->user if $class->user->id;
# Load all extensions here if not running under mod_perl
- $class->extensions unless $ENV{MOD_PERL};
+ $class->extensions unless BZ_PERSISTENT;
my $authorizer = new Bugzilla::Auth();
$type = LOGIN_REQUIRED if $class->cgi->param('GoAheadAndLogIn');
@@ -868,6 +855,20 @@ sub check_rate_limit {
}
}
+# called from the verify version, component, and group page.
+# if we're making a group invalid, stuff the default group into the cgi param
+# to make it checked by default.
+sub check_default_product_security_group {
+ my ($class, $product, $invalid_groups, $optional_group_controls) = @_;
+ return unless my $group = $product->default_security_group_obj;
+ if (@$invalid_groups) {
+ my $cgi = $class->cgi;
+ my @groups = $cgi->param('groups');
+ push @groups, $group->name unless any { $_ eq $group->name } @groups;
+ $cgi->param('groups', @groups);
+ }
+}
+
# Private methods
# Per-process cleanup. Note that this is a plain subroutine, not a method,
@@ -902,10 +903,10 @@ sub _cleanup {
sub END {
# Bugzilla.pm cannot compile in mod_perl.pl if this runs.
- _cleanup() unless $ENV{MOD_PERL};
+ _cleanup() unless BZ_PERSISTENT;
}
-init_page() if !$ENV{MOD_PERL};
+init_page() unless BZ_PERSISTENT;
1;
diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm
index 3737b97e2..05e2bd749 100644
--- a/Bugzilla/CGI.pm
+++ b/Bugzilla/CGI.pm
@@ -113,7 +113,7 @@ sub new {
# Under mod_perl, CGI's global variables get reset on each request,
# so we need to set them up again every time.
- $class->_init_bz_cgi_globals() if $ENV{MOD_PERL};
+ $class->_init_bz_cgi_globals() if BZ_PERSISTENT;
my $self = $class->SUPER::new(@args);
@@ -597,6 +597,8 @@ sub header {
sub param {
my $self = shift;
+ local $CGI::LIST_CONTEXT_WARN = 0;
+
# When we are just requesting the value of a parameter...
if (scalar(@_) == 1) {
my @result = $self->SUPER::param(@_);
diff --git a/Bugzilla/Config/GroupSecurity.pm b/Bugzilla/Config/GroupSecurity.pm
index 68c852fe6..c1d2faac1 100644
--- a/Bugzilla/Config/GroupSecurity.pm
+++ b/Bugzilla/Config/GroupSecurity.pm
@@ -84,6 +84,32 @@ sub get_param_list {
name => 'strict_isolation',
type => 'b',
default => 0
+ },
+ {
+ name => 'always_filleable_groups',
+ type => 'l',
+ default => join(", ", qw(
+ addons-security
+ bugzilla-security
+ client-services-security
+ consulting
+ core-security
+ finance
+ infra
+ infrasec
+ l20n-security
+ marketing-private
+ mozilla-confidential
+ mozilla-employee-confidential
+ mozilla-foundation-confidential
+ mozilla-engagement
+ mozilla-messaging-confidential
+ partner-confidential
+ payments-confidential
+ tamarin-security
+ websites-security
+ webtools-security
+ )),
}
);
return @param_list;
diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm
index 00f0f8104..2971c7a53 100644
--- a/Bugzilla/Constants.pm
+++ b/Bugzilla/Constants.pm
@@ -194,6 +194,8 @@ use Memoize;
EMAIL_LIMIT_EXCEPTION
JOB_QUEUE_VIEW_MAX_JOBS
+
+ BZ_PERSISTENT
);
@Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
@@ -705,6 +707,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/DB/Schema.pm b/Bugzilla/DB/Schema.pm
index 3307464db..41afaeacf 100644
--- a/Bugzilla/DB/Schema.pm
+++ b/Bugzilla/DB/Schema.pm
@@ -1410,6 +1410,18 @@ use constant ABSTRACT_SCHEMA => {
NOTNULL => 1, DEFAULT => "'---'"},
allows_unconfirmed => {TYPE => 'BOOLEAN', NOTNULL => 1,
DEFAULT => 'TRUE'},
+ default_op_sys_id => {TYPE => 'INT2',
+ REFERENCES => {TABLE => 'op_sys',
+ COLUMN => 'id',
+ DELETE => 'SET NULL'}},
+ default_platform_id => {TYPE => 'INT2',
+ REFERENCES => {TABLE => 'rep_platform',
+ COLUMN => 'id',
+ DELETE => 'SET NULL'}},
+ security_group_id => {TYPE => 'INT3',
+ REFERENCES => {TABLE => 'groups',
+ COLUMN => 'id',
+ DELETE => 'SET NULL'}},
],
INDEXES => [
products_name_idx => {FIELDS => ['name'],
diff --git a/Bugzilla/Install.pm b/Bugzilla/Install.pm
index 6d47a143f..6ac16821e 100644
--- a/Bugzilla/Install.pm
+++ b/Bugzilla/Install.pm
@@ -284,6 +284,12 @@ use constant DEFAULT_PRODUCT => {
defaultmilestone => DEFAULT_MILESTONE,
};
+use constant DEFAULT_PRODUCT_GROUP => {
+ name => 'test-product-security',
+ description => "Security Sensitive TestProduct Bug",
+ isbuggroup => 1,
+};
+
use constant DEFAULT_COMPONENT => {
name => 'TestComponent',
description => 'This is a test component in the test product database.'
@@ -362,7 +368,8 @@ sub create_default_product {
print get_text('install_default_product',
{ name => DEFAULT_PRODUCT->{name} }) . "\n";
- my $product = Bugzilla::Product->create(DEFAULT_PRODUCT);
+ my $group = Bugzilla::Group->create(DEFAULT_PRODUCT_GROUP);
+ my $product = Bugzilla::Product->create({ %{DEFAULT_PRODUCT()}, security_group_id => $group->id });
# Get the user who will be the owner of the Component.
# We pick the admin with the lowest id, which is probably the
diff --git a/Bugzilla/Logging.pm b/Bugzilla/Logging.pm
index b69ffa2e9..769485c86 100644
--- a/Bugzilla/Logging.pm
+++ b/Bugzilla/Logging.pm
@@ -17,7 +17,7 @@ use Bugzilla::Constants qw(bz_locations);
use English qw(-no_match_vars $PROGRAM_NAME);
sub is_interactive {
- return exists $ENV{'SERVER_SOFTWARE'} ? 1 : 0;
+ return not exists $ENV{SERVER_SOFTWARE}
}
BEGIN {
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/Product.pm b/Bugzilla/Product.pm
index 3ac1692f0..9cf4bf397 100644
--- a/Bugzilla/Product.pm
+++ b/Bugzilla/Product.pm
@@ -47,6 +47,9 @@ use constant DB_COLUMNS => qw(
isactive
defaultmilestone
allows_unconfirmed
+ default_platform_id
+ default_op_sys_id
+ security_group_id
);
use constant UPDATE_COLUMNS => qw(
@@ -55,6 +58,9 @@ use constant UPDATE_COLUMNS => qw(
defaultmilestone
isactive
allows_unconfirmed
+ default_platform_id
+ default_op_sys_id
+ security_group_id
);
use constant VALIDATORS => {
@@ -837,6 +843,60 @@ sub is_active { return $_[0]->{'isactive'}; }
sub default_milestone { return $_[0]->{'defaultmilestone'}; }
sub classification_id { return $_[0]->{'classification_id'}; }
+sub default_security_group {
+ my ($self) = @_;
+ return $self->default_security_group_obj->name;
+}
+
+sub default_security_group_obj {
+ my ($self) = @_;
+ my $group_id = $self->{security_group_id};
+ if (!$group_id) {
+ return Bugzilla::Group->new({ name => Bugzilla->params->{insidergroup}, cache => 1 });
+ }
+ return Bugzilla::Group->new({ id => $group_id, cache => 1 });
+}
+
+sub default_platform_id { shift->{default_platform_id} }
+sub default_op_sys_id { shift->{default_op_sys_id} }
+
+# you can always file bugs into a product's default security group, as well as
+# into any of the groups in @always_fileable_groups
+sub group_always_settable {
+ my ( $self, $group ) = @_;
+ my @always_fileable_groups = split(/\s*,\s*/, Bugzilla->params->{always_fileable_groups});
+ return $group->name eq $self->default_security_group
+ || ( ( any { $_ eq $group->name } @always_fileable_groups ) ? 1 : 0 );
+}
+
+
+sub default_platform {
+ my ($self) = @_;
+ if (!exists $self->{default_platform}) {
+ $self->{default_platform} = $self->default_platform_id
+ ? Bugzilla::Field::Choice
+ ->type('rep_platform')
+ ->new($self->{default_platform_id})
+ ->name
+ : undef;
+ }
+ return $self->{default_platform};
+}
+
+sub default_op_sys {
+ my ($self) = @_;
+ if (!exists $self->{default_op_sys}) {
+ $self->{default_op_sys} = $self->default_op_sys_id
+ ? Bugzilla::Field::Choice
+ ->type('op_sys')
+ ->new($self->{default_op_sys_id})
+ ->name
+ : undef;
+ }
+ return $self->{default_op_sys};
+}
+
+
###############################
#### Subroutines ######
###############################
diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm
index d27896532..0d2a4cd86 100644
--- a/Bugzilla/Template.pm
+++ b/Bugzilla/Template.pm
@@ -570,7 +570,7 @@ sub create {
# if a packager has modified bz_locations() to contain absolute
# paths.
ABSOLUTE => 1,
- RELATIVE => $ENV{MOD_PERL} ? 0 : 1,
+ RELATIVE => 0,
COMPILE_DIR => bz_locations()->{'template_cache'},
@@ -1037,7 +1037,7 @@ sub create {
# under mod_perl, use a provider (template loader) that preloads all templates into memory
my $provider_class
- = $ENV{MOD_PERL}
+ = BZ_PERSISTENT
? 'Bugzilla::Template::PreloadProvider'
: 'Template::Provider';
diff --git a/Makefile.PL b/Makefile.PL
index 34e4e2487..57bc06001 100755
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -34,6 +34,8 @@ BEGIN {
my %requires = (
'Algorithm::BloomFilter' => '0.02',
'CGI' => '3.51',
+ 'CGI::Compile' => 0,
+ 'CGI::Emulate::PSGI' => 0,
'CPAN::Meta::Prereqs' => '2.132830',
'CPAN::Meta::Requirements' => '2.121',
'Class::XSAccessor' => '1.18',
@@ -51,11 +53,14 @@ my %requires = (
'HTML::Escape' => '1.10',
'IO::Async' => '0.71',
'JSON::MaybeXS' => '1.003008',
+ 'JSON::MaybeXS' => '1.003008',
'JSON::XS' => '2.01',
'LWP::Protocol::https' => '6.07',
'LWP::UserAgent' => '6.26',
'List::MoreUtils' => '0.418',
'Log::Dispatch' => '2.67',
+ 'Log::Dispatch' => '2.67',
+ 'Log::Log4perl' => '1.49',
'Log::Log4perl' => '1.49',
'Math::Random::ISAAC' => '1.0.1',
'Module::Metadata' => '1.000033',
@@ -64,8 +69,10 @@ my %requires = (
'MooX::StrictConstructor' => '0.008',
'Mozilla::CA' => '20160104',
'Parse::CPAN::Meta' => '1.44',
+ 'Plack' => '1.0031',
'Role::Tiny' => '2.000003',
'Sereal' => '4.004',
+ 'Sereal' => '4.004',
'Taint::Util' => '0.08',
'Template' => '2.24',
'Text::CSV_XS' => '1.26',
@@ -318,6 +325,32 @@ my %optional_features = (
}
}
},
+<<<<<<< HEAD
+=======
+ psgi => {
+ description => "PSGI Support",
+ prereqs => {
+ runtime => {
+ requires => {
+ 'Plack' => '1.0031',
+ 'CGI::Compile' => 0,
+ 'CGI::Emulate::PSGI' => 0,
+ },
+ },
+ },
+ },
+ csp => {
+ description => 'Content-Security-Policy support',
+ prereqs => {
+ runtime => {
+ requires => {
+ 'Type::Tiny' => 1,
+ 'MooX::StrictConstructor' => 0.008,
+ }
+ }
+ }
+ },
+>>>>>>> 741eeec31... psgi optionalize until can rebuild vendor bundle
elasticsearch => {
description => 'Elasticsearch-powered searches',
prereqs => {
@@ -363,6 +396,7 @@ my @bmo_features = grep {
(?: pg
| oracle
| mod_perl
+ | psgi
| sqlite
| auth_ldap
| auth_radius
diff --git a/app.psgi b/app.psgi
new file mode 100644
index 000000000..4425b3e0c
--- /dev/null
+++ b/app.psgi
@@ -0,0 +1,115 @@
+#!/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;
+
+BEGIN { $main::BUGZILLA_PERSISTENT = 1 }
+
+use File::Basename;
+use File::Spec;
+
+BEGIN {
+ require lib;
+ my $dir = File::Spec->rel2abs( dirname(__FILE__) );
+ lib->import(
+ $dir,
+ File::Spec->catdir( $dir, 'lib' ),
+ File::Spec->catdir( $dir, qw(local lib perl5) )
+ );
+
+ # disable "use lib" from now on
+ no warnings qw(redefine);
+ *lib::import = sub { };
+}
+
+# it is very important for CGI::Compile to be loaded first.
+use CGI::Compile;
+use Bugzilla::PSGI qw(compile_cgi);
+use Bugzilla::Logging;
+use Bugzilla ();
+use Bugzilla::Constants ();
+use Bugzilla::BugMail ();
+use Bugzilla::CGI ();
+use Bugzilla::Extension ();
+use Bugzilla::Install::Requirements ();
+use Bugzilla::Util ();
+use Bugzilla::RNG ();
+
+use Plack;
+use Plack::Builder;
+use Plack::App::URLMap;
+use Plack::App::WrapCGI;
+use Plack::Response;
+
+# Pre-load all extensions and find their static dirs.
+my @extensions = map { $_->NAME } @{ Bugzilla::Extension->load_all() };
+my @static_dirs = qw( data/webdot docs graphs images js skins static );
+foreach my $name (@extensions) {
+ my $dir = File::Spec->catfile('extensions', $name, 'web');
+ push @static_dirs, $dir if -d $dir;
+}
+
+Bugzilla->preload_features();
+
+# Force instantiation of template so Bugzilla::Template::PreloadProvider can do its magic.
+Bugzilla->template;
+
+use Bugzilla::Sentry;
+
+
+my $bugzilla_app = builder {
+ my $static_paths = join '|', map quotemeta, sort {length $b <=> length $a || $a cmp $b } @static_dirs;
+
+ enable 'Log4perl', category => 'Plack';
+
+ enable 'Static',
+ path => sub { s{^/(?:static/v\d+\.\d+/)?($static_paths)/}{$1/}gs },
+ root => Bugzilla::Constants::bz_locations->{cgi_path};
+
+ my @scripts = glob('*.cgi');
+
+ my %mount;
+
+ foreach my $script (@scripts) {
+ my $name = basename($script);
+ $mount{$name} = compile_cgi($script);
+ }
+
+ Bugzilla::Hook::process('psgi_builder', { mount => \%mount });
+
+ foreach my $name ( keys %mount ) {
+ mount "/$name" => $mount{$name};
+ }
+
+ # so mount / => $app will make *all* files redirect to the index.
+ # instead we use an inline middleware to rewrite / to /index.cgi
+ enable sub {
+ my $app = shift;
+ return sub {
+ my $env = shift;
+ $env->{PATH_INFO} = '/index.cgi' if $env->{PATH_INFO} eq '/';
+ return $app->($env);
+ };
+ };
+
+ mount '/robots.txt' => $mount{'robots.cgi'};
+ mount '/rest' => $mount{'rest.cgi'};
+
+};
+
+unless (caller) {
+ require Plack::Runner;
+ my $runner = Plack::Runner->new;
+ $runner->parse_options(@ARGV);
+ $runner->run($bugzilla_app);
+ exit 0;
+}
+
+return $bugzilla_app;
diff --git a/editproducts.cgi b/editproducts.cgi
index a989e4bc1..618aec547 100755
--- a/editproducts.cgi
+++ b/editproducts.cgi
@@ -158,15 +158,19 @@ if ($action eq 'new') {
check_token_data($token, 'add_product');
my %create_params = (
- classification => $classification_name,
- name => $product_name,
- description => scalar $cgi->param('description'),
- version => scalar $cgi->param('version'),
- defaultmilestone => scalar $cgi->param('defaultmilestone'),
- isactive => scalar $cgi->param('is_active'),
- create_series => scalar $cgi->param('createseries'),
- allows_unconfirmed => scalar $cgi->param('allows_unconfirmed'),
+ classification => $classification_name,
+ name => $product_name,
+ description => scalar $cgi->param('description'),
+ version => scalar $cgi->param('version'),
+ defaultmilestone => scalar $cgi->param('defaultmilestone'),
+ isactive => scalar $cgi->param('is_active'),
+ create_series => scalar $cgi->param('createseries'),
+ allows_unconfirmed => scalar $cgi->param('allows_unconfirmed'),
+ default_platform_id => scalar $cgi->param('default_platform_id'),
+ default_op_sys_id => scalar $cgi->param('default_op_sys_id'),
+ security_group_id => scalar $cgi->param('security_group_id'),
);
+
my $product = Bugzilla::Product->create(\%create_params);
delete_token($token);
@@ -279,6 +283,12 @@ if ($action eq 'update') {
default_milestone => scalar $cgi->param('defaultmilestone'),
});
+ foreach my $field (qw( default_platform_id default_op_sys_id security_group_id )) {
+ my $value = $cgi->param($field);
+ detaint_natural($value);
+ $product->set($field, $value);
+ }
+
my $changes = $product->update();
delete_token($token);
diff --git a/editusers.cgi b/editusers.cgi
index 934e0a4ef..ae1f35835 100755
--- a/editusers.cgi
+++ b/editusers.cgi
@@ -24,14 +24,13 @@ use Bugzilla::Field;
use Bugzilla::Group;
use Bugzilla::Token;
-my $user = Bugzilla->login(LOGIN_REQUIRED);
-
+local our $user = Bugzilla->login(LOGIN_REQUIRED);
my $cgi = Bugzilla->cgi;
my $template = Bugzilla->template;
my $dbh = Bugzilla->dbh;
my $userid = $user->id;
my $editusers = $user->in_group('editusers');
-local our $vars = {};
+local our $vars = {};
# Reject access if there is no sense in continuing.
$editusers
diff --git a/extensions/BMO/Extension.pm b/extensions/BMO/Extension.pm
index 2d5d2b182..322d03769 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;
@@ -76,14 +77,6 @@ BEGIN {
*Bugzilla::Bug::is_unassigned = \&_bug_is_unassigned;
*Bugzilla::Bug::has_current_patch = \&_bug_has_current_patch;
*Bugzilla::Bug::missing_sec_approval = \&_bug_missing_sec_approval;
- *Bugzilla::Product::default_security_group = \&_default_security_group;
- *Bugzilla::Product::default_security_group_obj = \&_default_security_group_obj;
- *Bugzilla::Product::group_always_settable = \&_group_always_settable;
- *Bugzilla::Product::default_platform_id = \&_product_default_platform_id;
- *Bugzilla::Product::default_op_sys_id = \&_product_default_op_sys_id;
- *Bugzilla::Product::default_platform = \&_product_default_platform;
- *Bugzilla::Product::default_op_sys = \&_product_default_op_sys;
- *Bugzilla::check_default_product_security_group = \&_check_default_product_security_group;
*Bugzilla::Attachment::is_bounty_attachment = \&_attachment_is_bounty_attachment;
*Bugzilla::Attachment::bounty_details = \&_attachment_bounty_details;
*Bugzilla::Attachment::external_redirect = \&_attachment_external_redirect;
@@ -820,26 +813,6 @@ sub quicksearch_map {
}
}
-sub object_columns {
- my ($self, $args) = @_;
- return unless $args->{class}->isa('Bugzilla::Product');
- push @{ $args->{columns} }, qw(
- default_platform_id
- default_op_sys_id
- security_group_id
- );
-}
-
-sub object_update_columns {
- my ($self, $args) = @_;
- return unless $args->{object}->isa('Bugzilla::Product');
- push @{ $args->{columns} }, qw(
- default_platform_id
- default_op_sys_id
- security_group_id
- );
-}
-
sub object_before_create {
my ($self, $args) = @_;
return unless $args->{class}->isa('Bugzilla::Product');
@@ -979,33 +952,6 @@ sub _bug_missing_sec_approval {
return $set == 0;
}
-sub _product_default_platform_id { $_[0]->{default_platform_id} }
-sub _product_default_op_sys_id { $_[0]->{default_op_sys_id} }
-
-sub _product_default_platform {
- my ($self) = @_;
- if (!exists $self->{default_platform}) {
- $self->{default_platform} = $self->default_platform_id
- ? Bugzilla::Field::Choice
- ->type('rep_platform')
- ->new($_[0]->{default_platform_id})
- ->name
- : undef;
- }
- return $self->{default_platform};
-}
-sub _product_default_op_sys {
- my ($self) = @_;
- if (!exists $self->{default_op_sys}) {
- $self->{default_op_sys} = $self->default_op_sys_id
- ? Bugzilla::Field::Choice
- ->type('op_sys')
- ->new($_[0]->{default_op_sys_id})
- ->name
- : undef;
- }
- return $self->{default_op_sys};
-}
sub _get_named_query {
my ($sharer_id, $group_id, $definition) = @_;
@@ -1385,34 +1331,6 @@ sub db_schema_abstract_schema {
sub install_update_db {
my $dbh = Bugzilla->dbh;
- # per-product hw/os defaults
- my $op_sys_default = _field_value('op_sys', 'Unspecified', 50);
- $dbh->bz_add_column(
- 'products',
- 'default_op_sys_id' => {
- TYPE => 'INT2',
- DEFAULT => $op_sys_default->id,
- REFERENCES => {
- TABLE => 'op_sys',
- COLUMN => 'id',
- DELETE => 'SET NULL',
- },
- }
- );
- my $platform_default = _field_value('rep_platform', 'Unspecified', 50);
- $dbh->bz_add_column(
- 'products',
- 'default_platform_id' => {
- TYPE => 'INT2',
- DEFAULT => $platform_default->id,
- REFERENCES => {
- TABLE => 'rep_platform',
- COLUMN => 'id',
- DELETE => 'SET NULL',
- },
- }
- );
-
# Migrate old is_active stuff to new patch (is in core in 4.2), The old
# column name was 'is_active', the new one is 'isactive' (no underscore).
if ($dbh->bz_column_info('milestones', 'is_active')) {
@@ -1449,99 +1367,6 @@ sub install_update_db {
buglist => 0,
});
}
-
- # Add default security group id column
- if (!$dbh->bz_column_info('products', 'security_group_id')) {
- $dbh->bz_add_column(
- 'products',
- 'security_group_id' => {
- TYPE => 'INT3',
- REFERENCES => {
- TABLE => 'groups',
- COLUMN => 'id',
- DELETE => 'SET NULL',
- },
- }
- );
-
- # if there are no groups, then we're creating a database from scratch
- # and there's nothing to migrate
- my ($group_count) = $dbh->selectrow_array("SELECT COUNT(*) FROM groups");
- if ($group_count) {
- # Migrate old product_sec_group mappings from the time this change was made
- my %product_sec_groups = (
- "addons.mozilla.org" => 'client-services-security',
- "Air Mozilla" => 'mozilla-employee-confidential',
- "Android Background Services" => 'cloud-services-security',
- "Audio/Visual Infrastructure" => 'mozilla-employee-confidential',
- "AUS" => 'client-services-security',
- "Bugzilla" => 'bugzilla-security',
- "bugzilla.mozilla.org" => 'bugzilla-security',
- "Cloud Services" => 'cloud-services-security',
- "Community Tools" => 'websites-security',
- "Data & BI Services Team" => 'metrics-private',
- "Developer Documentation" => 'websites-security',
- "Developer Ecosystem" => 'client-services-security',
- "Finance" => 'finance',
- "Firefox Friends" => 'mozilla-employee-confidential',
- "Firefox Health Report" => 'cloud-services-security',
- "Infrastructure & Operations" => 'mozilla-employee-confidential',
- "Input" => 'websites-security',
- "Intellego" => 'intellego-team',
- "Internet Public Policy" => 'mozilla-employee-confidential',
- "L20n" => 'l20n-security',
- "Legal" => 'legal',
- "Marketing" => 'marketing-private',
- "Marketplace" => 'client-services-security',
- "Mozilla Communities" => 'mozilla-communities-security',
- "Mozilla Corporation" => 'mozilla-employee-confidential',
- "Mozilla Developer Network" => 'websites-security',
- "Mozilla Foundation" => 'mozilla-employee-confidential',
- "Mozilla Foundation Operations" => 'mozilla-foundation-operations',
- "Mozilla Grants" => 'grants',
- "mozillaignite" => 'websites-security',
- "Mozilla Messaging" => 'mozilla-messaging-confidential',
- "Mozilla Metrics" => 'metrics-private',
- "mozilla.org" => 'mozilla-employee-confidential',
- "Mozilla PR" => 'pr-private',
- "Mozilla QA" => 'mozilla-employee-confidential',
- "Mozilla Reps" => 'mozilla-reps',
- "Popcorn" => 'websites-security',
- "Privacy" => 'privacy',
- "quality.mozilla.org" => 'websites-security',
- "Recruiting" => 'hr',
- "Release Engineering" => 'mozilla-employee-confidential',
- "Snippets" => 'websites-security',
- "Socorro" => 'client-services-security',
- "support.mozillamessaging.com" => 'websites-security',
- "support.mozilla.org" => 'websites-security',
- "Talkback" => 'talkback-private',
- "Tamarin" => 'tamarin-security',
- "Taskcluster" => 'taskcluster-security',
- "Testopia" => 'bugzilla-security',
- "Tree Management" => 'mozilla-employee-confidential',
- "Web Apps" => 'client-services-security',
- "Webmaker" => 'websites-security',
- "Websites" => 'websites-security',
- "Webtools" => 'webtools-security',
- "www.mozilla.org" => 'websites-security',
- );
- # 1. Set all to core-security by default
- my $core_sec_group = Bugzilla::Group->new({ name => 'core-security' });
- $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
- my $group = Bugzilla::Group->new({ name => $group_name, cache => 1 });
- if (!$group) {
- warn "Security group $group_name not found. Using core-security instead.\n";
- next;
- }
- $dbh->do("UPDATE products SET security_group_id = ? WHERE name = ?", undef, $group->id, $prod_name);
- }
- }
- }
}
# return the Bugzilla::Field::Choice object for the specified field and value.
@@ -1557,7 +1382,6 @@ sub _field_value {
isactive => 1,
});
}
-
sub _last_closed_date {
my ($self) = @_;
my $dbh = Bugzilla->dbh;
@@ -1666,6 +1490,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;
@@ -2544,41 +2390,6 @@ sub query_database {
}
}
-# you can always file bugs into a product's default security group, as well as
-# into any of the groups in @always_fileable_groups
-sub _group_always_settable {
- my ($self, $group) = @_;
- return
- $group->name eq $self->default_security_group
- || ((grep { $_ eq $group->name } @always_fileable_groups) ? 1 : 0);
-}
-
-sub _default_security_group {
- return $_[0]->default_security_group_obj->name;
-}
-
-sub _default_security_group_obj {
- my $group_id = $_[0]->{security_group_id};
- if (!$group_id) {
- return Bugzilla::Group->new({ name => Bugzilla->params->{insidergroup}, cache => 1 });
- }
- return Bugzilla::Group->new({ id => $group_id, cache => 1 });
-}
-
-# called from the verify version, component, and group page.
-# if we're making a group invalid, stuff the default group into the cgi param
-# to make it checked by default.
-sub _check_default_product_security_group {
- my ($self, $product, $invalid_groups, $optional_group_controls) = @_;
- return unless my $group = $product->default_security_group_obj;
- if (@$invalid_groups) {
- my $cgi = Bugzilla->cgi;
- my @groups = $cgi->param('groups');
- push @groups, $group->name unless grep { $_ eq $group->name } @groups;
- $cgi->param('groups', @groups);
- }
-}
-
sub install_filesystem {
my ($self, $args) = @_;
my $files = $args->{files};
diff --git a/extensions/BMO/lib/Data.pm b/extensions/BMO/lib/Data.pm
index 4df05581c..525b4ee04 100644
--- a/extensions/BMO/lib/Data.pm
+++ b/extensions/BMO/lib/Data.pm
@@ -17,7 +17,6 @@ use Tie::IxHash;
our @EXPORT = qw( $cf_visible_in_products
%group_change_notification
$cf_setters
- @always_fileable_groups
%group_auto_cc
%create_bug_formats
@default_named_queries
@@ -218,29 +217,6 @@ our $cf_setters = {
'cf_rank' => [ 'rank-setters' ],
};
-# Groups in which you can always file a bug, regardless of product or user.
-our @always_fileable_groups = qw(
- addons-security
- bugzilla-security
- client-services-security
- consulting
- core-security
- finance
- infra
- infrasec
- l20n-security
- marketing-private
- mozilla-confidential
- mozilla-employee-confidential
- mozilla-foundation-confidential
- mozilla-engagement
- mozilla-messaging-confidential
- partner-confidential
- payments-confidential
- tamarin-security
- websites-security
- webtools-security
-);
# Automatically CC users to bugs filed into configured groups and products
our %group_auto_cc = (
diff --git a/extensions/BzAPI/Extension.pm b/extensions/BzAPI/Extension.pm
index bb9805134..1f7cce04a 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);
@@ -188,6 +189,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/Push/lib/Logger.pm b/extensions/Push/lib/Logger.pm
index 833cb3b19..7ae96b58a 100644
--- a/extensions/Push/lib/Logger.pm
+++ b/extensions/Push/lib/Logger.pm
@@ -31,11 +31,11 @@ sub debugging {
}
sub _log_it {
- require Apache2::Log;
my ($self, $method, $message) = @_;
return if $method eq 'DEBUG' && !$self->debugging;
chomp $message;
if ($ENV{MOD_PERL}) {
+ require Apache2::Log;
Apache2::ServerRec::warn("Push $method: $message");
} elsif ($ENV{SCRIPT_FILENAME}) {
print STDERR "Push $method: $message\n";
diff --git a/heartbeat.cgi b/heartbeat.cgi
index 40dc8e79b..917853d2b 100755
--- a/heartbeat.cgi
+++ b/heartbeat.cgi
@@ -28,7 +28,7 @@ my $ok = eval {
die "database not available" unless $database_ok;
die "memcached server(s) not available" unless $memcached_ok;
- die "mod_perl not configured?" unless $ENV{MOD_PERL};
+ die "mod_perl/psgi not configured?" unless BZ_PERSISTENT;
die "missing bmo feature dependencies" unless Bugzilla->has_feature('bmo');
1;
};
diff --git a/mod_perl.pl b/mod_perl.pl
index 09fd80850..af60bb359 100644
--- a/mod_perl.pl
+++ b/mod_perl.pl
@@ -6,12 +6,15 @@
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
+
package Bugzilla::ModPerl;
use 5.10.1;
use strict;
use warnings;
+BEGIN { $main::BUGZILLA_PERSISTENT = 1 }
+
# This sets up our libpath without having to specify it in the mod_perl
# configuration.
use File::Basename;
diff --git a/scripts/migrate-database.pl b/scripts/migrate-database.pl
new file mode 100755
index 000000000..cde7c80c0
--- /dev/null
+++ b/scripts/migrate-database.pl
@@ -0,0 +1,47 @@
+#!/usr/bin/perl
+use 5.10.1;
+use strict;
+use warnings;
+
+use File::Basename;
+use File::Spec;
+BEGIN {
+ require lib;
+ my $dir = File::Spec->rel2abs(dirname(__FILE__));
+ my $base = File::Spec->catdir($dir, "..");
+ lib->import($base, File::Spec->catdir($base, "lib"), File::Spec->catdir($base, qw(local lib perl5)));
+ chdir $base;
+}
+
+use Bugzilla;
+BEGIN { Bugzilla->extensions }
+
+use Bugzilla::DB;
+use Bugzilla::Install::DB;
+use Bugzilla::Config qw(update_params);
+
+Bugzilla::DB::bz_create_database();
+
+# Clear all keys from Memcached to ensure we see the correct schema.
+Bugzilla->memcached->clear_all();
+
+# now get a handle to the database:
+my $dbh = Bugzilla->dbh;
+# Create the tables, and do any database-specific schema changes.
+$dbh->bz_setup_database();
+# Populate the tables that hold the values for the <select> fields.
+$dbh->bz_populate_enum_tables();
+
+# Using Bugzilla::Field's create() or update() depends on the
+# fielddefs table having a modern definition. So, we have to make
+# these particular schema changes before we make any other schema changes.
+Bugzilla::Install::DB::update_fielddefs_definition();
+
+Bugzilla::Field::populate_field_definitions();
+
+###########################################################################
+# Update the tables to the current definition --TABLE--
+###########################################################################
+
+Bugzilla::Install::DB::update_table_definitions({});
+Bugzilla::Install::init_workflow();
diff --git a/template/en/default/admin/params/groupsecurity.html.tmpl b/template/en/default/admin/params/groupsecurity.html.tmpl
index 041af6833..e20c18421 100644
--- a/template/en/default/admin/params/groupsecurity.html.tmpl
+++ b/template/en/default/admin/params/groupsecurity.html.tmpl
@@ -50,13 +50,14 @@
usevisibilitygroups => "Do you wish to restrict visibility of users to members of " _
"specific groups?",
-
+
strict_isolation => "Don't allow users to be assigned to, " _
"be qa-contacts on, " _
"be added to CC list, " _
"or make or remove dependencies " _
"involving any bug that is in a product on which that " _
- "user is forbidden to edit.",
+ "user is forbidden to edit.",
+ always_fileablr_grpups => "Groups in which you can always file a bug, regardless of product or user.",
}
%]
diff --git a/token.cgi b/token.cgi
index 51ed93977..990040050 100755
--- a/token.cgi
+++ b/token.cgi
@@ -23,7 +23,7 @@ use Date::Format;
use Date::Parse;
use JSON qw( decode_json );
-my $dbh = Bugzilla->dbh;
+local our $dbh = Bugzilla->dbh;
local our $cgi = Bugzilla->cgi;
local our $template = Bugzilla->template;
local our $vars = {};
diff --git a/userprefs.cgi b/userprefs.cgi
index e70b9780a..830c49eed 100755
--- a/userprefs.cgi
+++ b/userprefs.cgi
@@ -29,7 +29,7 @@ use DateTime;
use constant SESSION_MAX => 20;
-my $template = Bugzilla->template;
+local our $template = Bugzilla->template;
local our $vars = {};
###############################################################################