Commit e9a32920 authored by terry%mozilla.org's avatar terry%mozilla.org

Major spankage. Added a new state, UNCONFIRMED. Added new groups,

"editbugs" and "canconfirm". People without these states are now much more limited in what they can do. For backwards compatability, by default all users will have the editbugs and canconfirm bits on them. Installing this changes as is should only have one major visible effect -- an UNCONFIRMED state will appear in the query page. But no bugs will become in that state, until you tweak some of the new voting-related parameters you'll find when editing products.
parent 3c0ea11d
......@@ -490,6 +490,9 @@ sub BuildPulldown {
if ($tag eq $default) {
$selectpart = " SELECTED";
}
if (!defined $desc) {
$desc = $tag;
}
$entry .= qq{<OPTION$selectpart VALUE="$tag">$desc\n};
}
$entry .= qq{</SELECT>};
......@@ -515,28 +518,31 @@ sub quietly_check_login() {
$::usergroupset = '0';
my $loginok = 0;
$::disabledreason = '';
$::userid = 0;
if (defined $::COOKIE{"Bugzilla_login"} &&
defined $::COOKIE{"Bugzilla_logincookie"}) {
ConnectToDatabase();
if (!defined $ENV{'REMOTE_HOST'}) {
$ENV{'REMOTE_HOST'} = $ENV{'REMOTE_ADDR'};
}
SendSQL("select profiles.groupset, profiles.login_name, " .
SendSQL("SELECT profiles.userid, profiles.groupset, " .
"profiles.login_name, " .
"profiles.login_name = " .
SqlQuote($::COOKIE{"Bugzilla_login"}) .
" and profiles.cryptpassword = logincookies.cryptpassword " .
"and logincookies.hostname = " .
" AND profiles.cryptpassword = logincookies.cryptpassword " .
"AND logincookies.hostname = " .
SqlQuote($ENV{"REMOTE_HOST"}) .
", profiles.disabledtext " .
" from profiles,logincookies where logincookies.cookie = " .
" FROM profiles, logincookies WHERE logincookies.cookie = " .
SqlQuote($::COOKIE{"Bugzilla_logincookie"}) .
" and profiles.userid = logincookies.userid");
" AND profiles.userid = logincookies.userid");
my @row;
if (@row = FetchSQLData()) {
my ($groupset, $loginname, $ok, $disabledtext) = (@row);
my ($userid, $groupset, $loginname, $ok, $disabledtext) = (@row);
if ($ok) {
if ($disabledtext eq '') {
$loginok = 1;
$::userid = $userid;
$::usergroupset = $groupset;
$::COOKIE{"Bugzilla_login"} = $loginname; # Makes sure case
# is in
......@@ -730,6 +736,7 @@ name=PleaseMailAPassword>
# Update the timestamp on our logincookie, so it'll keep on working.
SendSQL("update logincookies set lastused = null where cookie = $::COOKIE{'Bugzilla_logincookie'}");
return $::userid;
}
......@@ -785,6 +792,37 @@ sub PutFooter {
}
sub CheckIfVotedConfirmed {
my ($id, $who) = (@_);
SendSQL("SELECT bugs.votes, bugs.bug_status, products.votestoconfirm, " .
" bugs.everconfirmed " .
"FROM bugs, products " .
"WHERE bugs.bug_id = $id AND products.product = bugs.product");
my ($votes, $status, $votestoconfirm, $everconfirmed) = (FetchSQLData());
if ($votes >= $votestoconfirm && $status eq $::unconfirmedstate) {
SendSQL("UPDATE bugs SET bug_status = 'NEW', everconfirmed = 1 " .
"WHERE bug_id = $id");
my $fieldid = GetFieldID("bug_status");
SendSQL("INSERT INTO bugs_activity " .
"(bug_id,who,bug_when,fieldid,oldvalue,newvalue) VALUES " .
"($id,$who,now(),$fieldid,'$::unconfirmedstate','NEW')");
if (!$everconfirmed) {
$fieldid = GetFieldID("everconfirmed");
SendSQL("INSERT INTO bugs_activity " .
"(bug_id,who,bug_when,fieldid,oldvalue,newvalue) VALUES " .
"($id,$who,now(),$fieldid,'0','1')");
}
AppendComment($id, DBID_to_name($who),
"*** This bug has been confirmed by popular vote. ***");
print "<TABLE BORDER=1><TD><H2>Bug $id has been confirmed by votes.</H2>\n";
system("./processmail", $id);
print "<TD><A HREF=\"show_bug.cgi?id=$id\">Go To BUG# $id</A></TABLE>\n";
}
}
sub DumpBugActivity {
my ($id, $starttime) = (@_);
my $datepart = "";
......@@ -885,7 +923,7 @@ sub GetCommandMenu {
$html .= ", <a href=editparams.cgi>parameters</a>";
$html .= ", <a href=sanitycheck.cgi><NOBR>sanity check</NOBR></a>";
}
if (UserInGroup("editusers")) {
if (UserInGroup("editusers") || UserInGroup("editgroupmembers")) {
$html .= ", <a href=editusers.cgi>users</a>";
}
if (UserInGroup("editcomponents")) {
......
......@@ -31,13 +31,13 @@ sub bug_form_pl_sillyness {
$zz = %::components;
$zz = %::prodmaxvotes;
$zz = %::versions;
$zz = @::legal_keywords;
$zz = @::legal_opsys;
$zz = @::legal_platform;
$zz = @::legal_product;
$zz = @::legal_priority;
$zz = @::legal_resolution_no_dup;
$zz = @::legal_severity;
$zz = @::keywordsbyname;
}
my %knownattachments;
......@@ -194,14 +194,27 @@ if (@row = FetchSQLData()) {
exit;
}
my $assignedtoid = $bug{'assigned_to'};
my $reporterid = $bug{'reporter'};
my $qacontactid = $bug{'qa_contact'};
$bug{'assigned_to'} = DBID_to_name($bug{'assigned_to'});
$bug{'reporter'} = DBID_to_name($bug{'reporter'});
print qq{<FORM NAME="changeform" METHOD="POST" ACTION="process_bug.cgi">\n};
# foreach my $i (sort(keys(%bug))) {
# my $q = value_quote($bug{$i});
# print qq{<INPUT TYPE="HIDDEN" NAME="orig-$i" VALUE="$q">\n};
# }
$bug{'long_desc'} = GetLongDescription($id);
my $longdesclength = length($bug{'long_desc'});
GetVersionTable();
#
# These should be read from the database ...
#
......@@ -229,11 +242,9 @@ if (defined $URL && $URL ne "none" && $URL ne "NULL" && $URL ne "") {
}
print "
<FORM NAME=changeform METHOD=POST ACTION=\"process_bug.cgi\">
<INPUT TYPE=HIDDEN NAME=\"delta_ts\" VALUE=\"$bug{'delta_ts'}\">
<INPUT TYPE=HIDDEN NAME=\"longdesclength\" VALUE=\"$longdesclength\">
<INPUT TYPE=HIDDEN NAME=\"id\" VALUE=$id>
<INPUT TYPE=HIDDEN NAME=\"was_assigned_to\" VALUE=\"$bug{'assigned_to'}\">
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0><TR>
<TD ALIGN=RIGHT><B>Bug#:</B></TD><TD><A HREF=\"show_bug.cgi?id=$bug{'bug_id'}\">$bug{'bug_id'}</A></TD>
<TD ALIGN=RIGHT><B><A HREF=\"bug_status.html#rep_platform\">Platform:</A></B></TD>
......@@ -449,50 +460,73 @@ my $knum = 1;
my $status = $bug{'bug_status'};
if ($status eq "NEW" || $status eq "ASSIGNED" || $status eq "REOPENED") {
if ($status ne "ASSIGNED") {
print "<INPUT TYPE=radio NAME=knob VALUE=accept>";
print "Accept bug (change status to <b>ASSIGNED</b>)<br>";
$knum++;
}
if ($bug{'resolution'} ne "") {
print "<INPUT TYPE=radio NAME=knob VALUE=clearresolution>\n";
print "Clear the resolution (remove the current resolution of\n";
print "<b>$bug{'resolution'}</b>)<br>\n";
my $canedit = UserInGroup("editbugs");
my $canconfirm;
if ($status eq $::unconfirmedstate) {
$canconfirm = UserInGroup("canconfirm");
if ($canedit || $canconfirm) {
print "<INPUT TYPE=radio NAME=knob VALUE=confirm>";
print "Confirm bug (change status to <b>NEW</b>)<br>";
$knum++;
}
print "<INPUT TYPE=radio NAME=knob VALUE=resolve>
}
if ($::userid && ($canedit || $::userid == $assignedtoid ||
$::userid == $reporterid || $::userid == $qacontactid)) {
if (IsOpenedState($status)) {
if ($status ne "ASSIGNED") {
print "<INPUT TYPE=radio NAME=knob VALUE=accept>";
my $extra = "";
if ($status eq $::unconfirmedstate && ($canconfirm || $canedit)) {
$extra = "confirm bug, ";
}
print "Accept bug (${extra}change status to <b>ASSIGNED</b>)<br>";
$knum++;
}
if ($bug{'resolution'} ne "") {
print "<INPUT TYPE=radio NAME=knob VALUE=clearresolution>\n";
print "Clear the resolution (remove the current resolution of\n";
print "<b>$bug{'resolution'}</b>)<br>\n";
$knum++;
}
print "<INPUT TYPE=radio NAME=knob VALUE=resolve>
Resolve bug, changing <A HREF=\"bug_status.html\">resolution</A> to
<SELECT NAME=resolution
ONCHANGE=\"document.changeform.knob\[$knum\].checked=true\">
$resolution_popup</SELECT><br>\n";
$knum++;
print "<INPUT TYPE=radio NAME=knob VALUE=duplicate>
$knum++;
print "<INPUT TYPE=radio NAME=knob VALUE=duplicate>
Resolve bug, mark it as duplicate of bug #
<INPUT NAME=dup_id SIZE=6 ONCHANGE=\"document.changeform.knob\[$knum\].checked=true\"><br>\n";
$knum++;
my $assign_element = "<INPUT NAME=\"assigned_to\" SIZE=32 ONCHANGE=\"document.changeform.knob\[$knum\].checked=true\" VALUE=\"$bug{'assigned_to'}\">";
$knum++;
my $assign_element = "<INPUT NAME=\"assigned_to\" SIZE=32 ONCHANGE=\"document.changeform.knob\[$knum\].checked=true\" VALUE=\"$bug{'assigned_to'}\">";
print "<INPUT TYPE=radio NAME=knob VALUE=reassign>
print "<INPUT TYPE=radio NAME=knob VALUE=reassign>
<A HREF=\"bug_status.html#assigned_to\">Reassign</A> bug to
$assign_element
<br>\n";
$knum++;
print "<INPUT TYPE=radio NAME=knob VALUE=reassignbycomponent>
if ($status eq $::unconfirmedstate && ($canconfirm || $canedit)) {
print "&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE=checkbox NAME=andconfirm> and confirm bug (change status to <b>NEW</b>)<BR>";
}
$knum++;
print "<INPUT TYPE=radio NAME=knob VALUE=reassignbycomponent>
Reassign bug to owner of selected component<br>\n";
$knum++;
} else {
print "<INPUT TYPE=radio NAME=knob VALUE=reopen> Reopen bug<br>\n";
$knum++;
if ($status eq "RESOLVED") {
print "<INPUT TYPE=radio NAME=knob VALUE=verify>
Mark bug as <b>VERIFIED</b><br>\n";
$knum++;
}
if ($status ne "CLOSED") {
print "<INPUT TYPE=radio NAME=knob VALUE=close>
Mark bug as <b>CLOSED</b><br>\n";
} else {
print "<INPUT TYPE=radio NAME=knob VALUE=reopen> Reopen bug<br>\n";
$knum++;
if ($status eq "RESOLVED") {
print "<INPUT TYPE=radio NAME=knob VALUE=verify>
Mark bug as <b>VERIFIED</b><br>\n";
$knum++;
}
if ($status ne "CLOSED") {
print "<INPUT TYPE=radio NAME=knob VALUE=close>
Mark bug as <b>CLOSED</b><br>\n";
$knum++;
}
}
}
......
......@@ -30,7 +30,9 @@
The <B>status</B> and <B>resolution</B> field define and track the
life cycle of a bug.
<a name="status">
<p>
</a>
<TABLE BORDER=1 CELLPADDING=4>
<TR ALIGN=CENTER VALIGN=TOP>
......@@ -42,7 +44,12 @@ certain status transitions are allowed.
<TD>The <b>resolution</b> field indicates what happened to this bug.
<TR VALIGN=TOP><TD>
<DL><DT><B>NEW</B>
<DL><DT><B>UNCONFIRMED</B>
<DD> This bug has recently been added to the database. Nobody has
validated that this bug is true. Users who have the "canconfirm"
permission set may confirm this bug, changing its state to NEW.
Or, it may be directly resolved and marked RESOLVED.
<DT><B>NEW</B>
<DD> This bug has recently been added to the assignee's list of bugs
and must be processed. Bugs in this state may be accepted, and
become <B>ASSIGNED</B>, passed on to someone else, and remain
......@@ -60,8 +67,8 @@ certain status transitions are allowed.
</DL>
<TD>
<DL>
<DD> No resolution yet. All bugs which are <B>NEW</B> or
<B>ASSIGNED</B> have the resolution set to blank. All other bugs
<DD> No resolution yet. All bugs which are in one of these "open" states
have the resolution set to blank. All other bugs
will be marked with one of the following resolutions.
</DL>
......@@ -188,8 +195,7 @@ searching for bugs that have been resolved or verified, remember to set the
status field appropriately.
<hr>
<address><a href="http://home.netscape.com/people/terry/">Terry Weissman &lt;terry@netscape.com&gt;</a></address>
<!-- hhmts start -->
Last modified: Thu Jan 13 16:22:39 2000
Last modified: Wed Feb 16 20:41:24 2000
<!-- hhmts end -->
</body> </html>
......@@ -33,6 +33,7 @@ use Date::Parse;
sub sillyness {
my $zz;
$zz = $::defaultqueryname;
$zz = $::unconfirmedstate;
$zz = @::components;
$zz = @::default_column_list;
$zz = @::keywordsbyname;
......@@ -824,6 +825,14 @@ my $dotweak = defined $::FORM{'tweak'};
if ($dotweak) {
confirm_login();
if (!UserInGroup("canedit")) {
print qq{
Sorry; you do not have sufficient priviledges to edit a bunch of bugs
at once.
};
PutFooter();
exit();
}
} else {
quietly_check_login();
}
......@@ -979,7 +988,7 @@ if ($splitheader) {
$tablestart .= "</TR>\n<TR><TD></TD>";
}
for (my $i=1-$pass ; $i<@th ; $i += 2) {
my $h = @th[$i];
my $h = $th[$i];
$h =~ s/TH/TH COLSPAN="2" ALIGN="left"/;
$tablestart .= $h;
}
......@@ -1287,6 +1296,12 @@ if ($::usergroupset ne '0' && $buggroupset =~ /^\d+$/) {
<INPUT TYPE=radio NAME=knob VALUE=none CHECKED>
Do nothing else<br>";
$knum++;
if ($statushash{$::unconfirmedstate} && 1 == scaler(keys(%statushash))) {
print "
<INPUT TYPE=radio NAME=knob VALUE=confirm>
Confirm bugs (change status to <b>NEW</b>)<br>";
}
$knum++;
print "
<INPUT TYPE=radio NAME=knob VALUE=accept>
Accept bugs (change status to <b>ASSIGNED</b>)<br>";
......@@ -1363,7 +1378,7 @@ if ($count > 0) {
<NOBR><A HREF=\"enter_bug.cgi\">Enter New Bug</A></NOBR>
&nbsp;&nbsp;
<NOBR><A HREF=\"colchange.cgi?$::buffer\">Change columns</A></NOBR>";
if (!$dotweak && $count > 1) {
if (!$dotweak && $count > 1 && UserInGroup("canedit")) {
print "&nbsp;&nbsp;\n";
print "<NOBR><A HREF=\"buglist.cgi?$fields$orderpart&tweak=1\">";
print "Change several bugs at once</A></NOBR>\n";
......
......@@ -547,7 +547,7 @@ $table{bugs} =
assigned_to mediumint not null, # This is a comment.
bug_file_loc text,
bug_severity enum($severities) not null,
bug_status enum("NEW", "ASSIGNED", "REOPENED", "RESOLVED", "VERIFIED", "CLOSED") not null,
bug_status enum("UNCONFIRMED", "NEW", "ASSIGNED", "REOPENED", "RESOLVED", "VERIFIED", "CLOSED") not null,
creation_ts datetime not null,
delta_ts timestamp,
short_desc mediumtext,
......@@ -567,6 +567,7 @@ $table{bugs} =
# the real data comes from the keywords table.
. '
lastdiffed datetime not null,
everconfirmed tinyint not null,
index (assigned_to),
index (creation_ts),
......@@ -656,7 +657,10 @@ $table{products} =
description mediumtext,
milestoneurl tinytext not null,
disallownew tinyint not null,
votesperuser smallint not null';
votesperuser smallint not null,
maxvotesperbug smallint not null default 10000,
votestoconfirm smallint not null
';
$table{profiles} =
......@@ -670,10 +674,25 @@ $table{profiles} =
disabledtext mediumtext not null,
newemailtech tinyint not null,
mybugslink tinyint not null default 1,
blessgroupset bigint not null,
unique(login_name)';
$table{profiles_activity} =
'userid mediumint not null,
who mediumint not null,
profiles_when datetime not null,
fieldid mediumint not null,
oldvalue tinytext,
newvalue tinytext,
index (userid),
index (profiles_when),
index (fieldid)';
$table{namedqueries} =
'userid mediumint not null,
name varchar(64) not null,
......@@ -775,22 +794,31 @@ while (my ($tabname, $fielddef) = each %table) {
# Populate groups table
###########################################################################
sub GroupExists ($)
{
my ($name) = @_;
my $sth = $dbh->prepare("SELECT name FROM groups WHERE name='$name'");
$sth->execute;
if ($sth->rows) {
return 1;
}
return 0;
}
#
# This subroutine checks if a group exist. If not, it will be automatically
# created with the next available bit set
#
sub AddGroup ($$)
{
my ($name, $desc) = @_;
sub AddGroup {
my ($name, $desc, $userregexp) = @_;
$userregexp ||= "";
# does the group exist?
my $sth = $dbh->prepare("SELECT name FROM groups WHERE name='$name'");
$sth->execute;
return if $sth->rows;
return if GroupExists($name);
# get highest bit number
$sth = $dbh->prepare("SELECT bit FROM groups ORDER BY bit DESC");
my $sth = $dbh->prepare("SELECT bit FROM groups ORDER BY bit DESC");
$sth->execute;
my @row = $sth->fetchrow_array;
......@@ -807,21 +835,31 @@ sub AddGroup ($$)
$sth = $dbh->prepare('INSERT INTO groups
(bit, name, description, userregexp)
VALUES (?, ?, ?, ?)');
$sth->execute($bit, $name, $desc, "");
$sth->execute($bit, $name, $desc, $userregexp);
return $bit;
}
#
# BugZilla uses --GROUPS-- to assign various rights to it's users.
# BugZilla uses --GROUPS-- to assign various rights to its users.
#
AddGroup 'tweakparams', 'Can tweak operating parameters';
AddGroup 'editusers', 'Can edit or disable users';
AddGroup 'editgroupmembers', 'Can put people in and out of groups that they are members of.';
AddGroup 'creategroups', 'Can create and destroy groups.';
AddGroup 'editcomponents', 'Can create, destroy, and edit components.';
AddGroup 'editkeywords', 'Can create, destroy, and edit keywords.';
if (!GroupExists("editbugs")) {
my $id = AddGroup('editbugs', 'Can edit all aspects of any bug.', ".*");
$dbh->do("UPDATE profiles SET groupset = groupset | $id");
}
if (!GroupExists("canconfirm")) {
my $id = AddGroup('canconfirm', 'Can confirm a bug.', ".*");
$dbh->do("UPDATE profiles SET groupset = groupset | $id");
}
......@@ -1427,6 +1465,24 @@ AddField('profiles', 'mybugslink', 'tinyint not null default 1');
AddField('namedqueries', 'linkinfooter', 'tinyint not null');
# 2000-02-12 Added a new state to bugs, UNCONFIRMED. Added ability to confirm
# a vote via bugs. Added user bits to control which users can confirm bugs
# by themselves, and which users can edit bugs without their names on them.
# Added a user field which controls which groups a user can put other users
# into.
my @states = ("UNCONFIRMED", "NEW", "ASSIGNED", "REOPENED", "RESOLVED",
"VERIFIED", "CLOSED");
CheckEnumField('bugs', 'bug_status', @states);
if (!GetFieldDef('bugs', 'everconfirmed')) {
AddField('bugs', 'everconfirmed', 'tinyint not null');
$dbh->do("UPDATE bugs SET everconfirmed = 1");
}
AddField('products', 'maxvotesperbug', 'smallint not null default 10000');
AddField('products', 'votestoconfirm', 'smallint not null');
AddField('profiles', 'blessgroupset', 'bigint not null');
#
# If you had to change the --TABLE-- definition in any way, then add your
# differential change code *** A B O V E *** this comment.
......
<HTML><head>
<!--
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is the Bugzilla Bug Tracking System.
The Initial Developer of the Original Code is Netscape Communications
Corporation. Portions created by Netscape are
Copyright (C) 2000 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s): Terry Weissman <terry@mozilla.org>
-->
<title>Understanding the UNCONFIRMED state, and other recent changes</title>
</head>
<body>
<h1>Understanding the UNCONFIRMED state, and other recent changes</h1>
[This document is aimed primarily at people who have used Bugzilla
before the UNCONFIRMED state was implemented. It might be helpful for
newer users as well.]
<p>
New bugs in some products will now show up in a new state,
UNCONFIRMED. This means that we have nobody has confirmed that the
bug is real. Very busy engineers will probably generally ignore
UNCONFIRMED that have been assigned to them, until they have been
confirmed in one way or another. (Engineers with more time will
hopefully glance over their UNCONFIRMED bugs regularly.)
<p>
The <a href="bug_status.html">page describing bug fields</a> has been
updated to include UNCONFIRMED.
<p>
There are two basic ways that a bug can become confirmed (and enter
the NEW) state.
<ul>
<li> A user with the appropriate permissions (see below for more on
permissions) decides that the bug is a valid one, and confirms
it. We hope to gather a small army of responsible volunteers
to regularly go through bugs for us.
<li> The bug gathers a certain number of votes. <b>Any</b> valid
Bugzilla user may vote for bugs (each user gets a certain
number of bugs); any UNCONFIRMED bug which enough bugs becomes
automatically confirmed, and enters the NEW state.
</ul>
One implication of this is that it is worth your time to search the
bug system for duplicates of your bug to vote on them, before
submitting your own bug. If we can spread around knowledge of this
fact, it ought to help cut down the number of duplicate bugs in the
system.
<h2>Permissions.</h2>
Users now have a certain set of permissions. To see your permissions,
check out the
<a href="userprefs.cgi?bank=permissions">user preferences</a> page.
<p>
If you have the "Can confirm a bug" permission, then you will be able
to move UNCONFIRMED bugs into the NEW state.
<p>
If you have the "Can edit all aspects of any bug" permission, then you
can tweak anything about any bug. If not, you may only edit those
bugs that you have submitted, or that you have assigned to you (or
qa-assigned to you). However, anyone may add a comment to any bug.
<p>
Some people (initially, the initial owners and initial qa-contacts for
components in the system) have the ability to give the above two
permissions to other people. So, if you really feel that you ought to
have one of these permissions, a good person to ask (via private
email, please!) is the person who is assigned a relevant bug.
<h2>Other details.</h2>
An initial stab was taken to decide who would be given which of the
above permissions. This was determined by some simple heurstics of
who was assigned bugs, and who the default owners of bugs were, and a
look at people who seem to have submitted several bugs that appear to
have been interesting and valid. Inevitably, we have failed to give
someone the permissions they deserve. Please don't take it
personally; just bear with us as we shake out the new system.
<p>
People with one of the two bits above can easily confirm their own
bugs, so bugs they submit will actually start out in the NEW state.
They can override this when submitting a bug.
<p>
People can ACCEPT or RESOLVE a bug assigned to them, even if they
aren't allowed to confirm it. However, the system remembers, and if
the bug gets REOPENED or reassigned to someone else, it will revert
back to the UNCONFIRMED state. If the bug has ever been confirmed,
then REOPENing or reassigning will cause it to go to the NEW or
REOPENED state.
<p>
Note that only some products support the UNCONFIRMED state. In other
products, all new bugs will automatically start in the NEW state.
<h2>Things still to be done.</h2>
There probably ought to be a way to get a bug back into the
UNCONFIRMED state, but there isn't yet.
<p>
If a person has submitted several bugs that get confirmed, then this
is probably a person who understands the system well, and deserves the
"Can confirm a bug" permission. This kind of person should be
detected and promoted automatically.
<p>
There should also be a way to automatically promote people to get the
"Can edit all aspects of any bug" permission.
<p>
The "enter a new bug" page needs to be revamped with easy ways for new
people to educate themselves on the benefit of searching for a bug
like the one they're about to submit and voting on it, rather than
adding a new useless duplicate.
<hr>
<!-- hhmts start -->
Last modified: Wed Feb 16 21:04:56 2000
<!-- hhmts end -->
</body> </html>
......@@ -428,7 +428,7 @@ DefParam("expectbigqueries",
0);
DefParam("emailregexp",
'This defines the regexp to use for legal email addresses. The default tries to match fully qualified email addresses. Another popular value to put here is <tt>^[^@, ]$</tt>, which means "local usernames, no @ allowed.',
'This defines the regexp to use for legal email addresses. The default tries to match fully qualified email addresses. Another popular value to put here is <tt>^[^@, ]*$</tt>, which means "local usernames, no @ allowed.',
"t",
q:^[^@, ]*@[^@, ]*\\.[^@, ]*$:);
......@@ -444,7 +444,7 @@ DefParam("emailsuffix",
DefParam("voteremovedmail",
q{This is a mail message to send to anyone who gets a vote removed from a bug for any reason. %to% gets replaced by a comma-separated list of people who used to be voting for this bug. %bugid% gets replaced by the bug number. %reason% gets replaced by a short reason describing why the vote was removed. %<i>anythingelse</i>% gets replaced by the definition of thatparameter (as defined on this page).},
q{This is a mail message to send to anyone who gets a vote removed from a bug for any reason. %to% gets replaced by a comma-separated list of people who used to be voting for this bug. %bugid% gets replaced by the bug number. %reason% gets replaced by a short reason describing why the vote was removed. %count% is how many votes got removed.%<i>anythingelse</i>% gets replaced by the definition of that parameter (as defined on this page).},
"l",
"From: bugzilla-daemon
To: %to%
......@@ -454,6 +454,8 @@ You used to have a vote on bug %bugid%, but it has been removed.
Reason: %reason%
Votes removed: %count%
%urlbase%show_bug.cgi?id=%bugid%
");
......@@ -488,6 +490,9 @@ DefParam("commentonaccept",
DefParam("commentonclearresolution",
"If this option is on, the user needs to enter a short comment if the bugs resolution is cleared",
"b", 0 );
DefParam("commentonconfirm",
"If this option is on, the user needs to enter a short comment when confirming a bug",
"b", 0 );
DefParam("commentonresolve",
"If this option is on, the user needs to enter a short comment if the bug is resolved",
"b", 0 );
......
......@@ -63,17 +63,27 @@ foreach my $id (@buglist) {
}
}
SendSQL("select bug_id, product from bugs where bug_id = " .
join(" or bug_id = ", @buglist));
SendSQL("SELECT bugs.bug_id, bugs.product, products.maxvotesperbug " .
"FROM bugs, products " .
"WHERE products.product = bugs.product ".
" AND bugs.bug_id IN (" . join(", ", @buglist) . ")");
my %prodcount;
while (MoreSQLData()) {
my ($id, $prod) = (FetchSQLData());
my ($id, $prod, $max) = (FetchSQLData());
if (!defined $prodcount{$prod}) {
$prodcount{$prod} = 0;
}
$prodcount{$prod} += $::FORM{$id};
if ($::FORM{$id} > $max) {
PutHeader("Don't overstuff!", "Illegal vote");
print "You may only use at most $max votes for a single bug in the\n";
print "<tt>$prod</tt> product, but you are using $::FORM{$id}.\n";
print "<P>Please click <b>Back</b> and try again.<hr>\n";
PutFooter();
exit();
}
}
foreach my $prod (keys(%prodcount)) {
......@@ -81,7 +91,7 @@ foreach my $prod (keys(%prodcount)) {
PutHeader("Don't overstuff!", "Illegal vote");
print "You may only use $::prodmaxvotes{$prod} votes for bugs in the\n";
print "<tt>$prod</tt> product, but you are using $prodcount{$prod}.\n";
print "Please click <b>Back</b> and try again.<hr>\n";
print "<P>Please click <b>Back</b> and try again.<hr>\n";
PutFooter();
exit();
}
......@@ -110,10 +120,12 @@ foreach my $id (keys %affected) {
SendSQL("unlock tables");
PutHeader("Voting tabulated", "Voting tabulated", $::COOKIE{'Bugzilla_login'});
print "Your votes have been recorded.\n";
print qq{<p><a href="showvotes.cgi?user=$who">Review your votes</a><hr>\n};
foreach my $id (keys %affected) {
CheckIfVotedConfirmed($id, $who);
}
PutFooter();
exit();
......
......@@ -204,7 +204,6 @@ PutHeader ("Enter Bug","Enter Bug","This page lets you enter a new bug into Bugz
print "
<FORM METHOD=POST ACTION=\"post_bug.cgi\">
<INPUT TYPE=HIDDEN NAME=bug_status VALUE=NEW>
<INPUT TYPE=HIDDEN NAME=reporter VALUE=\"$::COOKIE{'Bugzilla_login'}\">
<INPUT TYPE=HIDDEN NAME=product VALUE=\"" . value_quote($product) . "\">
<TABLE CELLSPACING=2 CELLPADDING=0 BORDER=0>";
......@@ -260,6 +259,26 @@ print "
<td></td>
</TR>
<tr><td>&nbsp<td> <td> <td> <td> <td> </tr>
";
if (UserInGroup("canedit") || UserInGroup("canconfirm")) {
SendSQL("SELECT votestoconfirm FROM products WHERE product = " .
SqlQuote($product));
if (FetchOneColumn()) {
print qq{
<TR>
<TD ALIGN="right"><B><A HREF="bug_status.html#status">Initial state:</B></A></TD>
<TD COLSPAN="5">
};
print BuildPulldown("bug_status",
[[$::unconfirmedstate], ["NEW"]],
"NEW");
print "</TD></TR>";
}
}
print "
<tr>
<TD ALIGN=RIGHT><B><A HREF=\"bug_status.html#assigned_to\">Assigned To:</A></B></TD>
<TD colspan=5>$assign_element
......
......@@ -73,6 +73,7 @@ $::param{'version'} = '2.9';
$::dontchange = "--do_not_change--";
$::chooseone = "--Choose_one:--";
$::defaultqueryname = "(Default query)";
$::unconfirmedstate = "UNCONFIRMED";
sub ConnectToDatabase {
if (!defined $::db) {
......@@ -644,7 +645,7 @@ sub UserInGroup {
sub IsOpenedState {
my ($state) = (@_);
if ($state =~ /^(NEW|REOPENED|ASSIGNED)$/) {
if ($state =~ /^(NEW|REOPENED|ASSIGNED)$/ || $state eq $::unconfirmedstate) {
return 1;
}
return 0;
......@@ -652,24 +653,42 @@ sub IsOpenedState {
sub RemoveVotes {
my ($id, $reason) = (@_);
my ($id, $who, $reason) = (@_);
ConnectToDatabase();
SendSQL("select profiles.login_name from votes, profiles where votes.bug_id = $id and profiles.userid = votes.who");
my $whopart = "";
if ($who) {
$whopart = " AND votes.who = $who";
}
SendSQL("SELECT profiles.login_name, votes.count " .
"FROM votes, profiles " .
"WHERE votes.bug_id = $id " .
"AND profiles.userid = votes.who" .
$whopart);
my @list;
while (MoreSQLData()) {
push(@list, FetchOneColumn());
my ($name, $count) = (@_);
push(@list, [$name, $count]);
}
if (0 < @list) {
if (open(SENDMAIL, "|/usr/lib/sendmail -t")) {
my %substs;
$substs{"to"} = join(',', @list);
$substs{"bugid"} = $id;
$substs{"reason"} = $reason;
print SENDMAIL PerformSubsts(Param("voteremovedmail"), \%substs);
close SENDMAIL;
foreach my $ref (@list) {
my ($name, $count) = (@$ref);
if (open(SENDMAIL, "|/usr/lib/sendmail -t")) {
my %substs;
$substs{"to"} = $name;
$substs{"bugid"} = $id;
$substs{"reason"} = $reason;
$substs{"count"} = $count;
print SENDMAIL PerformSubsts(Param("voteremovedmail"),
\%substs);
close SENDMAIL;
}
}
SendSQL("delete from votes where bug_id = $id");
SendSQL("update bugs set votes = 0, delta_ts=delta_ts where bug_id = $id");
SendSQL("DELETE FROM votes WHERE bug_id = $id" . $whopart);
SendSQL("SELECT SUM(count) FROM votes WHERE bug_id = $id");
my $v = FetchOneColumn();
$v ||= 0;
SendSQL("UPDATE bugs SET votes = $v, delta_ts = delta_ts " .
"WHERE bug_id = $id");
}
}
......
......@@ -120,12 +120,32 @@ if (Param("useqacontact")) {
if (exists $::FORM{'bug_status'}) {
if (!UserInGroup("canedit") && !UserInGroup("canconfirm")) {
delete $::FORM{'bug_status'};
}
}
if (!exists $::FORM{'bug_status'}) {
$::FORM{'bug_status'} = $::unconfirmedstate;
SendSQL("SELECT votestoconfirm FROM products WHERE product = " .
SqlQuote($::FORM{'product'}));
if (!FetchOneColumn()) {
$::FORM{'bug_status'} = "NEW";
}
}
my @used_fields;
foreach my $f (@bug_fields) {
if (exists $::FORM{$f}) {
push (@used_fields, $f);
}
}
if (exists $::FORM{'bug_status'} && $::FORM{'bug_status'} ne $::unconfirmedstate) {
push(@used_fields, "everconfirmed");
$::FORM{'everconfirmed'} = 1;
}
my $query = "insert into bugs (\n" . join(",\n", @used_fields) . ",
creation_ts )
......
......@@ -24,6 +24,9 @@
use diagnostics;
use strict;
my $UserInEditGroupSet = -1;
my $UserInCanConfirmGroupSet = -1;
require "CGI.pl";
# Shut up misguided -w warnings about "used only once":
......@@ -38,7 +41,7 @@ use vars %::versions,
%::legal_priority,
%::legal_severity;
confirm_login();
my $whoid = confirm_login();
print "Content-type: text/html\n\n";
......@@ -103,6 +106,97 @@ if ($::FORM{'product'} ne $::dontchange) {
}
# Checks that the user is allowed to change the given field. Actually, right
# now, the rules are pretty simple, and don't look at the field itself very
# much, but that could be enhanced.
my $lastbugid = 0;
my $ownerid;
my $reporterid;
my $qacontactid;
sub CheckCanChangeField {
my ($f, $bugid, $oldvalue, $newvalue) = (@_);
if ($f eq "assigned_to" || $f eq "reporter" || $f eq "qa_contact") {
if ($oldvalue =~ /^\d+$/) {
if ($oldvalue == 0) {
$oldvalue = "";
} else {
$oldvalue = DBID_to_name($oldvalue);
}
}
}
if ($oldvalue eq $newvalue) {
return 1;
}
if ($f =~ /^longdesc/) {
return 1;
}
if ($UserInEditGroupSet < 0) {
$UserInEditGroupSet = UserInGroup("editbugs");
}
if ($UserInEditGroupSet) {
return 1;
}
if ($lastbugid != $bugid) {
SendSQL("SELECT reporter, assigned_to, qa_contact FROM bugs " .
"WHERE bug_id = $bugid");
($reporterid, $ownerid, $qacontactid) = (FetchSQLData());
}
if ($reporterid eq $whoid || $ownerid eq $whoid || $qacontactid eq $whoid) {
if ($f ne "bug_status") {
return 1;
}
if ($newvalue eq $::unconfirmedstate || !IsOpenedState($newvalue)) {
return 1;
}
# Hmm. They are trying to set this bug to some opened state
# that isn't the UNCONFIRMED state. Are they in the right
# group? Or, has it ever been confirmed? If not, then this
# isn't legal.
if ($UserInCanConfirmGroupSet < 0) {
$UserInCanConfirmGroupSet = UserInGroup("canconfirm");
}
if ($UserInCanConfirmGroupSet) {
return 1;
}
my $fieldid = GetFieldID("bug_status");
SendSQL("SELECT newvalue FROM bugs_activity " .
"WHERE fieldid = $fieldid " .
" AND oldvalue = '$::unconfirmedstate'");
while (MoreSQLData()) {
my $n = FetchOneColumn();
if (IsOpenedState($n) && $n ne $::unconfirmedstate) {
return 1;
}
}
}
SendSQL("UNLOCK TABLES");
$oldvalue = value_quote($oldvalue);
$newvalue = value_quote($newvalue);
print qq{
<H1>Sorry, not allowed.</H1>
Only the owner or submitter of the bug, or a sufficiently
empowered user, may make that change to the $f field.
<TABLE>
<TR><TH ALIGN="right">Old value:</TH><TD>$oldvalue</TD></TR>
<TR><TH ALIGN="right">New value:</TH><TD>$newvalue</TD></TR>
</TABLE>
<pre>($reporterid eq $whoid || $ownerid eq $whoid || $qacontactid eq $whoid)</PRE>
<P>Click <B>Back</B> and try again.
};
PutFooter();
exit();
}
my @idlist;
if (defined $::FORM{'id'}) {
......@@ -160,11 +254,29 @@ sub DoComma {
$::comma = ",";
}
sub DoConfirm {
if ($UserInEditGroupSet < 0) {
$UserInEditGroupSet = UserInGroup("editbugs");
}
if ($UserInCanConfirmGroupSet < 0) {
$UserInCanConfirmGroupSet = UserInGroup("canconfirm");
}
if ($UserInEditGroupSet || $UserInCanConfirmGroupSet) {
DoComma();
$::query .= "everconfirmed = 1";
}
}
sub ChangeStatus {
my ($str) = (@_);
if ($str ne $::dontchange) {
DoComma();
$::query .= "bug_status = '$str'";
if (IsOpenedState($str)) {
$::query .= "bug_status = IF(everconfirmed = 1, '$str', '$::unconfirmedstate')";
} else {
$::query .= "bug_status = '$str'";
}
}
}
......@@ -192,7 +304,7 @@ sub CheckonComment( $ ) {
if( $ret ) {
if (!defined $::FORM{'comment'} || $::FORM{'comment'} =~ /^\s*$/) {
# No commet - sorry, action not allowed !
# No comment - sorry, action not allowed !
warnBanner("You have to specify a <b>comment</b> on this change." .
"<p>" .
"Please press <b>Back</b> and give some words " .
......@@ -275,11 +387,17 @@ SWITCH: for ($::FORM{'knob'}) {
/^none$/ && do {
last SWITCH;
};
/^confirm$/ && CheckonComment( "confirm" ) && do {
DoConfirm();
ChangeStatus('NEW');
last SWITCH;
};
/^accept$/ && CheckonComment( "accept" ) && do {
DoConfirm();
ChangeStatus('ASSIGNED');
last SWITCH;
};
/^clearresolution$/ && CheckonComment( "clearresolution" ) &&do {
/^clearresolution$/ && CheckonComment( "clearresolution" ) && do {
ChangeResolution('');
last SWITCH;
};
......@@ -289,6 +407,9 @@ SWITCH: for ($::FORM{'knob'}) {
last SWITCH;
};
/^reassign$/ && CheckonComment( "reassign" ) && do {
if ($::FORM{'andconfirm'}) {
DoConfirm();
}
ChangeStatus('NEW');
DoComma();
if ( Param("strictvaluechecks") ) {
......@@ -460,7 +581,6 @@ sub SnapShotDeps {
}
my $whoid = DBNameToIdAndCheck($::FORM{'who'});
my $timestamp;
sub LogDependencyActivity {
......@@ -489,6 +609,13 @@ foreach my $id (@idlist) {
"keywords $write, longdescs $write, fielddefs $write, " .
"keyworddefs READ, groups READ");
my @oldvalues = SnapShotBug($id);
my $i = 0;
foreach my $col (@::log_columns) {
if (exists $::FORM{$col}) {
CheckCanChangeField($col, $id, $oldvalues[$i], $::FORM{$col});
}
$i++;
}
if (defined $::FORM{'delta_ts'} && $::FORM{'delta_ts'} ne $delta_ts) {
print "
......@@ -730,7 +857,7 @@ The changes made were:
# updates about this bug.
}
if ($col eq 'product') {
RemoveVotes($id,
RemoveVotes($id, 0,
"This bug has been moved to a different product");
}
$col = GetFieldID($col);
......
......@@ -84,8 +84,7 @@ if (defined $::FORM{'bug_id'}) {
if (!defined $status) {
next;
}
my $opened = ($status eq "NEW" || $status eq "ASSIGNED" ||
$status eq "REOPENED");
my $opened = IsOpenedState($status);
my $strike = $opened ? "" : "<strike>";
my $endstrike = $opened ? "" : "</strike>";
$summary = html_quote($summary);
......
......@@ -215,6 +215,42 @@ sub SaveFooter {
sub ShowPermissions {
print "You have the following permission bits set on your account:\n";
print "<P><UL>\n";
my $found = 0;
SendSQL("SELECT description FROM groups " .
"WHERE bit & $::usergroupset != 0 " .
"ORDER BY bit");
while (MoreSQLData()) {
my ($description) = (FetchSQLData());
print "<LI>$description\n";
$found = 1;
}
if ($found == 0) {
print "<LI>(No extra permission bits have been set).\n";
}
print "</UL>\n";
SendSQL("SELECT blessgroupset FROM profiles WHERE userid = $userid");
my $blessgroupset = FetchOneColumn();
if ($blessgroupset) {
print "And you can turn on or off the following bits for\n";
print qq{<A HREF="editusers.cgi">other users</A>:\n};
print "<P><UL>\n";
SendSQL("SELECT description FROM groups " .
"WHERE bit & $blessgroupset != 0 " .
"ORDER BY bit");
while (MoreSQLData()) {
my ($description) = (FetchSQLData());
print "<LI>$description\n";
}
print "</UL>\n";
}
}
######################################################################
################# Live code (not sub defs) starts here ###############
......@@ -239,7 +275,9 @@ my @banklist = (
["diffs", "Email settings",
\&ShowDiffs, \&SaveDiffs],
["footer", "Page footer",
\&ShowFooter, \&SaveFooter]
\&ShowFooter, \&SaveFooter],
["permissions", "Permissions",
\&ShowPermissions, undef]
);
......@@ -300,9 +338,11 @@ if (defined $bankdescription) {
</TABLE>
<INPUT TYPE="hidden" NAME="dosave" VALUE="1">
<INPUT TYPE="hidden" NAME="bank" VALUE="$bank">
<INPUT TYPE="submit" VALUE="Submit">
</FORM>
};
if ($savefunc) {
print qq{<INPUT TYPE="submit" VALUE="Submit">\n};
}
print qq{</FORM>\n};
} else {
print "<P>Please choose from the above links which settings you wish to change.</P>";
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment