Skip to content

Commit 993100b

Browse files
committed
Merge branch 'master' into development
* master: Bumped version to 20250707.1 Bug 2038147 Bug 2042314 - [HackerOne] GitHub PR webhook can write attachments to non-visible BMO bugs r=sheehan Bug 2052188 - Move Close as Invalid button to the bottom action bar Bug 2052429 - Show: Open/Closed/All selects All incorrectly Bug 1619459 - Updated QA test to stop testing XMLRPC/JSONRPC and only test REST Bug 2043733 - Live Github Status for Pull Requests Bug 2036191 - Crash Signature Field Mismatch in Bugzilla REST API Bug 2049554 - Cloned security bugs should default to being secure even if they aren't in the default security group Bug 1355999 - Autocomplete on https://bugzilla.mozilla.org/form.web.bounty
2 parents 39c91a7 + c1181b5 commit 993100b

69 files changed

Lines changed: 3410 additions & 3983 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎Bugzilla.pm‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use warnings;
1313

1414
use Bugzilla::Logging;
1515

16-
our $VERSION = '20260630.1';
16+
our $VERSION = '20260707.1';
1717

1818
use Bugzilla::Auth;
1919
use Bugzilla::Auth::Persist::Cookie;

‎Bugzilla/API/V1/Github.pm‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ sub pull_request {
9494
# can see it (non-fatal).
9595
my ($bug_id) = $title =~ BUG_RE;
9696
my $bug = Bugzilla::Bug->new($bug_id);
97-
if ($bug->{error}) {
97+
if ($bug->{error} || !Bugzilla->user->can_see_bug($bug->id)) {
9898
$template->process('global/code-error.html.tmpl',
9999
{error => 'github_pr_bug_not_found'}, \$message)
100100
|| die $template->error();

‎Bugzilla/Bug.pm‎

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2717,9 +2717,17 @@ sub set_all {
27172717

27182718
$self->_add_remove($params, 'see_also');
27192719

2720-
# And set custom fields.
2720+
# And set custom fields. Only fields enabled for the bug's current
2721+
# product/component are considered; product/component were already applied
2722+
# via SUPER::set_all above, so this reflects the post-move state. This is
2723+
# intentional (bug 2036191): a value submitted for a field not enabled on
2724+
# the target product/component is ignored rather than written, closing the
2725+
# glitch where e.g. cf_crash_signature could be stored on a product that
2726+
# doesn't expose it.
27212727
my @custom_fields
2722-
= grep { $_->type != FIELD_TYPE_EXTENSION } Bugzilla->active_custom_fields;
2728+
= grep { $_->type != FIELD_TYPE_EXTENSION } Bugzilla->active_custom_fields(
2729+
{product => $self->product_obj, component => $self->component_obj}
2730+
);
27232731
foreach my $field (@custom_fields) {
27242732
my $fname = $field->name;
27252733
if (exists $params->{$fname}) {
@@ -3054,16 +3062,33 @@ sub _set_product {
30543062
# We copy this array because the original array is modified while we're
30553063
# working, and that confuses "foreach".
30563064
my @current_groups = @{$self->groups_in};
3065+
my $dropped_group = 0;
30573066
foreach my $group (@current_groups) {
30583067
if (!$product->group_is_valid($group)) {
30593068
$self->remove_group($group);
3069+
$dropped_group = 1;
30603070
}
30613071
}
30623072

30633073
# Make sure the bug is in all the mandatory groups for the new product.
30643074
foreach my $group (@{$product->groups_mandatory}) {
30653075
$self->add_group($group);
30663076
}
3077+
3078+
# If any of the bug's groups were dropped because they aren't valid in the
3079+
# new product, add the target product's default security group so the bug
3080+
# stays restricted to the best of our ability. This covers non-default
3081+
# security groups such as dom-core-security, not just the source product's
3082+
# own default (Bug 2028240, Bug 2049554, Bug 2038147). Runs for all usage
3083+
# modes; the browser path additionally pre-selects the group in the
3084+
# verify-new-product UI via _check_default_product_security_group() in the
3085+
# BMO extension.
3086+
my @pre_move_names = map { $_->name } @current_groups;
3087+
for my $sec_group (
3088+
_target_security_group_when_dropping($product, \@pre_move_names, $dropped_group))
3089+
{
3090+
$self->add_group($sec_group);
3091+
}
30673092
}
30683093
else {
30693094
# If we didn't change the product, we just die if any of these are invalid.
@@ -4372,20 +4397,45 @@ sub in_group {
43724397
}
43734398

43744399
# Returns extra group names to add when cloning $self into $target_product.
4375-
# If the bug is in its source product's default security group and the target
4376-
# product has a different one, the target group name is returned so the clone
4377-
# stays secure (Bug 2028240).
4400+
# When cloning across products, any of the bug's groups that aren't valid in
4401+
# the target product are silently dropped. If that would lose a group, we add
4402+
# the target product's default security group so the clone stays restricted to
4403+
# the best of our ability. This mirrors what happens when a bug is moved
4404+
# between products (see Bugzilla::check_default_product_security_group, which
4405+
# the verify-new-product template calls with the dropped groups), and covers
4406+
# non-default security groups such as dom-core-security -- not just the source
4407+
# product's own default (Bug 2028240, Bug 2049554).
43784408
sub extra_security_groups_for_clone {
43794409
my ($self, $target_product) = @_;
43804410
return () if $self->product_id == $target_product->id;
4411+
return () unless @{$self->groups_in};
4412+
4413+
# If every group the bug is in carries over to the target product, then no
4414+
# restriction is lost and there is nothing to compensate for.
4415+
my $dropped = $self->get_invalid_groups(
4416+
{bug_ids => [$self->id], product => $target_product});
4417+
4418+
my @group_names = map { $_->name } @{$self->groups_in};
4419+
return _target_security_group_when_dropping($target_product, \@group_names,
4420+
scalar @$dropped);
4421+
}
4422+
4423+
# Returns the target product's default security group name to add when a bug is
4424+
# moved or cloned into $target_product and at least one of its groups would be
4425+
# dropped there ($any_dropped is true). Returns () when nothing is dropped, the
4426+
# target has no default security group, or the bug is already in it.
4427+
# $group_names is an arrayref of the bug's current group names (caller supplies
4428+
# the snapshot it needs). This keeps a bug that was secured in *any* group --
4429+
# not only the source product's own default security group -- restricted after
4430+
# a product change (Bug 2028240, Bug 2049554, Bug 2038147).
4431+
sub _target_security_group_when_dropping {
4432+
my ($target_product, $group_names, $any_dropped) = @_;
4433+
return () unless $any_dropped;
43814434
return () unless $target_product->can('default_security_group');
43824435

4383-
my @clone_groups = map { $_->name } @{$self->groups_in};
4384-
my $source_sec = eval { $self->product_obj->default_security_group };
4385-
return () unless $source_sec && grep { $_ eq $source_sec } @clone_groups;
4386-
4436+
local $@;
43874437
my $target_sec = eval { $target_product->default_security_group };
4388-
return () unless $target_sec && !grep { $_ eq $target_sec } @clone_groups;
4438+
return () unless $target_sec && !grep { $_ eq $target_sec } @$group_names;
43894439

43904440
return ($target_sec);
43914441
}

‎Bugzilla/Config/Github.pm‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ sub get_param_list {
1717
{name => 'github_pr_linking_enabled', type => 'b', default => 0},
1818
{name => 'github_pr_signature_secret', type => 't', default => ''},
1919
{name => 'github_push_comment_enabled', type => 'b', default => 0},
20-
{name => 'github_api_token', type => 't', default => ''},
20+
{name => 'github_pr_status_enabled', type => 'b', default => 0},
21+
{name => 'github_api_token', type => 'p', default => ''},
2122
);
2223
return @param_list;
2324
}

‎Bugzilla/WebService/Bug.pm‎

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,20 +1754,31 @@ sub _bug_to_hash {
17541754
foreach my $field (@custom_fields) {
17551755
my $name = $field->name;
17561756
next if !filter_wants($params, $name, ['default', 'custom']);
1757-
if ($field->type == FIELD_TYPE_BUG_ID) {
1758-
$item{$name} = $self->type('int', $bug->$name);
1759-
}
1760-
elsif ($field->type == FIELD_TYPE_DATETIME || $field->type == FIELD_TYPE_DATE) {
1761-
my $value = $bug->$name;
1762-
$item{$name} = defined($value) ? $self->type('dateTime', $value) : undef;
1763-
}
1764-
elsif ($field->type == FIELD_TYPE_MULTI_SELECT) {
1765-
my @values = map { $self->type('string', $_) } @{$bug->$name};
1766-
$item{$name} = \@values;
1767-
}
1768-
else {
1769-
$item{$name} = $self->type('string', $bug->$name);
1770-
}
1757+
$item{$name} = $self->_format_cf_value($field, $bug->$name);
1758+
}
1759+
1760+
# Include stored values for CFs not enabled for this product/component,
1761+
# so callers aren't silently missing data when a bug retains a value after
1762+
# its product/component changed. Multi-select CFs are excluded: they are
1763+
# not preloaded by DB_COLUMNS and each accessor fires a separate SELECT,
1764+
# making them too expensive to include for hidden fields across many bugs.
1765+
my %seen_cf = map { $_->name => 1 } @custom_fields;
1766+
my @hidden_cfs = grep {
1767+
!$seen_cf{$_->name}
1768+
&& $_->type != FIELD_TYPE_EXTENSION
1769+
&& $_->type != FIELD_TYPE_MULTI_SELECT
1770+
} Bugzilla->active_custom_fields({skip_extensions => 1});
1771+
foreach my $field (@hidden_cfs) {
1772+
my $name = $field->name;
1773+
next if !filter_wants($params, $name, ['default', 'custom']);
1774+
my $raw = $bug->$name;
1775+
next if !defined($raw) || $raw eq '';
1776+
1777+
# Single-select fields store the '---' sentinel when unset; treat it as
1778+
# empty so hidden fields left at their default aren't surfaced as noise.
1779+
next if $field->type == FIELD_TYPE_SINGLE_SELECT && $raw eq '---';
1780+
1781+
$item{$name} = $self->_format_cf_value($field, $raw);
17711782
}
17721783

17731784
# Timetracking fields are only sent if the user can see them.
@@ -1823,6 +1834,22 @@ sub _bug_to_hash {
18231834
return \%item;
18241835
}
18251836

1837+
sub _format_cf_value {
1838+
my ($self, $field, $value) = @_;
1839+
if ($field->type == FIELD_TYPE_BUG_ID) {
1840+
return $self->type('int', $value);
1841+
}
1842+
elsif ($field->type == FIELD_TYPE_DATETIME || $field->type == FIELD_TYPE_DATE) {
1843+
return defined($value) ? $self->type('dateTime', $value) : undef;
1844+
}
1845+
elsif ($field->type == FIELD_TYPE_MULTI_SELECT) {
1846+
return [map { $self->type('string', $_) } @{$value}];
1847+
}
1848+
else {
1849+
return $self->type('string', $value);
1850+
}
1851+
}
1852+
18261853
sub _user_to_hash {
18271854
my ($self, $user, $filters, $types, $prefix) = @_;
18281855
my $item = filter $filters,

‎Bugzilla/WebService/Server/REST/Resources/User.pm‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ sub _rest_resources {
2828
{GET => {method => 'login'}},
2929
qr{^/logout$},
3030
{GET => {method => 'logout'}},
31+
qr{^/user/offer_account_by_email$},
32+
{POST => {method => 'offer_account_by_email'}},
3133
qr{^/user$},
3234
{
3335
GET => {method => 'get'},

‎Bugzilla/WebService/User.pm‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,13 @@ and real name.
852852
853853
This is the recommended way to create a Bugzilla account.
854854
855-
=item B<Param>
855+
=item B<REST>
856+
857+
POST /user/offer_account_by_email
858+
859+
The params to include in the POST body are the same as below.
860+
861+
=item B<Params>
856862
857863
=over
858864

‎buglist.cgi‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use Bugzilla::Status;
2929
use Bugzilla::Token;
3030

3131
use Date::Parse;
32-
use List::Util qw(any);
32+
use List::Util qw(any all);
3333
use List::MoreUtils qw(uniq);
3434

3535

@@ -890,9 +890,21 @@ $vars->{'closedstates'} = [map { $_->name } closed_bug_statuses()];
890890

891891
# Determine which status filter tab is active for the toggle UI.
892892
{
893-
my @requested = $params->param('bug_status');
893+
my @requested = $params->param('bug_status');
894+
my @resolution = $params->param('resolution');
894895
if (!@requested || any { $_ eq '__all__' } @requested) {
895-
$vars->{'status_filter'} = 'all';
896+
# resolution=--- (unresolved) only matches open bugs; a resolution list
897+
# with no "---" only matches closed bugs. Either way that's a more
898+
# specific filter than "all", even though bug_status wasn't set.
899+
if (@resolution && all { $_ eq '---' } @resolution) {
900+
$vars->{'status_filter'} = 'open';
901+
}
902+
elsif (@resolution && !(any { $_ eq '---' } @resolution)) {
903+
$vars->{'status_filter'} = 'closed';
904+
}
905+
else {
906+
$vars->{'status_filter'} = 'all';
907+
}
896908
}
897909
elsif (any { $_ eq '__open__' } @requested) {
898910
$vars->{'status_filter'} = 'open';

‎extensions/BMO/lib/Data.pm‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ tie(
155155
"Testing" => [],
156156
"Thunderbird" => [],
157157
"Toolkit" => [],
158+
"Web Compatibility" => [],
158159
"WebExtensions" => [],
159160
},
160161
qr/^cf_due_date$/ => {

‎extensions/BMO/template/en/default/bug/create/create-client-bounty.html.tmpl‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ function validateAndSubmit() {
147147
A short description of the issue being reported.
148148
</div>
149149
<input
150-
required type="text" name="short_desc" id="short_desc" size="80">
150+
required type="text" name="short_desc" id="short_desc" size="80" autocomplete="off">
151151
</div>
152152

153153
<div class="form_section">
@@ -166,7 +166,7 @@ function validateAndSubmit() {
166166
The full URL (hostname/subpage) where the issue exists (if the URL is especially long
167167
please just include it in the comments)
168168
</div>
169-
<input type="text" name="bug_file_loc" id="bug_file_loc" size="80" placeholder="https://">
169+
<input type="text" name="bug_file_loc" id="bug_file_loc" size="80" placeholder="https://" autocomplete="off">
170170
</div>
171171

172172
<div class="form_section">

0 commit comments

Comments
 (0)