]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 266579 : Users without privs can confirm bugs by assigning to themselves first...
authortravis%sedsystems.ca <>
Fri, 21 Jan 2005 07:22:07 +0000 (07:22 +0000)
committertravis%sedsystems.ca <>
Fri, 21 Jan 2005 07:22:07 +0000 (07:22 +0000)
Patch by LpSolit@gmail.com    r=myk    a=justdave

Bugzilla/Bug.pm
enter_bug.cgi
post_bug.cgi
process_bug.cgi
template/en/default/bug/create/create.html.tmpl
template/en/default/bug/knob.html.tmpl
template/en/default/global/user-error.html.tmpl
template/en/default/global/userselect.html.tmpl

index bad24b589e35d60a32c7b441c39111ff615fd6a7..85f7ee030eb695bca207ab0f73d671eb596db21e 100755 (executable)
@@ -404,20 +404,22 @@ sub user {
     # Display everything as if they have all the permissions in the
     # world; their permissions will get checked when they log in and
     # actually try to make the change.
-    my $privileged = (!Bugzilla->user->id)
-                     || Bugzilla->user->in_group("editbugs")
-                     || Bugzilla->user->id == $self->{'assigned_to'}{'id'}
-                     || (Param('useqacontact') && $self->{'qa_contact'} &&
-                         Bugzilla->user->id == $self->{'qa_contact'}{'id'});
-    my $isreporter = Bugzilla->user->id && 
-                     Bugzilla->user->id == $self->{'reporter'}{'id'};
-
-    my $canedit = $privileged || $isreporter;
-    my $canconfirm = $privileged || Bugzilla->user->in_group("canconfirm");
-
-    $self->{'user'} = {canmove    => $canmove, 
-                       canconfirm => $canconfirm, 
-                       canedit    => $canedit,};
+    my $unknown_privileges = !Bugzilla->user->id
+                             || Bugzilla->user->in_group("editbugs");
+    my $canedit = $unknown_privileges
+                  || Bugzilla->user->id == $self->{'assigned_to'}{'id'}
+                  || (Param('useqacontact')
+                      && $self->{'qa_contact'}
+                      && Bugzilla->user->id == $self->{'qa_contact'}{'id'});
+    my $canconfirm = $unknown_privileges
+                     || Bugzilla->user->in_group("canconfirm");
+    my $isreporter = Bugzilla->user->id
+                     && Bugzilla->user->id == $self->{'reporter'}{'id'};
+
+    $self->{'user'} = {canmove    => $canmove,
+                       canconfirm => $canconfirm,
+                       canedit    => $canedit,
+                       isreporter => $isreporter};
     return $self->{'user'};
 }
 
index 2cbb455ccebe73605a5b49dd6ca92a6571ca4ca9..b159d10313730f8dd67280b303ae0e3ccd39b068 100755 (executable)
@@ -317,7 +317,11 @@ $vars->{'component_'} = \@components;
 $default{'component_'} = formvalue('component');
 
 $vars->{'assigned_to'} = formvalue('assigned_to');
+$vars->{'assigned_to_disabled'} = !UserInGroup('editbugs');
+
 $vars->{'cc'} = formvalue('cc');
+$vars->{'cc_disabled'} = 0;
+
 $vars->{'product'} = $product;
 $vars->{'bug_file_loc'} = formvalue('bug_file_loc', "http://");
 $vars->{'short_desc'} = formvalue('short_desc');
index 3f2d32062f2d59f562066451b8c36e589d437687..40111ff77b6d3e2d74a2fcde4f40fc93e12f9b06 100755 (executable)
@@ -130,7 +130,7 @@ my $sql_product = SqlQuote($::FORM{'product'});
 my $sql_component = SqlQuote($::FORM{'component'});
 
 # Default assignee is the component owner.
