diff options
12 files changed, 363 insertions, 68 deletions
diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index 0484ab8f4..3d3a92838 100644 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -4029,8 +4029,8 @@ sub check_can_change_field { return 1; } - # Allow anyone to change comments. - if ($field =~ /^longdesc/) { + # Allow anyone to change comments, or set flags + if ($field =~ /^longdesc/ || $field eq 'flagtypes.name') { return 1; } diff --git a/Bugzilla/Flag.pm b/Bugzilla/Flag.pm index 0828ddc7c..2f6ee526f 100644 --- a/Bugzilla/Flag.pm +++ b/Bugzilla/Flag.pm @@ -312,6 +312,12 @@ sub set_flag { ThrowCodeError('flag_unexpected_object', { 'caller' => ref $obj }); } + # Make sure the user can change flags + my $privs; + $bug->check_can_change_field('flagtypes.name', 0, 1, \$privs) + || ThrowUserError('illegal_change', + { field => 'flagtypes.name', privs => $privs }); + # Update (or delete) an existing flag. if ($params->{id}) { my $flag = $class->check({ id => $params->{id} }); diff --git a/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl b/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl index de97706b0..f72267246 100644 --- a/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl +++ b/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl @@ -41,29 +41,36 @@ <label>Project Flags:</label> </td> <td> - <table id="project-flags"> - [% FOREACH field = project_flags %] - [% NEXT IF NOT user.id AND field.value == "---" %] - <tr id="row_[% field.name FILTER js %]"> - <td> </td> - <td> - <label for="[% field.name FILTER html %]"> - [% field_descs.${field.name} FILTER html %]: - </label> - </td> - <td> - [% PROCESS bug/field.html.tmpl value = bug.${field.name} - editable = user.id - no_tds = 1 %] - [% IF user.id %] - <span id="ro_[% field.name FILTER html %]" class="bz_hidden"> - [% bug.${field.name} FILTER html %] - </span> - [% END %] - </td> - </tr> + [% IF bug.check_can_change_field('flagtypes.name', 0, 1) %] + <table id="project-flags"> + [% FOREACH field = project_flags %] + [% NEXT IF NOT user.id AND field.value == "---" %] + <tr id="row_[% field.name FILTER js %]"> + <td> </td> + <td> + <label for="[% field.name FILTER html %]"> + [% field_descs.${field.name} FILTER html %]: + </label> + </td> + <td> + [% PROCESS bug/field.html.tmpl value = bug.${field.name} + editable = user.id + no_tds = 1 %] + [% IF user.id %] + <span id="ro_[% field.name FILTER html %]" class="bz_hidden"> + [% bug.${field.name} FILTER html %] + </span> + [% END %] + </td> + </tr> + [% END %] + </table> + [% ELSE %] + [% FOREACH field = project_flags %] + [% NEXT IF bug.${field.name} == "---" %] + [% field_descs.${field.name} FILTER html %]: [% bug.${field.name} FILTER html %]<br> + [% END %] [% END %] - </table> </td> </tr> [% END %] @@ -74,34 +81,41 @@ <label>Tracking Flags:</label> </td> <td> - [% IF user.id %] - <span id="edit_tracking_fields_action"> - (<a onclick="bmo_show_tracking_flags()" href="javascript:void(0)">edit</a>) - </span> + [% IF bug.check_can_change_field('flagtypes.name', 0, 1) %] + [% IF user.id %] + <span id="edit_tracking_fields_action"> + (<a onclick="bmo_show_tracking_flags()" href="javascript:void(0)">edit</a>) + </span> + [% END %] + <table id="custom-flags"> + [% FOREACH field = tracking_flags %] + [% NEXT IF NOT user.id AND field.value == "---" %] + <tr id="row_[% field.name FILTER js %]"> + <td> </td> + <td> + <label for="[% field.name FILTER html %]"> + [% field_descs.${field.name} FILTER html %]: + </label> + </td> + <td> + [% PROCESS bug/field.html.tmpl value = bug.${field.name} + editable = user.id + no_tds = 1 %] + [% IF user.id %] + <span id="ro_[% field.name FILTER html %]" class="bz_hidden"> + [% bug.${field.name} FILTER html %] + </span> + [% END %] + </td> + </tr> + [% END %] + </table> + [% ELSE %] + [% FOREACH field = tracking_flags %] + [% NEXT IF bug.${field.name} == "---" %] + [% field_descs.${field.name} FILTER html %]: [% bug.${field.name} FILTER html %]<br> + [% END %] [% END %] - <table id="custom-flags"> - [% FOREACH field = tracking_flags %] - [% NEXT IF NOT user.id AND field.value == "---" %] - <tr id="row_[% field.name FILTER js %]"> - <td> </td> - <td> - <label for="[% field.name FILTER html %]"> - [% field_descs.${field.name} FILTER html %]: - </label> - </td> - <td> - [% PROCESS bug/field.html.tmpl value = bug.${field.name} - editable = user.id - no_tds = 1 %] - [% IF user.id %] - <span id="ro_[% field.name FILTER html %]" class="bz_hidden"> - [% bug.${field.name} FILTER html %] - </span> - [% END %] - </td> - </tr> - [% END %] - </table> </td> </tr> <script type="text/javascript"> diff --git a/extensions/RestrictComments/Config.pm b/extensions/RestrictComments/Config.pm new file mode 100644 index 000000000..bef472cc1 --- /dev/null +++ b/extensions/RestrictComments/Config.pm @@ -0,0 +1,16 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::RestrictComments; + +use strict; + +use constant NAME => 'RestrictComments'; +use constant REQUIRED_MODULES => []; +use constant OPTIONAL_MODULES => []; + +__PACKAGE__->NAME; diff --git a/extensions/RestrictComments/Extension.pm b/extensions/RestrictComments/Extension.pm new file mode 100644 index 000000000..001332a8e --- /dev/null +++ b/extensions/RestrictComments/Extension.pm @@ -0,0 +1,95 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::RestrictComments; + +use strict; +use warnings; + +use base qw(Bugzilla::Extension); + +use Bugzilla::Constants; + +BEGIN { + *Bugzilla::Bug::restrict_comments = \&_bug_restrict_comments; +} + +sub _bug_restrict_comments { + my ($self) = @_; + return $self->{restrict_comments}; +} + +sub bug_check_can_change_field { + my ($self, $args) = @_; + my ($bug, $priv_results) = @$args{qw(bug priv_results)}; + my $user = Bugzilla->user; + + if ($user->id + && $bug->restrict_comments + && !$user->in_group(Bugzilla->params->{'restrict_comments_group'})) + { + push(@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED); + return; + } +} + +sub _can_restrict_comments { + my ($self, $object) = @_; + return unless $object->isa('Bugzilla::Bug'); + $self->{setter_group} ||= Bugzilla->params->{'restrict_comments_enable_group'}; + return Bugzilla->user->in_group($self->{setter_group}); +} + +sub object_end_of_set_all { + my ($self, $args) = @_; + my $object = $args->{object}; + if ($self->_can_restrict_comments($object)) { + my $input = Bugzilla->input_params; + $object->set('restrict_comments', $input->{restrict_comments} ? 1 : undef); + } +} + +sub object_update_columns { + my ($self, $args) = @_; + my ($object, $columns) = @$args{qw(object columns)}; + if ($self->_can_restrict_comments($object)) { + push(@$columns, 'restrict_comments'); + } +} + +sub object_columns { + my ($self, $args) = @_; + my ($class, $columns) = @$args{qw(class columns)}; + if ($class->isa('Bugzilla::Bug')) { + push(@$columns, 'restrict_comments'); + } +} + +sub bug_fields { + my ($self, $args) = @_; + my $fields = $args->{'fields'}; + push (@$fields, 'restrict_comments') +} + +sub config_add_panels { + my ($self, $args) = @_; + my $modules = $args->{panel_modules}; + $modules->{RestrictComments} = "Bugzilla::Extension::RestrictComments::Config"; +} + +sub install_update_db { + my $dbh = Bugzilla->dbh; + + my $field = new Bugzilla::Field({ name => 'restrict_comments' }); + if (!$field) { + Bugzilla::Field->create({ name => 'restrict_comments', description => 'Restrict Comments' }); + } + + $dbh->bz_add_column('bugs', 'restrict_comments', { TYPE => 'BOOLEAN' }); +} + +__PACKAGE__->NAME; diff --git a/extensions/RestrictComments/lib/Config.pm b/extensions/RestrictComments/lib/Config.pm new file mode 100644 index 000000000..33607e680 --- /dev/null +++ b/extensions/RestrictComments/lib/Config.pm @@ -0,0 +1,47 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::RestrictComments::Config; + +use strict; +use warnings; + +use Bugzilla::Config::Common; +use Bugzilla::Group; + +our $sortkey = 510; + +sub get_param_list { + my ($class) = @_; + + my @param_list = ( + { + name => 'restrict_comments_group', + type => 's', + choices => \&_get_all_group_names, + default => '', + checker => \&check_group + }, + { + name => 'restrict_comments_enable_group', + type => 's', + choices => \&_get_all_group_names, + default => '', + checker => \&check_group + }, + ); + + return @param_list; +} + +sub _get_all_group_names { + my @group_names = map {$_->name} Bugzilla::Group->get_all; + unshift(@group_names, ''); + return \@group_names; +} + +1; diff --git a/extensions/RestrictComments/template/en/default/admin/params/restrictcomments.html.tmpl b/extensions/RestrictComments/template/en/default/admin/params/restrictcomments.html.tmpl new file mode 100644 index 000000000..d2a050563 --- /dev/null +++ b/extensions/RestrictComments/template/en/default/admin/params/restrictcomments.html.tmpl @@ -0,0 +1,23 @@ +[%# 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. + #%] + +[% + title = "Restrict Comments" + desc = "Edit Restrict Comments Configuration" +%] + +[% param_descs = +{ + restrict_comments_group => "Users must be a member of this group to " _ + "comment on bug with restricted commenting " _ + "enabled." + + restrict_comments_enable_group => "Members of this group can toggle " _ + "'restrict comments' on bugs." +} +%] diff --git a/extensions/RestrictComments/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl b/extensions/RestrictComments/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl new file mode 100644 index 000000000..0cc24e289 --- /dev/null +++ b/extensions/RestrictComments/template/en/default/hook/bug/edit-after_comment_commit_button.html.tmpl @@ -0,0 +1,21 @@ +[%# 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. + #%] + + +[% RETURN UNLESS user.in_group(Param('restrict_comments_enable_group')) %] + +<div> + <input type="checkbox" name="restrict_comments" id="restrict_comments" + [% " checked" IF bug.restrict_comments %]> + <label for="restrict_comments"> + Restrict commenting on this [% terms.bug %] to users in the + <b>[% Param('restrict_comments_group') FILTER html %]</b> group. + </label> + (<a href="page.cgi?id=restrict_comments_guidelines.html" + target="_blank">guidelines</a>) +</div> diff --git a/extensions/RestrictComments/template/en/default/pages/restrict_comments_guidelines.html.tmpl b/extensions/RestrictComments/template/en/default/pages/restrict_comments_guidelines.html.tmpl new file mode 100644 index 000000000..694681ad7 --- /dev/null +++ b/extensions/RestrictComments/template/en/default/pages/restrict_comments_guidelines.html.tmpl @@ -0,0 +1,62 @@ +[%# 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 Bugzilla %] + +[% PROCESS global/header.html.tmpl + title = "Restrict Comments - Guidelines" +%] + +<h3>Restricting Comments</h3> + +<p> + Some [% terms.bug %] reports are inundated with comments that make it + difficult for developers to conduct technical discussions. Restricting + comments provides the ability for users in the + [%+ Param('restrict_comments_enable_group') FILTER html %] group to prevent + users who are not in the [% Param('restrict_comments_group') FILTER html %] + from making additional comments. +</p> + +<h3>Guidelines</h3> + +<ul> + <li> + Restrictions may be applied to [% terms.bugs %] which are subject to high + volumes of off topic comments, or [% terms.bugs %] which contain high volumes + of violations of [% terms.Bugzilla %] + <a href="page.cgi?id=etiquette.html">etiquette guidelines</a>. + </li> + <li> + Restrictions should not be used as a preemptive measure against comments + which have not yet occurred. + </li> + <li> + Restrictions should not be used to privilege + [%+ Param('restrict_comments_group') FILTER html %] users over other users + in valid disputes/discussions. + </li> +</ul> + +<h3>Impact</h3> + +<ul> + <li> + Users who are not in the [% Param('restrict_comments_group') FILTER html %] + group will not be able to comment on the [% terms.bug %], nor will they be + able to change the value of any field. + </li> + <li> + All users will still be able to CC themselves to the [% terms.bug %]. + </li> + <li> + All users will still be able to vote for the [% terms.bug %]. + </li> +</ul> + +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/bug/comments.html.tmpl b/template/en/default/bug/comments.html.tmpl index 23f024ae1..a876fb081 100644 --- a/template/en/default/bug/comments.html.tmpl +++ b/template/en/default/bug/comments.html.tmpl @@ -170,18 +170,20 @@ [<a class="bz_wrap_link" href="#" onclick="return toggleCommentWrap(this, [% count %])">wrap</a>] [% END %] - [<a class="bz_reply_link" href="#add_comment" - [% IF user.settings.quote_replies.value != 'off' %] - onclick="replyToComment('[% count %]', '[% comment.id %]', '[% comment.author.name || comment.author.nick FILTER html FILTER js %]'); return false;" - [% END %] - >reply</a>] + [% IF bug.check_can_change_field('longdesc', 1, 0) %] + [<a class="bz_reply_link" href="#add_comment" + [% IF user.settings.quote_replies.value != 'off' %] + onclick="replyToComment('[% count %]', '[% comment.id %]', '[% comment.author.name || comment.author.nick FILTER html FILTER js %]'); return false;" + [% END %] + >reply</a>] + [% END %] <script type="text/javascript"><!-- addCollapseLink([% count %], 'Toggle comment display'); // --> </script> </span> [% END %] - [% IF mode == "edit" && user.is_insider %] + [% IF mode == "edit" && user.is_insider && bug.check_can_change_field('longdesc', 0, 1) %] <div class="bz_private_checkbox"> <input type="hidden" value="1" name="defined_isprivate_[% comment.id %]"> diff --git a/template/en/default/bug/edit.html.tmpl b/template/en/default/bug/edit.html.tmpl index 52e5865b8..d57d9641c 100644 --- a/template/en/default/bug/edit.html.tmpl +++ b/template/en/default/bug/edit.html.tmpl @@ -903,7 +903,7 @@ flag_types = bug.flag_types any_flags_requesteeble = bug.any_flags_requesteeble %] [% END %] - [% IF show_more_flags %] + [% IF show_more_flags && bug.check_can_change_field('flagtypes.name', 0, 1) %] <span id="bz_flags_more_container" class="bz_default_hidden"> [% IF !bug_flags_set %]<em>None yet set</em>[% END %] (<a href="#" id="bz_flags_more_action">[% IF !bug_flags_set %]set[% ELSE %]more[% END %] flags</a>) @@ -1090,7 +1090,7 @@ <label for="comment" accesskey="c"><b>Additional <u>C</u>omments</b></label>: - [% IF user.is_insider %] + [% IF user.is_insider && bug.check_can_change_field('longdesc', 0, 1) %] <input type="checkbox" name="comment_is_private" value="1" id="newcommentprivacy" onClick="updateCommentTagControl(this, 'comment')"> @@ -1102,14 +1102,23 @@ <!-- This table keeps the submit button aligned with the box. --> <table><tr><td> - [% INCLUDE global/textarea.html.tmpl - name = 'comment' - id = 'comment' - minrows = 10 - maxrows = 25 - cols = constants.COMMENT_COLS - %] - [% Hook.process("after_comment_textarea", 'bug/edit.html.tmpl') %] + [% IF bug.check_can_change_field('longdesc', 0, 1) %] + [% INCLUDE global/textarea.html.tmpl + name = 'comment' + id = 'comment' + minrows = 10 + maxrows = 25 + cols = constants.COMMENT_COLS + %] + [% Hook.process("after_comment_textarea", 'bug/edit.html.tmpl') %] + [% ELSE %] + <div id="comment"> + <fieldset> + <legend>Note</legend> + You are unable to make an additional comment on this [% terms.bug %]. + </fieldset> + </div> + [% END %] <br> [% PROCESS commit_button id=""%] diff --git a/template/en/default/flag/list.html.tmpl b/template/en/default/flag/list.html.tmpl index e670515e0..16775c714 100644 --- a/template/en/default/flag/list.html.tmpl +++ b/template/en/default/flag/list.html.tmpl @@ -18,7 +18,7 @@ # Contributor(s): Myk Melez <myk@mozilla.org> #%] -[% IF user.id AND !read_only_flags %] +[% IF user.id && !read_only_flags && bug.check_can_change_field('flagtypes.name', 0, 1) %] [%# We list flags by looping twice over the flag types relevant for the bug. # In the first loop, we display existing flags and then, for active types, |