-if ($::FORM{'assigned_to'} eq "") {
+if (!UserInGroup("editbugs") || $::FORM{'assigned_to'} eq "") {
     SendSQL("SELECT initialowner FROM components " .
             "WHERE id = $component_id");
     $::FORM{'assigned_to'} = FetchOneColumn();
index 724c709d89ebceb6b37432fefc05d34aa3e90617..54083327be016524163d12184a686ac06bdb8564 100755 (executable)
 #                 Dave Miller <justdave@syndicomm.com>
 #                 Christopher Aillon <christopher@aillon.com>
 #                 Myk Melez <myk@mozilla.org>
+#                 Frédéric Buclin <LpSolit@netscape.net>
 
 use strict;
 
 my $UserInEditGroupSet = -1;
 my $UserInCanConfirmGroupSet = -1;
+my $PrivilegesRequired = 0;
 
 use lib qw(.);
 
@@ -237,14 +239,10 @@ if ((($::FORM{'id'} && $::FORM{'product'} ne $::oldproduct)
         $vars->{'oldvalue'} = $::oldproduct;
         $vars->{'newvalue'} = $::FORM{'product'};
         $vars->{'field'} = 'product';
-        ThrowUserError("illegal_change",
-                       { oldvalue => $::oldproduct,
-                         newvalue => $::FORM{'product'},
-                         field => 'product',
-                       },
-                       "abort");
-    }
+        $vars->{'privs'} = $PrivilegesRequired;
+        ThrowUserError("illegal_change", $vars, "abort");
+    }
+
     CheckFormField(\%::FORM, 'product', \@::legal_product);
     my $prod = $::FORM{'product'};
 
@@ -350,34 +348,18 @@ sub CheckCanChangeField {
     # START DO_NOT_CHANGE
     my ($field, $bugid, $oldvalue, $newvalue) = (@_);
 
-    # Convert email IDs into addresses for $oldvalue
-    if (($field eq "assigned_to") || 
-        ($field eq "reporter") || 
-        ($field eq "qa_contact")) 
-    {
-        if ($oldvalue =~ /^\d+$/) {
-            if ($oldvalue == 0) {
-                $oldvalue = "";
-            } else {
-                $oldvalue = DBID_to_name($oldvalue);
-            }
-        }
-    }
-
     # Return true if they haven't changed this field at all.
     if ($oldvalue eq $newvalue) {
         return 1;
-    }    
-    elsif (trim($oldvalue) eq trim($newvalue)) {
+    } elsif (trim($oldvalue) eq trim($newvalue)) {
         return 1;
     # numeric fields need to be compared using == 
-    } elsif (($field eq "estimated_time" || $field eq "remaining_time") &&
-             $oldvalue == $newvalue) {
+    } elsif (($field eq "estimated_time" || $field eq "remaining_time")
+             && $oldvalue == $newvalue)
+    {
         return 1;
     }
-        
-    
-    
+
     # A resolution change is always accompanied by a status change. So, we 
     # always OK resolution changes; if they really can't do this, we will 
     # notice it when status is checked. 
@@ -390,7 +372,15 @@ sub CheckCanChangeField {
     if ($field =~ /^longdesc/) {
         return 1;
     }
-    
+
+    # Ignore the assigned_to field if the bug is not being reassigned
+    if ($field eq "assigned_to"
+        && $::FORM{'knob'} ne "reassignbycomponent"
+        && $::FORM{'knob'} ne "reassign")
+    {
+        return 1;
+    }
+
     # START DO_NOT_CHANGE
     # Find out whether the user is a member of the "editbugs" and/or
     # "canconfirm" groups. $UserIn*GroupSet are caches of the return value of 
@@ -403,23 +393,31 @@ sub CheckCanChangeField {
         $UserInCanConfirmGroupSet = UserInGroup("canconfirm");
     }
     # END DO_NOT_CHANGE
-    
-    # Allow anyone with "editbugs" to change anything.
+
+    # If the user isn't allowed to change a field, we must tell him who can.
+    # We store the required permission set into the $PrivilegesRequired
+    # variable which gets passed to the error template.
+    #
+    # $PrivilegesRequired = 0 : no privileges required;
+    # $PrivilegesRequired = 1 : the reporter, owner or an empowered user;
+    # $PrivilegesRequired = 2 : the owner or an empowered user;
+    # $PrivilegesRequired = 3 : an empowered user.
+
+    # Allow anyone with "editbugs" privs to change anything.
     if ($UserInEditGroupSet) {
         return 1;
     }
-    
-    # Allow anyone with "canconfirm" to confirm bugs.
-    if ($UserInCanConfirmGroupSet) {
-        if (($field eq "canconfirm") ||
-            (($field eq "bug_status") && 
-             ($oldvalue eq $::unconfirmedstate) &&
-             IsOpenedState($newvalue)))
-        {
-            return 1;
-        }
+
+    # *Only* users with "canconfirm" privs can confirm bugs.
+    if ($field eq "canconfirm"
+        || ($field eq "bug_status"
+            && $oldvalue eq $::unconfirmedstate
+            && IsOpenedState($newvalue)))
+    {
+        $PrivilegesRequired = 3;
+        return $UserInCanConfirmGroupSet;
     }
-    
+
     # START DO_NOT_CHANGE
     # $reporterid, $ownerid and $qacontactid are caches of the results of
     # the call to find out the owner, reporter and qacontact of the current bug.
@@ -431,46 +429,48 @@ sub CheckCanChangeField {
     }    
     # END DO_NOT_CHANGE
 
-    # Allow the owner to change anything.
-    if ($ownerid eq $whoid) {
+    # Allow the owner to change anything else.
+    if ($ownerid == $whoid) {
         return 1;
     }
     
-    # Allow the QA contact to change anything.
-    if (Param('useqacontact') && ($qacontactid eq $whoid)) {
+    # Allow the QA contact to change anything else.
+    if (Param('useqacontact') && ($qacontactid == $whoid)) {
         return 1;
     }
     
-    # The reporter's a more complicated case...
-    if ($reporterid eq $whoid) {
-        # Reporter may not:
-        # - confirm his own bugs (this assumes he doesn't have canconfirm, or we
-        #   would have returned "1" earlier)
-        if (($field eq "bug_status") && 
-            ($oldvalue eq $::unconfirmedstate) &&
-             IsOpenedState($newvalue))
-        {
+    # The reporter is a more complicated case...
+    if ($reporterid == $whoid) {
+        $PrivilegesRequired = 2;
+
+        # The reporter may not:
+        # - reassign bugs, unless the bugs are assigned to him;
+        #   in that case we will have already returned 1 above
+        #   when checking for the owner of the bug.
+        if ($field eq "assigned_to") {
             return 0;
         }
-        
-        # - change the target milestone            
-        if  ($field eq "target_milestone")  {
+        # - change the QA contact
+        if ($field eq "qa_contact") {
             return 0;
-        }       
-        
+        }
+        # - change the target milestone
+        if ($field eq "target_milestone") {
+            return 0;
+        }
         # - change the priority (unless he could have set it originally)
-        if (($field eq "priority") &&
-            !Param('letsubmitterchoosepriority'))
+        if ($field eq "priority"
+            && !Param('letsubmitterchoosepriority'))
         {
             return 0;
         }
-        
-        # Allow reporter to change anything else.
+        # Allow the reporter to change anything else.
         return 1;
     }
-  
+
     # If we haven't returned by this point, then the user doesn't have the
     # necessary permissions to change this field.
+    $PrivilegesRequired = 1;
     return 0;
 }
 
@@ -619,19 +619,23 @@ sub ChangeStatus {
         } else {
             $::query .= "bug_status = " . SqlQuote($str);
         }
-        $::FORM{'bug_status'} = $str; # Used later for call to
-                                      # CheckCanChangeField to make sure this
-                                      # is really kosher.
+        # If bugs are reassigned and their status is "UNCONFIRMED", they
+        # should keep this status instead of "NEW" as suggested here.
+        # This point is checked for each bug later in the code.
+        $::FORM{'bug_status'} = $str;
     }
 }
 
 sub ChangeResolution {
     my ($str) = (@_);
-    if (!$::FORM{'dontchange'} ||
-       ($str ne $::FORM{'dontchange'})) {
+    if (!$::FORM{'dontchange'}
+        || $str ne $::FORM{'dontchange'})
+    {
         DoComma();
         $::query .= "resolution = " . SqlQuote($str);
-        $::FORM{'resolution'} = $str; # Used later by CheckCanChangeField
+        # We define this variable here so that customized installations
+        # may set rules based on the resolution in CheckCanChangeField.
+        $::FORM{'resolution'} = $str;
     }
 }
 
@@ -761,18 +765,6 @@ if (Param("usebugaliases") && defined($::FORM{'alias'})) {
     }
 }
 
-if (defined $::FORM{'qa_contact'}) {
-    my $name = trim($::FORM{'qa_contact'});
-    if ($name ne $::FORM{'dontchange'}) {
-        my $id = 0;
-        if ($name ne "") {
-            $id = DBNameToIdAndCheck($name);
-        }
-        DoComma();
-        $::query .= "qa_contact = $id";
-    }
-}
-
 # jeff.hedlund@matrixsi.com time tracking data processing:
 if (UserInGroup(Param('timetrackinggroup'))) {
     foreach my $field ("estimated_time", "remaining_time") {
@@ -874,6 +866,26 @@ if (defined $::FORM{newcc} || defined $::FORM{removecc} || defined $::FORM{massc
     }
 }
 
+# Store the new assignee and QA contact IDs (if any). This is the
+# only way to keep these informations when bugs are reassigned by
+# component as $::FORM{'assigned_to'} and $::FORM{'qa_contact'}
+# are not the right fields to look at.
+
+my $assignee;
+my $qacontact;
+
+if (defined $::FORM{'qa_contact'}
+    && $::FORM{'knob'} ne "reassignbycomponent")
+{
+    $qacontact = 0;
+    my $name = trim($::FORM{'qa_contact'});
+    # The QA contact cannot be deleted from show_bug.cgi for a single bug!
+    if ($name ne $::FORM{'dontchange'}) {
+        $qacontact = DBNameToIdAndCheck($name) if ($name ne "");
+        DoComma();
+        $::query .= "qa_contact = $qacontact";
+    }
+}
 
 CheckFormFieldDefined(\%::FORM, 'knob');
 SWITCH: for ($::FORM{'knob'}) {
@@ -907,19 +919,20 @@ SWITCH: for ($::FORM{'knob'}) {
                 ThrowUserError("resolving_remaining_time");
             }
         }
-        
+        # Check here, because its the only place we require the resolution
+        CheckFormField(\%::FORM, 'resolution', \@::settable_resolution);
+
         # don't resolve as fixed while still unresolved blocking bugs
-        if (Param("noresolveonopenblockers") && ($::FORM{'resolution'} eq 'FIXED')) {
-           my @dependencies = CountOpenDependencies(@idlist);
-           if (scalar @dependencies > 0) {
-               ThrowUserError("still_unresolved_bugs", 
+        if (Param("noresolveonopenblockers")
+            && $::FORM{'resolution'} eq 'FIXED')
+        {
+            my @dependencies = CountOpenDependencies(@idlist);
+            if (scalar @dependencies > 0) {
+                ThrowUserError("still_unresolved_bugs",
                                { dependencies     => \@dependencies,
                                  dependency_count => scalar @dependencies });
-            }          
+            }
         }
-
-        # Check here, because its the only place we require the resolution
-        CheckFormField(\%::FORM, 'resolution', \@::settable_resolution);
         ChangeStatus('RESOLVED');
         ChangeResolution($::FORM{'resolution'});
         last SWITCH;
@@ -930,12 +943,13 @@ SWITCH: for ($::FORM{'knob'}) {
         }
         ChangeStatus('NEW');
         DoComma();
-        if (!defined$::FORM{'assigned_to'} ||
-            trim($::FORM{'assigned_to'}) eq "") {
+        if (!defined $::FORM{'assigned_to'}
+            || trim($::FORM{'assigned_to'}) eq "")
+        {
             ThrowUserError("reassign_to_empty");
         }
-        my $newid = DBNameToIdAndCheck(trim($::FORM{'assigned_to'}));
-        $::query .= "assigned_to = $newid";
+        $assignee = DBNameToIdAndCheck(trim($::FORM{'assigned_to'}));
+        $::query .= "assigned_to = $assignee";
         last SWITCH;
     };
     /^reassignbycomponent$/  && CheckonComment( "reassignbycomponent" ) && do {
@@ -951,14 +965,13 @@ SWITCH: for ($::FORM{'knob'}) {
         ChangeStatus('NEW');
         SendSQL("SELECT initialowner FROM components " .
                 "WHERE components.id = $comp_id");
-        my $newid = FetchOneColumn();
+        $assignee = FetchOneColumn();
         DoComma();
-        $::query .= "assigned_to = $newid";
+        $::query .= "assigned_to = $assignee";
         if (Param("useqacontact")) {
             SendSQL("SELECT initialqacontact FROM components " .
                     "WHERE components.id = $comp_id");
-            my $qacontact = FetchOneColumn();
-            $qacontact = 0 unless (defined $qacontact && $qacontact != 0);
+            $qacontact = FetchOneColumn() || 0;
             DoComma();
             $::query .= "qa_contact = $qacontact";
         }
@@ -1130,8 +1143,6 @@ foreach my $id (@idlist) {
             "group_control_map AS oldcontrolmap READ, " .
             "group_control_map AS newcontrolmap READ, " .
             "group_control_map READ");
-    my @oldvalues = SnapShotBug($id);
-    my %oldhash;
     # Fun hack.  @::log_columns only contains the component_id,
     # not the name (since bug 43600 got fixed).  So, we need to have
     # this id ready for the loop below, otherwise anybody can
@@ -1143,31 +1154,58 @@ foreach my $id (@idlist) {
         $::FORM{'component_id'} = 
                             get_component_id($product_id, $::FORM{'component'});
     }
-    
+
+    # It may sound crazy to set %formhash for each bug as $::FORM{}
+    # will not change, but %formhash is modified below and we prefer
+    # to set it again.
     my $i = 0;
+    my @oldvalues = SnapShotBug($id);
+    my %oldhash;
+    my %formhash;
     foreach my $col (@::log_columns) {
         # Consider NULL db entries to be equivalent to the empty string
-        $oldvalues[$i] = '' unless defined($oldvalues[$i]);
+        $oldvalues[$i] = '' unless defined $oldvalues[$i];
         $oldhash{$col} = $oldvalues[$i];
-        if (exists $::FORM{$col}) {
-            if (!CheckCanChangeField($col, $id, $oldvalues[$i], $::FORM{$col})) {
-                # More fun hacking... don't display component_id
-                my $vars;
-                if ($col eq 'component_id') {
-                    $vars->{'oldvalue'} = 
-                                   get_component_name($oldhash{'component_id'});
-                    $vars->{'newvalue'} = $::FORM{'component'};
-                    $vars->{'field'} = 'component';
-                }
-                else {
-                    $vars->{'oldvalue'} = $oldvalues[$i];
-                    $vars->{'newvalue'} = $::FORM{$col};
-                    $vars->{'field'} = $col;
-                }
-                ThrowUserError("illegal_change", $vars, "abort");
+        $formhash{$col} = $::FORM{$col} if defined $::FORM{$col};
+        $i++;
+    }
+    # If the user is reassigning bugs, we need to:
+    # - convert $newhash{'assigned_to'} and $newhash{'qa_contact'}
+    #   email addresses into their corresponding IDs;
+    # - update $newhash{'bug_status'} to its real state if the bug
+    #   is in the unconfirmed state.
+    $formhash{'qa_contact'} = $qacontact if Param('useqacontact');
+    if ($::FORM{'knob'} eq 'reassignbycomponent'
+        || $::FORM{'knob'} eq 'reassign')
+    {
+        $formhash{'assigned_to'} = $assignee;
+        if ($oldhash{'bug_status'} eq $::unconfirmedstate) {
+            $formhash{'bug_status'} = $oldhash{'bug_status'};
+        }
+    }
+    foreach my $col (@::log_columns) {
+        if (exists $formhash{$col}
+            && !CheckCanChangeField($col, $id, $oldhash{$col}, $formhash{$col}))
+        {
+            my $vars;
+            if ($col eq 'component_id') {
+                # Display the component name
+                $vars->{'oldvalue'} = get_component_name($oldhash{$col});
+                $vars->{'newvalue'} = $::FORM{'component'};
+                $vars->{'field'} = 'component';
+            } elsif ($col eq 'assigned_to' || $col eq 'qa_contact') {
+                # Display the assignee or QA contact email address
+                $vars->{'oldvalue'} = DBID_to_name($oldhash{$col});
+                $vars->{'newvalue'} = DBID_to_name($formhash{$col});
+                $vars->{'field'} = $col;
+            } else {
+                $vars->{'oldvalue'} = $oldhash{$col};
+                $vars->{'newvalue'} = $formhash{$col};
+                $vars->{'field'} = $col;
             }
+            $vars->{'privs'} = $PrivilegesRequired;
+            ThrowUserError("illegal_change", $vars, "abort");
         }
-        $i++;
     }
 
     # When editing multiple bugs, users can specify a list of keywords to delete
@@ -1184,6 +1222,7 @@ foreach my $id (@idlist) {
         $vars->{'oldvalue'} = $oldhash{keywords};
         $vars->{'newvalue'} = "no keywords";
         $vars->{'field'} = "keywords";
+        $vars->{'privs'} = $PrivilegesRequired;
         ThrowUserError("illegal_change", $vars, "abort");
     }
 
index dd0d4f13c6d78416fc863e9970b0239b2a22e3ce..d22ab8dc69bfbdc379cc91e7fe86d796c04d5514 100644 (file)
@@ -187,6 +187,7 @@ function set_assign_to() {
       [% INCLUDE global/userselect.html.tmpl
          name => "assigned_to"
          value => assigned_to
+         disabled => assigned_to_disabled
          size => 32
          emptyok => 1
        %]
@@ -200,6 +201,7 @@ function set_assign_to() {
       [% INCLUDE global/userselect.html.tmpl
          name => "cc"
          value => cc
+         disabled => cc_disabled
          size => 45
          emptyok => 1
          multiple => 5
index cc8ca32b5162695243d919efeb95722896f70e59..035db1ae515014beab46131ff2b3297d8831cdff 100644 (file)
     [% knum = knum + 1 %]
   [% END %]
 
-  [% IF bug.user.canedit %]
-    [% IF bug.isopened %]
-      [% IF bug.bug_status != "ASSIGNED" && bug.user.canconfirm %]
-        <input type="radio" id="knob-accept" name="knob" value="accept">
-        <label for="knob-accept">
-          Accept [% terms.bug %] (
-          [% IF bug.isunconfirmed %]confirm [% terms.bug %], [% END %]change
-          status to <b>ASSIGNED</b>)
-        </label>
-        <br>
-        [% knum = knum + 1 %]
-      [% END %]
+  [% IF bug.isopened && bug.bug_status != "ASSIGNED" && bug.user.canedit
+        && (!bug.isunconfirmed || bug.user.canconfirm) %]
+    <input type="radio" id="knob-accept" name="knob" value="accept">
+    <label for="knob-accept">
+      Accept [% terms.bug %] (
+      [% IF bug.isunconfirmed %]confirm [% terms.bug %], [% END %]change
+      status to <b>ASSIGNED</b>)
+    </label>
+    <br>
+    [% knum = knum + 1 %]
+  [% END %]
 
+  [% IF bug.user.canedit || bug.user.isreporter %]
+    [% IF bug.isopened %]
       [% IF bug.resolution %]
         <input type="radio" id="knob-clear" name="knob" value="clearresolution">
         <label for="knob-clear">
       <br>
       [% knum = knum + 1 %]
 
-      <input type="radio" id="knob-reassign" name="knob" value="reassign">
-      <label for="knob-reassign">
-        <a href="page.cgi?id=fields.html#assigned_to">Reassign</a> 
-        [% terms.bug %] to
-      </label>
-      [% safe_assigned_to = FILTER js; bug.assigned_to.login; END %]
-      [% INCLUDE global/userselect.html.tmpl
-           name => "assigned_to"
-           value => bug.assigned_to.login
-           size => 32
-           onchange => "if ((this.value != '$safe_assigned_to') && (this.value != '')) {
-                          document.changeform.knob[$knum].checked=true;
-                        }"
-      %]
-      <br>
-      [% IF bug.isunconfirmed && bug.user.canconfirm %]
-        &nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" id="andconfirm" name="andconfirm">
-        <label for="andconfirm">
-          and confirm [% terms.bug %] (change status to <b>NEW</b>)
+      [% IF bug.user.canedit %]
+        <input type="radio" id="knob-reassign" name="knob" value="reassign">
+        <label for="knob-reassign">
+          <a href="page.cgi?id=fields.html#assigned_to">Reassign</a> 
+          [% terms.bug %] to
         </label>
+        [% safe_assigned_to = FILTER js; bug.assigned_to.login; END %]
+        [% INCLUDE global/userselect.html.tmpl
+             name => "assigned_to"
+             value => bug.assigned_to.login
+             size => 32
+             onchange => "if ((this.value != '$safe_assigned_to') && (this.value != '')) {
+                               document.changeform.knob[$knum].checked=true;
+                          }"
+        %]
         <br>
-      [% END %]
-      [% knum = knum + 1 %]
+        [% IF bug.isunconfirmed && bug.user.canconfirm %]
+          &nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" id="andconfirm" name="andconfirm">
+          <label for="andconfirm">
+            and confirm [% terms.bug %] (change status to <b>NEW</b>)
+          </label>
+          <br>
+        [% END %]
+        [% knum = knum + 1 %]
 
-      <input type="radio" id="knob-reassign-cmp" name="knob" value="reassignbycomponent">
-      <label for="knob-reassign-cmp">
-        Reassign [% terms.bug %] to owner
-        [% " and QA contact" IF Param('useqacontact') %]
-        of selected component
-      </label>
-      <br>
-      [% IF bug.isunconfirmed && bug.user.canconfirm %]
-        &nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" id="compconfirm" name="compconfirm">
-        <label for="compconfirm">
-          and confirm [% terms.bug %] (change status to <b>NEW</b>)
+        <input type="radio" id="knob-reassign-cmp" name="knob" value="reassignbycomponent">
+        <label for="knob-reassign-cmp">
+          Reassign [% terms.bug %] to owner
+          [% " and QA contact" IF Param('useqacontact') %]
+          of selected component
         </label>
         <br>
+        [% IF bug.isunconfirmed && bug.user.canconfirm %]
+          &nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" id="compconfirm" name="compconfirm">
+          <label for="compconfirm">
+            and confirm [% terms.bug %] (change status to <b>NEW</b>)
+          </label>
+          <br>
+        [% END %]
+        [% knum = knum + 1 %]
       [% END %]
-      [% knum = knum + 1 %]
     [% ELSE %]
       [% IF bug.resolution != "MOVED" ||
            (bug.resolution == "MOVED" && bug.user.canmove) %]
index aa4a432863de99354f885f5be631aa11d1853e39..5ea789a2fbf88fcb73a983674b7230210f27aec0 100644 (file)
     You tried to change the 
     <strong>[% field_descs.$field FILTER html %]</strong> field 
     from <em>[% oldvalue FILTER html %]</em> to 
-    <em>[% newvalue FILTER html %]</em>, 
-    but only the owner or submitter of the [% terms.bug %], or a 
-    sufficiently empowered user, may change that field.
-  
+    <em>[% newvalue FILTER html %]</em>, but only
+    [% IF privs < 3 %]
+      the owner
+      [% IF privs < 2 %] or reporter [% END %]
+      of the [% terms.bug %], or
+    [% END %]
+    a sufficiently empowered user may change that field.
+
   [% ELSIF error == "illegal_changed_in_last_x_days" %]
     [% title = "Your Search Makes No Sense" %]
     The <em>Changed in last ___ days</em> field must be a simple number. 
index 2162e260159c28a15a7c360dc835979eda8563d8..91692fd2120eeaef78c59cf78ff144e695756018 100644 (file)
@@ -20,6 +20,7 @@
   # name: mandatory; field name
   # value: optional; default field value/selection
   # onchange: optional; onchange attribute value
+  # disabled: optional; if true, the field is disabled
   # accesskey: optional, input only; accesskey attribute value
   # size: optional, input only; size attribute value
   # emptyok: optional, select only;  if true, prepend menu option to start of select
@@ -30,6 +31,7 @@
 [% IF Param("usemenuforusers") %]
 <select name="[% name FILTER html %]"
   [% IF onchange %] onchange="[% onchange FILTER html %]" [% END %]
+  [% IF disabled %] disabled="[% disabled FILTER html %]" [% END %]
   [% IF accesskey %] accesskey="[% accesskey FILTER html %]" [% END %]
   [% IF multiple %] multiple="multiple" size="[% multiple FILTER html %]" [% END %]
 >
 <input
   name="[% name FILTER html %]"
   value="[% value FILTER html %]"
+  [% IF onchange %] onchange="[% onchange FILTER html %]" [% END %]
+  [% IF disabled %] disabled="[% disabled FILTER html %]" [% END %]
   [% IF accesskey %] accesskey="[% accesskey FILTER html %]" [% END %]
   [% IF size %] size="[% size FILTER html %]" [% END %]
-  [% IF onchange %] onchange="[% onchange FILTER html %]" [% END %]
 >
 [% END %]