Commit c64d5111 authored by bugreport%peshkin.net's avatar bugreport%peshkin.net

Bug 147275 Rearchitect product groups

Patch by joel r=bbaetz,justdave a=justdave
parent e7720dcd
...@@ -167,6 +167,16 @@ sub UpdateParams { ...@@ -167,6 +167,16 @@ sub UpdateParams {
delete $param{'usequip'}; delete $param{'usequip'};
} }
# Change from old product groups to controls for group_control_map
# 2002-10-14 bug 147275 bugreport@peshkin.net
if (exists $param{'usebuggroups'} && !exists $param{'makeproductgroups'}) {
$param{'makeproductgroups'} = $param{'usebuggroups'};
}
if (exists $param{'usebuggroupsentry'}
&& !exists $param{'useentrygroupdefault'}) {
$param{'useentrygroupdefault'} = $param{'usebuggroupsentry'};
}
# --- DEFAULTS FOR NEW PARAMS --- # --- DEFAULTS FOR NEW PARAMS ---
foreach my $item (@param_list) { foreach my $item (@param_list) {
......
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
# Dawn Endico <endico@mozilla.org>
# Dan Mosedale <dmose@mozilla.org>
# Joe Robins <jmrobins@tgix.com>
# Jake <jake@bugzilla.org>
# J. Paul Reed <preed@sigkill.com>
# Bradley Baetz <bbaetz@student.usyd.edu.au>
# Christopher Aillon <christopher@aillon.com>
package Bugzilla::Constants;
use strict;
use base qw(Exporter);
@Bugzilla::Constants::EXPORT = qw(
CONTROLMAPNA
CONTROLMAPSHOWN
CONTROLMAPDEFAULT
CONTROLMAPMANDATORY
);
# CONSTANTS
#
# ControlMap constants for group_control_map.
# membercontol:othercontrol => meaning
# Na:Na => Bugs in this product may not be restricted to this
# group.
# Shown:Na => Members of the group may restrict bugs
# in this product to this group.
# Shown:Shown => Members of the group may restrict bugs
# in this product to this group.
# Anyone who can enter bugs in this product may initially
# restrict bugs in this product to this group.
# Shown:Mandatory => Members of the group may restrict bugs
# in this product to this group.
# Non-members who can enter bug in this product
# will be forced to restrict it.
# Default:Na => Members of the group may restrict bugs in this
# product to this group and do so by default.
# Default:Default => Members of the group may restrict bugs in this
# product to this group and do so by default and
# nonmembers have this option on entry.
# Default:Mandatory => Members of the group may restrict bugs in this
# product to this group and do so by default.
# Non-members who can enter bug in this product
# will be forced to restrict it.
# Mandatory:Mandatory => Bug will be forced into this group regardless.
# All other combinations are illegal.
use constant CONTROLMAPNA => 0;
use constant CONTROLMAPSHOWN => 1;
use constant CONTROLMAPDEFAULT => 2;
use constant CONTROLMAPMANDATORY => 3;
1;
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
use strict; use strict;
use RelationSet; use RelationSet;
use Bugzilla::Constants;
# Use the Attachment module to display attachments for the bug. # Use the Attachment module to display attachments for the bug.
use Attachment; use Attachment;
...@@ -144,12 +144,9 @@ sub show_bug { ...@@ -144,12 +144,9 @@ sub show_bug {
next; next;
} }
if (Param("usebuggroupsentry") if (!CanEnterProduct($product)) {
&& GroupExists($product)
&& !UserInGroup($product))
{
# If we're using bug groups to restrict entry on products, and # If we're using bug groups to restrict entry on products, and
# this product has a bug group, and the user is not in that # this product has an entry group, and the user is not in that
# group, we don't want to include that product in this list. # group, we don't want to include that product in this list.
next; next;
} }
...@@ -275,7 +272,7 @@ sub show_bug { ...@@ -275,7 +272,7 @@ sub show_bug {
SendSQL("SELECT DISTINCT groups.id, name, description," . SendSQL("SELECT DISTINCT groups.id, name, description," .
" bug_group_map.group_id IS NOT NULL," . " bug_group_map.group_id IS NOT NULL," .
" user_group_map.group_id IS NOT NULL," . " user_group_map.group_id IS NOT NULL," .
" isactive" . " isactive, membercontrol, othercontrol" .
" FROM groups" . " FROM groups" .
" LEFT JOIN bug_group_map" . " LEFT JOIN bug_group_map" .
" ON bug_group_map.group_id = groups.id" . " ON bug_group_map.group_id = groups.id" .
...@@ -284,35 +281,50 @@ sub show_bug { ...@@ -284,35 +281,50 @@ sub show_bug {
" ON user_group_map.group_id = groups.id" . " ON user_group_map.group_id = groups.id" .
" AND user_id = $::userid" . " AND user_id = $::userid" .
" AND NOT isbless" . " AND NOT isbless" .
" LEFT JOIN group_control_map" .
" ON group_control_map.group_id = groups.id" .
" AND group_control_map.product_id = " . $bug{'product_id'} .
" WHERE isbuggroup"); " WHERE isbuggroup");
$user{'inallgroups'} = 1; $user{'inallgroups'} = 1;
while (MoreSQLData()) { while (MoreSQLData()) {
my ($groupid, $name, $description, $ison, $ingroup, $isactive) my ($groupid, $name, $description, $ison, $ingroup, $isactive,
= FetchSQLData(); $membercontrol, $othercontrol) = FetchSQLData();
$bug{'inagroup'} = 1 if ($ison); $bug{'inagroup'} = 1 if ($ison);
$membercontrol ||= 0;
if ($isactive && ($membercontrol == CONTROLMAPMANDATORY)) {
$bug{'inagroup'} = 1;
}
# For product groups, we only want to display the checkbox if either # For product groups, we only want to display the checkbox if either
# (1) The bit is already set, or # (1) The bit is set and not required, or
# (2) The user is in the group, but either: # (2) The group is Shown or Default for members and
# (a) The group is a product group for the current product, or # the user is a member of the group.
# (b) The group name isn't a product name if ($ison ||
# This means that all product groups will be skipped, but ($isactive && $ingroup
# non-product bug groups will still be displayed. && (($membercontrol == CONTROLMAPDEFAULT)
if($ison || || ($membercontrol == CONTROLMAPSHOWN))
($isactive && ($ingroup && (!Param("usebuggroups") || ($name eq $bug{'product'}) || ))
(!defined $::proddesc{$name})))))
{ {
$user{'inallgroups'} &= $ingroup; $user{'inallgroups'} &= $ingroup;
my $mandatory;
if ($isactive && ($membercontrol == CONTROLMAPMANDATORY)) {
$mandatory = 1;
} else {
$mandatory = 0;
}
if (($ison) || ($ingroup)) {
push (@groups, { "bit" => $groupid, push (@groups, { "bit" => $groupid,
"ison" => $ison, "ison" => $ison,
"ingroup" => $ingroup, "ingroup" => $ingroup,
"mandatory" => $mandatory,
"description" => $description }); "description" => $description });
} }
} }
}
# If the bug is restricted to a group, get flags that allow # If the bug is restricted to a group, get flags that allow
# the user to set whether or not the reporter # the user to set whether or not the reporter
......
...@@ -728,7 +728,6 @@ $vars->{'order'} = $order; ...@@ -728,7 +728,6 @@ $vars->{'order'} = $order;
my $login = $::COOKIE{'Bugzilla_login'}; my $login = $::COOKIE{'Bugzilla_login'};
$vars->{'caneditbugs'} = UserInGroup('editbugs'); $vars->{'caneditbugs'} = UserInGroup('editbugs');
$vars->{'usebuggroups'} = Param('usebuggroups');
# Whether or not this user is authorized to move bugs to another installation. # Whether or not this user is authorized to move bugs to another installation.
$vars->{'ismover'} = 1 $vars->{'ismover'} = 1
......
...@@ -112,6 +112,7 @@ ...@@ -112,6 +112,7 @@
use strict; use strict;
use vars qw( $db_name %answer ); use vars qw( $db_name %answer );
use Bugzilla::Constants;
########################################################################### ###########################################################################
# Non-interactive override # Non-interactive override
...@@ -1716,6 +1717,17 @@ $table{quips} = ...@@ -1716,6 +1717,17 @@ $table{quips} =
userid mediumint not null default 0, userid mediumint not null default 0,
quip text not null'; quip text not null';
$table{group_control_map} =
'group_id mediumint not null,
product_id mediumint not null,
entry tinyint not null,
membercontrol tinyint not null,
othercontrol tinyint not null,
canedit tinyint not null,
unique(product_id, group_id),
index(group_id)';
########################################################################### ###########################################################################
# Create tables # Create tables
########################################################################### ###########################################################################
...@@ -2954,7 +2966,7 @@ if (GetFieldDef("logincookies", "hostname")) { ...@@ -2954,7 +2966,7 @@ if (GetFieldDef("logincookies", "hostname")) {
AddField("logincookies", "ipaddr", "varchar(40) NOT NULL"); AddField("logincookies", "ipaddr", "varchar(40) NOT NULL");
} }
# 2002-05-10 - enhanchment bug 143826 # 2002-08-19 - bugreport@peshkin.net bug 143826
# Add private comments and private attachments on less-private bugs # Add private comments and private attachments on less-private bugs
AddField('longdescs', 'isprivate', 'tinyint not null default 0'); AddField('longdescs', 'isprivate', 'tinyint not null default 0');
AddField('attachments', 'isprivate', 'tinyint not null default 0'); AddField('attachments', 'isprivate', 'tinyint not null default 0');
...@@ -3121,7 +3133,7 @@ if (($fielddef = GetFieldDef("attachments", "creation_ts")) && ...@@ -3121,7 +3133,7 @@ if (($fielddef = GetFieldDef("attachments", "creation_ts")) &&
ChangeFieldType("attachments", "creation_ts", "datetime NOT NULL"); ChangeFieldType("attachments", "creation_ts", "datetime NOT NULL");
} }
# 2002-08-XX - bugreport@peshkin.net - bug 157756 # 2002-09-22 - bugreport@peshkin.net - bug 157756
# #
# If the whole groups system is new, but the installation isn't, # If the whole groups system is new, but the installation isn't,
# convert all the old groupset groups, etc... # convert all the old groupset groups, etc...
...@@ -3464,6 +3476,54 @@ if (TableExists("attachstatuses") && TableExists("attachstatusdefs")) { ...@@ -3464,6 +3476,54 @@ if (TableExists("attachstatuses") && TableExists("attachstatusdefs")) {
print "done.\n"; print "done.\n";
} }
# 2002-11-24 - bugreport@peshkin.net - bug 147275
#
if (Param('makeproductgroups')) {
# If makeproductgroups is enabled and group_control_map is empty,
# backward-compatbility usebuggroups-equivalent records should
# be created.
my $entry = Param('useentrygroupdefault');
$sth = $dbh->prepare("SELECT COUNT(*) FROM group_control_map");
$sth->execute();
my ($mapcnt) = $sth->fetchrow_array();
if ($mapcnt == 0) {
# Initially populate group_control_map.
# First, get all the existing products and their groups.
$sth = $dbh->prepare("SELECT groups.id, products.id, groups.name, " .
"products.name FROM groups, products " .
"WHERE isbuggroup != 0 AND isactive != 0");
$sth->execute();
while (my ($groupid, $productid, $groupname, $productname)
= $sth->fetchrow_array()) {
if ($groupname eq $productname) {
# Product and group have same name.
$dbh->do("INSERT INTO group_control_map " .
"(group_id, product_id, entry, membercontrol, " .
"othercontrol, canedit) " .
"VALUES ($groupid, $productid, $entry, " .
CONTROLMAPDEFAULT . ", " .
CONTROLMAPNA . ", 0)");
} else {
# See if this group is a product group at all.
my $sth2 = $dbh->prepare("SELECT id FROM products WHERE name = " .
$dbh->quote($groupname));
$sth2->execute();
my ($id) = $sth2->fetchrow_array();
if (!$id) {
# If there is no product with the same name as this
# group, then it is permitted for all products.
$dbh->do("INSERT INTO group_control_map " .
"(group_id, product_id, entry, membercontrol, " .
"othercontrol, canedit) " .
"VALUES ($groupid, $productid, 0, " .
CONTROLMAPSHOWN . ", " .
CONTROLMAPNA . ", 0)");
}
}
}
}
}
# If you had to change the --TABLE-- definition in any way, then add your # If you had to change the --TABLE-- definition in any way, then add your
# differential change code *** A B O V E *** this comment. # differential change code *** A B O V E *** this comment.
# #
...@@ -3793,3 +3853,4 @@ $dbh->do("UPDATE components SET initialowner = $adminuid WHERE initialowner = 0" ...@@ -3793,3 +3853,4 @@ $dbh->do("UPDATE components SET initialowner = $adminuid WHERE initialowner = 0"
unlink "data/versioncache"; unlink "data/versioncache";
print "Reminder: Bugzilla now requires version 8.7 or later of sendmail.\n" unless $silent; print "Reminder: Bugzilla now requires version 8.7 or later of sendmail.\n" unless $silent;
...@@ -244,7 +244,7 @@ sub check_netmask { ...@@ -244,7 +244,7 @@ sub check_netmask {
}, },
{ {
name => 'usebuggroups', name => 'makeproductgroups',
desc => 'If this is on, Bugzilla will associate a bug group with each ' . desc => 'If this is on, Bugzilla will associate a bug group with each ' .
'product in the database, and use it for querying bugs.', 'product in the database, and use it for querying bugs.',
type => 'b', type => 'b',
...@@ -252,9 +252,9 @@ sub check_netmask { ...@@ -252,9 +252,9 @@ sub check_netmask {
}, },
{ {
name => 'usebuggroupsentry', name => 'useentrygroupdefault',
desc => 'If this is on, Bugzilla will use product bug groups to restrict ' . desc => 'If this is on, Bugzilla will use product bug groups to restrict ' .
'who can enter bugs. Requires usebuggroups to be on as well.', 'who can enter bugs. Requires makeproductgroups to be on as well.',
type => 'b', type => 'b',
default => 0 default => 0
}, },
......
...@@ -42,11 +42,11 @@ if (!defined $::FORM{'product'}) { ...@@ -42,11 +42,11 @@ if (!defined $::FORM{'product'}) {
# Reference to a subset of %::proddesc, which the user is allowed to see # Reference to a subset of %::proddesc, which the user is allowed to see
my %products; my %products;
if (Param("usebuggroups")) { if (AnyDefaultGroups()) {
# OK, now only add products the user can see # OK, now only add products the user can see
confirm_login() unless $::userid; confirm_login() unless $::userid;
foreach my $p (@::legal_product) { foreach my $p (@::legal_product) {
if (!GroupExists($p) || UserInGroup($p)) { if (CanEnterProduct($p)) {
$products{$p} = $::proddesc{$p}; $products{$p} = $::proddesc{$p};
} }
} }
...@@ -88,11 +88,8 @@ if (!$product_id) { ...@@ -88,11 +88,8 @@ if (!$product_id) {
} }
# Make sure the user is authorized to access this product. # Make sure the user is authorized to access this product.
if (Param("usebuggroups") && GroupExists($product)) { CanEnterProduct($product)
confirm_login() unless $::userid;
UserInGroup($product)
|| ThrowUserError("product_access_denied"); || ThrowUserError("product_access_denied");
}
###################################################################### ######################################################################
# End Data/Security Validation # End Data/Security Validation
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
use strict; use strict;
use lib "."; use lib ".";
use Bugzilla::Constants;
require "CGI.pl"; require "CGI.pl";
ConnectToDatabase(); ConnectToDatabase();
...@@ -117,9 +118,9 @@ unless ($action) { ...@@ -117,9 +118,9 @@ unless ($action) {
while (MoreSQLData()) { while (MoreSQLData()) {
my ($groupid, $name, $desc, $regexp, $isactive, $isbuggroup) = FetchSQLData(); my ($groupid, $name, $desc, $regexp, $isactive, $isbuggroup) = FetchSQLData();
print "<tr>\n"; print "<tr>\n";
print "<td>$name</td>\n"; print "<td>" . html_quote($name) . "</td>\n";
print "<td>$desc</td>\n"; print "<td>" . html_quote($desc) . "</td>\n";
print "<td>$regexp&nbsp</td>\n"; print "<td>" . html_quote($regexp) . "&nbsp</td>\n";
print "<td align=center>"; print "<td align=center>";
print "X" if (($isactive != 0) && ($isbuggroup != 0)); print "X" if (($isactive != 0) && ($isbuggroup != 0));
print "&nbsp</td>\n"; print "&nbsp</td>\n";
...@@ -185,22 +186,27 @@ if ($action eq 'changeform') { ...@@ -185,22 +186,27 @@ if ($action eq 'changeform') {
print "<TABLE BORDER=1 CELLPADDING=4>"; print "<TABLE BORDER=1 CELLPADDING=4>";
print "<TR><TH>Group:</TH><TD>"; print "<TR><TH>Group:</TH><TD>";
if ($isbuggroup == 0) { if ($isbuggroup == 0) {
print "$name"; print html_quote($name);
} else { } else {
print "<INPUT TYPE=HIDDEN NAME=\"oldname\" VALUE=$name> print "<INPUT TYPE=HIDDEN NAME=\"oldname\" VALUE=" .
<INPUT SIZE=60 NAME=\"name\" VALUE=\"$name\">"; html_quote($name) . ">
<INPUT SIZE=60 NAME=\"name\" VALUE=\"" . html_quote($name) . "\">";
} }
print "</TD></TR><TR><TH>Description:</TH><TD>"; print "</TD></TR><TR><TH>Description:</TH><TD>";
if ($isbuggroup == 0) { if ($isbuggroup == 0) {
print "$description"; print html_quote($description);
} else { } else {
print "<INPUT TYPE=HIDDEN NAME=\"olddesc\" VALUE=\"$description\"> print "<INPUT TYPE=HIDDEN NAME=\"olddesc\" VALUE=\"" .
<INPUT SIZE=70 NAME=\"desc\" VALUE=\"$description\">"; html_quote($description) . "\">
<INPUT SIZE=70 NAME=\"desc\" VALUE=\"" .
html_quote($description) . "\">";
} }
print "</TD></TR><TR> print "</TD></TR><TR>
<TH>User Regexp:</TH><TD>"; <TH>User Regexp:</TH><TD>";
print "<INPUT TYPE=HIDDEN NAME=\"oldrexp\" VALUE=\"$rexp\"> print "<INPUT TYPE=HIDDEN NAME=\"oldrexp\" VALUE=\"" .
<INPUT SIZE=40 NAME=\"rexp\" VALUE=\"$rexp\"></TD></TR>"; html_quote($rexp) . "\">
<INPUT SIZE=40 NAME=\"rexp\" VALUE=\"" .
html_quote($rexp) . "\"></TD></TR>";
if ($isbuggroup == 1) { if ($isbuggroup == 1) {
print "<TR><TH>Use For Bugs:</TH><TD> print "<TR><TH>Use For Bugs:</TH><TD>
<INPUT TYPE=checkbox NAME =\"isactive\" VALUE=1 " . (($isactive == 1) ? "CHECKED" : "") . "> <INPUT TYPE=checkbox NAME =\"isactive\" VALUE=1 " . (($isactive == 1) ? "CHECKED" : "") . ">
...@@ -252,8 +258,8 @@ if ($action eq 'changeform') { ...@@ -252,8 +258,8 @@ if ($action eq 'changeform') {
print "<INPUT TYPE=HIDDEN NAME=\"oldbless-$grpid\" VALUE=$blessmember></TD>"; print "<INPUT TYPE=HIDDEN NAME=\"oldbless-$grpid\" VALUE=$blessmember></TD>";
print "<TD><INPUT TYPE=checkbox NAME=\"grp-$grpid\" $grpchecked VALUE=1>"; print "<TD><INPUT TYPE=checkbox NAME=\"grp-$grpid\" $grpchecked VALUE=1>";
print "<INPUT TYPE=HIDDEN NAME=\"oldgrp-$grpid\" VALUE=$grpmember></TD>"; print "<INPUT TYPE=HIDDEN NAME=\"oldgrp-$grpid\" VALUE=$grpmember></TD>";
print "<TD><B>$grpnam</B></TD>"; print "<TD><B>" . html_quote($grpnam) . "</B></TD>";
print "<TD>$grpdesc</TD>"; print "<TD>" . html_quote($grpdesc) . "</TD>";
print "</TR>\n"; print "</TR>\n";
} }
...@@ -290,6 +296,10 @@ if ($action eq 'add') { ...@@ -290,6 +296,10 @@ if ($action eq 'add') {
print "<td><input size=30 name=\"regexp\"></td>\n"; print "<td><input size=30 name=\"regexp\"></td>\n";
print "<td><input type=\"checkbox\" name=\"isactive\" value=\"1\" checked></td>\n"; print "<td><input type=\"checkbox\" name=\"isactive\" value=\"1\" checked></td>\n";
print "</TR></TABLE>\n<HR>\n"; print "</TR></TABLE>\n<HR>\n";
print "<input type=\"checkbox\" name=\"insertnew\" value=\"1\"";
print " checked" if Param("makeproductgroups");
print ">\n";
print "Insert new group into all existing products.<P>\n";
print "<INPUT TYPE=SUBMIT VALUE=\"Add\">\n"; print "<INPUT TYPE=SUBMIT VALUE=\"Add\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"new\">\n"; print "<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"new\">\n";
print "</FORM>"; print "</FORM>";
...@@ -308,9 +318,13 @@ to this group, although bugs already in the group will remain in the group. ...@@ -308,9 +318,13 @@ to this group, although bugs already in the group will remain in the group.
Doing so is a much less drastic way to stop a group from growing Doing so is a much less drastic way to stop a group from growing
than deleting the group would be. <b>Note: If you are creating a group, you than deleting the group would be. <b>Note: If you are creating a group, you
probably want it to be usable for bugs, in which case you should leave this checked.</b><p>"; probably want it to be usable for bugs, in which case you should leave this checked.</b><p>";
print "<b>User RegExp</b> is optional, and if filled in, will automatically print "<b>User RegExp</b> is optional, and if filled in, will ";
grant membership to this group to anyone creating a new account with an print "automatically grant membership to this group to anyone with an ";
email address that matches this regular expression.<p>"; print "email address that matches this regular expression.<p>\n";
print "By default, the new group will be associated with existing ";
print "products. Unchecking the \"Insert new group into all existing ";
print "products\" option will prevent this and make the group become ";
print "visible only when its controls have been added to a product.<P>\n";
PutTrailer("<a href=editgroups.cgi>Back to the group list</a>"); PutTrailer("<a href=editgroups.cgi>Back to the group list</a>");
exit; exit;
...@@ -384,6 +398,16 @@ if ($action eq 'new') { ...@@ -384,6 +398,16 @@ if ($action eq 'new') {
VALUES ($admin, $gid, 0)"); VALUES ($admin, $gid, 0)");
SendSQL("INSERT INTO group_group_map (member_id, grantor_id, isbless) SendSQL("INSERT INTO group_group_map (member_id, grantor_id, isbless)
VALUES ($admin, $gid, 1)"); VALUES ($admin, $gid, 1)");
# Permit all existing products to use the new group if makeproductgroups.
if ($::FORM{insertnew}) {
SendSQL("INSERT INTO group_control_map " .
"(group_id, product_id, entry, membercontrol, " .
"othercontrol, canedit) " .
"SELECT $gid, products.id, 0, " .
CONTROLMAPSHOWN . ", " .
CONTROLMAPNA . ", 0 " .
"FROM products");
}
print "OK, done.<p>\n"; print "OK, done.<p>\n";
PutTrailer("<a href=\"editgroups.cgi?action=add\">Add another group</a>", PutTrailer("<a href=\"editgroups.cgi?action=add\">Add another group</a>",
"<a href=\"editgroups.cgi\">Back to the group list</a>"); "<a href=\"editgroups.cgi\">Back to the group list</a>");
...@@ -543,6 +567,7 @@ if ($action eq 'delete') { ...@@ -543,6 +567,7 @@ if ($action eq 'delete') {
SendSQL("DELETE FROM user_group_map WHERE group_id = $gid"); SendSQL("DELETE FROM user_group_map WHERE group_id = $gid");
SendSQL("DELETE FROM group_group_map WHERE grantor_id = $gid"); SendSQL("DELETE FROM group_group_map WHERE grantor_id = $gid");
SendSQL("DELETE FROM bug_group_map WHERE group_id = $gid"); SendSQL("DELETE FROM bug_group_map WHERE group_id = $gid");
SendSQL("DELETE FROM group_control_map WHERE group_id = $gid");
SendSQL("DELETE FROM groups WHERE id = $gid"); SendSQL("DELETE FROM groups WHERE id = $gid");
print "<B>Group $gid has been deleted.</B><BR>"; print "<B>Group $gid has been deleted.</B><BR>";
......
...@@ -36,6 +36,7 @@ use strict; ...@@ -36,6 +36,7 @@ use strict;
use lib qw(.); use lib qw(.);
use Bugzilla::Constants;
require "CGI.pl"; require "CGI.pl";
use vars qw( use vars qw(
...@@ -51,6 +52,7 @@ use vars qw( ...@@ -51,6 +52,7 @@ use vars qw(
$userid $userid
%MFORM %MFORM
%versions %versions
$proddesc
); );
# We have to connect to the database, even though we don't use it in this code, # We have to connect to the database, even though we don't use it in this code,
...@@ -60,7 +62,7 @@ ConnectToDatabase(); ...@@ -60,7 +62,7 @@ ConnectToDatabase();
# If we're using bug groups to restrict bug entry, we need to know who the # If we're using bug groups to restrict bug entry, we need to know who the
# user is right from the start. # user is right from the start.
confirm_login() if (Param("usebuggroupsentry")); confirm_login() if AnyEntryGroups();
if (!defined $::FORM{'product'}) { if (!defined $::FORM{'product'}) {
GetVersionTable(); GetVersionTable();
...@@ -69,9 +71,7 @@ if (!defined $::FORM{'product'}) { ...@@ -69,9 +71,7 @@ if (!defined $::FORM{'product'}) {
my %products; my %products;
foreach my $p (@enterable_products) { foreach my $p (@enterable_products) {
if (!(Param("usebuggroupsentry") if (CanEnterProduct($p))
&& GroupExists($p)
&& !UserInGroup($p)))
{ {
$products{$p} = $::proddesc{$p}; $products{$p} = $::proddesc{$p};
} }
...@@ -215,13 +215,11 @@ sub pickos { ...@@ -215,13 +215,11 @@ sub pickos {
# End of subroutines # End of subroutines
############################################################################## ##############################################################################
confirm_login() if (!(Param("usebuggroupsentry"))); confirm_login() if (!(AnyEntryGroups()));
# If the usebuggroupsentry parameter is set, we need to check and make sure # We need to check and make sure
# that the user has permission to enter a bug against this product. # that the user has permission to enter a bug against this product.
if(Param("usebuggroupsentry") if(!CanEnterProduct($product))
&& GroupExists($product)
&& !UserInGroup($product))
{ {
ThrowUserError("entry_access_denied", { product => $product}); ThrowUserError("entry_access_denied", { product => $product});
} }
...@@ -309,30 +307,25 @@ if (UserInGroup("editbugs") || UserInGroup("canconfirm")) { ...@@ -309,30 +307,25 @@ if (UserInGroup("editbugs") || UserInGroup("canconfirm")) {
$vars->{'bug_status'} = \@status; $vars->{'bug_status'} = \@status;
$default{'bug_status'} = $status[0]; $default{'bug_status'} = $status[0];
# Select whether to restrict this bug to the product's bug group or not, SendSQL("SELECT DISTINCT groups.id, groups.name, groups.description, " .
# if the usebuggroups parameter is set, and if this product has a bug group. "membercontrol, othercontrol " .
# First we get the bit and description for the group. "FROM groups LEFT JOIN group_control_map " .
my $group_id = '0'; "ON group_id = id AND product_id = $product_id " .
"WHERE isbuggroup != 0 AND isactive != 0 ORDER BY description");
if(Param("usebuggroups")) {
($group_id) = GroupExists($product);
}
SendSQL("SELECT DISTINCT groups.id, groups.name, groups.description " .
"FROM groups, user_group_map " .
"WHERE user_group_map.group_id = groups.id " .
"AND user_group_map.user_id = $::userid " .
"AND isbless = 0 " .
"AND isbuggroup = 1 AND isactive = 1 ORDER BY description");
my @groups; my @groups;
while (MoreSQLData()) { while (MoreSQLData()) {
my ($id, $prodname, $description) = FetchSQLData(); my ($id, $groupname, $description, $membercontrol, $othercontrol)
# Don't want to include product groups other than this product. = FetchSQLData();
next unless(!Param("usebuggroups") || $prodname eq $product || # Only include groups if the entering user will have an option.
!defined($::proddesc{$prodname})); next if ((!$membercontrol)
|| ($membercontrol == CONTROLMAPNA)
|| ($membercontrol == CONTROLMAPMANDATORY)
|| (($othercontrol != CONTROLMAPSHOWN)
&& ($othercontrol != CONTROLMAPDEFAULT)
&& (!UserInGroup($groupname)))
);
my $check; my $check;
# If this is the group for this product, make it checked. # If this is the group for this product, make it checked.
...@@ -343,11 +336,10 @@ while (MoreSQLData()) { ...@@ -343,11 +336,10 @@ while (MoreSQLData()) {
$check = formvalue("bit-$id", 0); $check = formvalue("bit-$id", 0);
} }
else { else {
# $group_bit will only have a non-zero value if we're using # Checkbox is checked by default if $control is a default state.
# bug groups and have one for this product. $check = (($membercontrol == CONTROLMAPDEFAULT)
# If $group_bit is 0, it won't match the current group, so compare || (($othercontrol == CONTROLMAPDEFAULT)
# it to the current bit instead of checking for non-zero. && (!UserInGroup($groupname))));
$check = ($group_id == $id);
} }
my $group = my $group =
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
use strict; use strict;
use Bugzilla::Constants;
use Bugzilla::Util; use Bugzilla::Util;
# Bring ChmodDataFile in until this is all moved to the module # Bring ChmodDataFile in until this is all moved to the module
use Bugzilla::Config qw(:DEFAULT ChmodDataFile); use Bugzilla::Config qw(:DEFAULT ChmodDataFile);
...@@ -684,6 +685,116 @@ sub GenerateRandomPassword { ...@@ -684,6 +685,116 @@ sub GenerateRandomPassword {
return $password; return $password;
} }
#
# This function checks if there are any entry groups defined.
# If called with no arguments, it identifies
# entry groups for all products. If called with a product
# id argument, it checks for entry groups associated with
# one particular product.
sub AnyEntryGroups {
my $product_id = shift;
$product_id = 0 unless ($product_id);
return $::CachedAnyEntryGroups{$product_id}
if defined($::CachedAnyEntryGroups{$product_id});
PushGlobalSQLState();
my $query = "SELECT 1 FROM group_control_map WHERE entry != 0";
$query .= " AND product_id = $product_id" if ($product_id);
$query .= " LIMIT 1";
SendSQL($query);
$::CachedAnyEntryGroups{$product_id} = MoreSQLData();
FetchSQLData();
PopGlobalSQLState();
return $::CachedAnyEntryGroups{$product_id};
}
#
# This function checks if there are any default groups defined.
# If so, then groups may have to be changed when bugs move from
# one bug to another.
sub AnyDefaultGroups {
return $::CachedAnyDefaultGroups if defined($::CachedAnyDefaultGroups);
PushGlobalSQLState();
SendSQL("SELECT 1 FROM group_control_map, groups WHERE " .
"groups.id = group_control_map.group_id " .
"AND isactive != 0 AND " .
"(membercontrol = " . CONTROLMAPDEFAULT .
" OR othercontrol = " . CONTROLMAPDEFAULT .
") LIMIT 1");
$::CachedAnyDefaultGroups = MoreSQLData();
FetchSQLData();
PopGlobalSQLState();
return $::CachedAnyDefaultGroups;
}
#
# This function checks if, given a product id, the user can edit
# bugs in this product at all.
sub CanEditProductId {
my ($productid) = @_;
my $query = "SELECT group_id FROM group_control_map " .
"WHERE product_id = $productid " .
"AND canedit != 0 ";
if ((defined @{$::vars->{user}{groupids}})
&& (@{$::vars->{user}{groupids}} > 0)) {
$query .= "AND group_id NOT IN(" .
join(',',@{$::vars->{user}{groupids}}) . ") ";
}
$query .= "LIMIT 1";
PushGlobalSQLState();
SendSQL($query);
my ($result) = FetchSQLData();
PopGlobalSQLState();
return (!defined($result));
}
#
# This function determines if a user can enter bugs in the named
# product.
sub CanEnterProduct {
my ($productname) = @_;
my $query = "SELECT group_id IS NULL " .
"FROM products " .
"LEFT JOIN group_control_map " .
"ON group_control_map.product_id = products.id " .
"AND group_control_map.entry != 0 ";
if ((defined @{$::vars->{user}{groupids}})
&& (@{$::vars->{user}{groupids}} > 0)) {
$query .= "AND group_id NOT IN(" .
join(',',@{$::vars->{user}{groupids}}) . ") ";
}
$query .= "WHERE products.name = " . SqlQuote($productname) . " LIMIT 1";
PushGlobalSQLState();
SendSQL($query);
my ($ret) = FetchSQLData();
PopGlobalSQLState();
return ($ret);
}
#
# This function returns an alphabetical list of product names to which
# the user can enter bugs.
sub GetEnterableProducts {
my $query = "SELECT name " .
"FROM products " .
"LEFT JOIN group_control_map " .
"ON group_control_map.product_id = products.id " .
"AND group_control_map.entry != 0 ";
if ((defined @{$::vars->{user}{groupids}})
&& (@{$::vars->{user}{groupids}} > 0)) {
$query .= "AND group_id NOT IN(" .
join(',',@{$::vars->{user}{groupids}}) . ") ";
}
$query .= "WHERE group_id IS NULL ORDER BY name";
PushGlobalSQLState();
SendSQL($query);
my @products = ();
while (MoreSQLData()) {
push @products,FetchOneColumn();
}
PopGlobalSQLState();
return (@products);
}
sub CanSeeBug { sub CanSeeBug {
my ($id, $userid) = @_; my ($id, $userid) = @_;
...@@ -1749,5 +1860,5 @@ $::vars = ...@@ -1749,5 +1860,5 @@ $::vars =
'VERSION' => $Bugzilla::Config::VERSION, 'VERSION' => $Bugzilla::Config::VERSION,
}; };
1; 1;
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
use strict; use strict;
use lib qw(.); use lib qw(.);
use Bugzilla::Constants;
require "CGI.pl"; require "CGI.pl";
require "bug_form.pl"; require "bug_form.pl";
...@@ -101,8 +102,7 @@ if (defined $::FORM{'maketemplate'}) { ...@@ -101,8 +102,7 @@ if (defined $::FORM{'maketemplate'}) {
umask 0; umask 0;
# Some sanity checking # Some sanity checking
if(Param("usebuggroupsentry") && GroupExists($product)) { if (!CanEnterProduct($product)) {
UserInGroup($product) ||
ThrowUserError("entry_access_denied", {product => $product}); ThrowUserError("entry_access_denied", {product => $product});
} }
...@@ -363,13 +363,38 @@ foreach my $b (grep(/^bit-\d*$/, keys %::FORM)) { ...@@ -363,13 +363,38 @@ foreach my $b (grep(/^bit-\d*$/, keys %::FORM)) {
WHERE user_id = $::userid WHERE user_id = $::userid
AND group_id = $v AND group_id = $v
AND isbless = 0"); AND isbless = 0");
my ($member) = FetchSQLData(); my ($permit) = FetchSQLData();
if ($member) { if (!$permit) {
SendSQL("SELECT othercontrol FROM group_control_map
WHERE group_id = $v AND product_id = $product_id");
my ($othercontrol) = FetchSQLData();
$permit = (($othercontrol == CONTROLMAPSHOWN)
|| ($othercontrol == CONTROLMAPDEFAULT));
}
if ($permit) {
push(@groupstoadd, $v) push(@groupstoadd, $v)
} }
} }
} }
SendSQL("SELECT DISTINCT groups.id, groups.name, " .
"membercontrol, othercontrol " .
"FROM groups LEFT JOIN group_control_map " .
"ON group_id = id AND product_id = $product_id " .
" WHERE isbuggroup != 0 AND isactive != 0 ORDER BY description");
while (MoreSQLData()) {
my ($id, $groupname, $membercontrol, $othercontrol ) = FetchSQLData();
$membercontrol ||= 0;
$othercontrol ||= 0;
# Add groups required
if (($membercontrol == CONTROLMAPMANDATORY)
|| (($othercontrol == CONTROLMAPMANDATORY)
&& (!UserInGroup($groupname)))) {
# User had no option, bug needs to be in this group.
push(@groupstoadd, $id)
}
}
# Lock tables before inserting records for the new bug into the database # Lock tables before inserting records for the new bug into the database
# if we are using a shadow database to prevent shadow database corruption # if we are using a shadow database to prevent shadow database corruption
......
...@@ -191,19 +191,14 @@ if ($default{'chfieldto'}->[0] eq "") { ...@@ -191,19 +191,14 @@ if ($default{'chfieldto'}->[0] eq "") {
GetVersionTable(); GetVersionTable();
# if using usebuggroups, then we don't want people to see products they don't # if using groups for entry, then we don't want people to see products they
# have access to. Remove them from the list. # don't have access to. Remove them from the list.
my @products = (); my @products = ();
my %component_set; my %component_set;
my %version_set; my %version_set;
my %milestone_set; my %milestone_set;
foreach my $p (@::legal_product) { foreach my $p (GetEnterableProducts()) {
# If we're using bug groups to restrict entry on products, and
# this product has a bug group, and the user is not in that
# group, we don't want to include that product in this list.
next if (Param("usebuggroups") && GroupExists($p) && !UserInGroup($p));
# We build up boolean hashes in the "-set" hashes for each of these things # We build up boolean hashes in the "-set" hashes for each of these things
# before making a list because there may be duplicates names across products. # before making a list because there may be duplicates names across products.
push @products, $p; push @products, $p;
......
...@@ -663,7 +663,7 @@ SendSQL("SELECT name, description FROM products ORDER BY name"); ...@@ -663,7 +663,7 @@ SendSQL("SELECT name, description FROM products ORDER BY name");
while (MoreSQLData()) { while (MoreSQLData()) {
my ($product, $productdesc) = FetchSQLData(); my ($product, $productdesc) = FetchSQLData();
next if (Param("usebuggroups") && GroupExists($product) && !UserInGroup($product)); next if (!CanEnterProduct($product));
push (@products, $product); push (@products, $product);
$line_count++; $line_count++;
......
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
# Dawn Endico <endico@mozilla.org> # Dawn Endico <endico@mozilla.org>
# Bryce Nesbitt <bryce@nextbus.COM>, # Bryce Nesbitt <bryce@nextbus.COM>,
# Joe Robins <jmrobins@tgix.com>, # Joe Robins <jmrobins@tgix.com>,
# If using the usebuggroups parameter, users shouldn't be able to see
# reports for products they don't have access to.
# Gervase Markham <gerv@gerv.net> and Adam Spiers <adam@spiers.net> # Gervase Markham <gerv@gerv.net> and Adam Spiers <adam@spiers.net>
# Added ability to chart any combination of resolutions/statuses. # Added ability to chart any combination of resolutions/statuses.
# Derive the choice of resolutions/statuses from the -All- data file # Derive the choice of resolutions/statuses from the -All- data file
...@@ -60,20 +58,11 @@ quietly_check_login(); ...@@ -60,20 +58,11 @@ quietly_check_login();
GetVersionTable(); GetVersionTable();
# If the usebuggroups parameter is set, we don't want to list all products.
# We only want those products that the user has permissions for. # We only want those products that the user has permissions for.
my @myproducts; my @myproducts;
if(Param("usebuggroups")) { push( @myproducts, "-All-");
push( @myproducts, "-All-"); foreach my $this_product (@legal_product) {
foreach my $this_product (@legal_product) { push(@myproducts, $this_product) if CanEnterProduct($this_product);
if(GroupExists($this_product) && !UserInGroup($this_product)) {
next;
} else {
push( @myproducts, $this_product )
}
}
} else {
push( @myproducts, "-All-", @legal_product );
} }
if (! defined $FORM{'product'}) { if (! defined $FORM{'product'}) {
...@@ -91,12 +80,11 @@ if (! defined $FORM{'product'}) { ...@@ -91,12 +80,11 @@ if (! defined $FORM{'product'}) {
grep($_ eq $FORM{'product'}, @myproducts) grep($_ eq $FORM{'product'}, @myproducts)
|| ThrowUserError("invalid_product_name", {product => $FORM{'product'}}); || ThrowUserError("invalid_product_name", {product => $FORM{'product'}});
# If usebuggroups is on, we don't want people to be able to view # We don't want people to be able to view
# reports for products they don't have permissions for... # reports for products they don't have permissions for...
Param("usebuggroups") if (!CanEnterProduct($FORM{'product'})) {
&& GroupExists($FORM{'product'}) ThrowUserError("report_access_denied");
&& !UserInGroup($FORM{'product'}) }
&& ThrowUserError("report_access_denied");
# We've checked that the product exists, and that the user can see it # We've checked that the product exists, and that the user can see it
# This means that is OK to detaint # This means that is OK to detaint
......
...@@ -26,6 +26,7 @@ use strict; ...@@ -26,6 +26,7 @@ use strict;
use lib qw(.); use lib qw(.);
require "CGI.pl"; require "CGI.pl";
use Bugzilla::Constants;
use vars qw(%FORM $unconfirmedstate); use vars qw(%FORM $unconfirmedstate);
...@@ -263,6 +264,7 @@ CrossCheck("groups", "id", ...@@ -263,6 +264,7 @@ CrossCheck("groups", "id",
["bug_group_map", "group_id"], ["bug_group_map", "group_id"],
["group_group_map", "grantor_id"], ["group_group_map", "grantor_id"],
["group_group_map", "member_id"], ["group_group_map", "member_id"],
["group_control_map", "group_id"],
["user_group_map", "group_id"]); ["user_group_map", "group_id"]);
CrossCheck("profiles", "userid", CrossCheck("profiles", "userid",
...@@ -288,6 +290,7 @@ CrossCheck("products", "id", ...@@ -288,6 +290,7 @@ CrossCheck("products", "id",
["components", "product_id", "name"], ["components", "product_id", "name"],
["milestones", "product_id", "value"], ["milestones", "product_id", "value"],
["versions", "product_id", "value"], ["versions", "product_id", "value"],
["group_control_map", "product_id"],
["flaginclusions", "product_id", "type_id"], ["flaginclusions", "product_id", "type_id"],
["flagexclusions", "product_id", "type_id"]); ["flagexclusions", "product_id", "type_id"]);
...@@ -613,6 +616,53 @@ DateCheck("groups", "last_changed"); ...@@ -613,6 +616,53 @@ DateCheck("groups", "last_changed");
DateCheck("profiles", "refreshed_when"); DateCheck("profiles", "refreshed_when");
########################################################################### ###########################################################################
# Control Values
###########################################################################
# Checks for values that are invalid OR
# not among the 9 valid combinations
Status("Checking for bad values in group_control_map");
SendSQL("SELECT COUNT(product_id) FROM group_control_map WHERE " .
"membercontrol NOT IN(" . CONTROLMAPNA . "," . CONTROLMAPSHOWN .
"," . CONTROLMAPDEFAULT . "," . CONTROLMAPMANDATORY . ")" .
" OR " .
"othercontrol NOT IN(" . CONTROLMAPNA . "," . CONTROLMAPSHOWN .
"," . CONTROLMAPDEFAULT . "," . CONTROLMAPMANDATORY . ")" .
" OR " .
"( (membercontrol != othercontrol) " .
"AND (membercontrol != " . CONTROLMAPSHOWN . ") " .
"AND ((membercontrol != " . CONTROLMAPDEFAULT . ") " .
"OR (othercontrol = " . CONTROLMAPSHOWN . ")))");
my $c = FetchOneColumn();
if ($c) {
Alert("Found $c bad group_control_map entries");
}
Status("Checking for bugs with groups violating their product's group controls");
BugCheck("bugs, groups, bug_group_map
LEFT JOIN group_control_map
ON group_control_map.product_id = bugs.product_id
AND group_control_map.group_id = bug_group_map.group_id
WHERE bugs.bug_id = bug_group_map.bug_id
AND bug_group_map.group_id = groups.id
AND groups.isactive != 0
AND ((group_control_map.membercontrol = " . CONTROLMAPNA . ")
OR (group_control_map.membercontrol IS NULL))",
"Have groups not permitted for their products");
BugCheck("bugs, groups, group_control_map
LEFT JOIN bug_group_map
ON group_control_map.group_id = bug_group_map.group_id
AND bugs.bug_id = bug_group_map.bug_id
WHERE group_control_map.product_id = bugs.product_id
AND bug_group_map.group_id = groups.id
AND groups.isactive != 0
AND group_control_map.membercontrol = " . CONTROLMAPMANDATORY . "
AND bug_group_map.group_id IS NULL",
"Are missing groups required for their products");
###########################################################################
# Unsent mail # Unsent mail
########################################################################### ###########################################################################
......
<!-- 1.0@bugzilla.org -->
[%# 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) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Joel Peshkin <bugreport@peshkin.net>
#
#%]
[% PROCESS global/header.html.tmpl title="Confirm Group Control Change for product \'$product\'" %]
[% FOREACH group = mandatory_groups %]
<P>
group '[% group.name FILTER html %]' impacts [% group.count %] bugs for which the group is
newly mandatory and will be added.
[% END %]
[% FOREACH group = na_groups %]
<P>
group '[% group.name FILTER html %]' impacts [% group.count %] bugs for which the group is no longer applicable and will be removed.
[% END %]
<form method="post" >
[% PROCESS "global/hidden-fields.html.tmpl" exclude="^(Bugzilla|LDAP)_(login|password)$" %]
<br>
Click "Continue" to proceed with the change including the changes
indicated above. If you do not want these changes, use "back" to
return to the previous page.
<p>
<input type="hidden" name="confirmed" value="confirmed">
<input type="submit" value="Continue">
</p>
</form>
[% PROCESS global/footer.html.tmpl %]
<!-- 1.0@bugzilla.org -->
[%# 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) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Joel Peshkin <bugreport@peshkin.net>
#%]
[% filt_product = product FILTER html %]
[% PROCESS global/header.html.tmpl
title = "Edit Group Controls for '$filt_product'"
%]
<form method="post" action="editproducts.cgi">
<input type="hidden" name="action" value="updategroupcontrols">
<input type="hidden" name="product" value="[% filt_product %]">
<table id="form" cellspacing="0" cellpadding="4" border="1">
<tr bgcolor="#6666ff">
<th>Group</th>
<th>Entry</th>
<th>MemberControl</th>
<th>OtherControl</th>
<th>Canedit</th>
<th>Bugs</th>
</tr>
[% FOREACH group = groups %]
[% IF group.isactive == 0 AND group.bugcount > 0 %]
<tr bgcolor="#bbbbbb">
<td>
[% group.name FILTER html %]
</td>
<td align="center" colspan=4>
Disabled
</td>
<td>
[% group.bugcount %]
</td>
<tr>
[% ELSIF group.isactive != 0 %]
<tr>
<td>
[% group.name FILTER html %]
</td>
<td>
<input type=checkbox value=1 name=entry_[% group.id %]
[% " checked=\"checked\"" IF group.entry %]>
</td>
<td>
<select name="membercontrol_[% group.id %]">
<option value=[% const.CONTROLMAPNA %]
[% " selected=\"selected\""
IF group.membercontrol == const.CONTROLMAPNA %]
>NA
</option>
<option value=[% const.CONTROLMAPSHOWN %]
[% " selected=\"selected\""
IF group.membercontrol == const.CONTROLMAPSHOWN %]
>Shown
</option>
<option value=[% const.CONTROLMAPDEFAULT %]
[% " selected=\"selected\""
IF group.membercontrol == const.CONTROLMAPDEFAULT %]
>Default
</option>
<option value=[% const.CONTROLMAPMANDATORY %]
[% " selected=\"selected\""
IF group.membercontrol == const.CONTROLMAPMANDATORY %]
>Mandatory
</option>
</select>
</td>
<td>
<select name="othercontrol_[% group.id %]">
<option value=[% const.CONTROLMAPNA %]
[% " selected=\"selected\""
IF group.othercontrol == const.CONTROLMAPNA %]
>NA
</option>
<option value=[% const.CONTROLMAPSHOWN %]
[% " selected=\"selected\""
IF group.othercontrol == const.CONTROLMAPSHOWN %]
>Shown
</option>
<option value=[% const.CONTROLMAPDEFAULT %]
[% " selected=\"selected\""
IF group.othercontrol == const.CONTROLMAPDEFAULT %]
>Default
</option>
<option value=[% const.CONTROLMAPMANDATORY %]
[% " selected=\"selected\""
IF group.othercontrol == const.CONTROLMAPMANDATORY %]
>Mandatory
</option>
</select>
</td>
<td>
<input type=checkbox value=1 name=canedit_[% group.id %]
[% " checked=\"checked\"" IF group.canedit %]>
</td>
<td>
[% group.bugcount %]
</td>
</tr>
[% END %]
[% END %]
</table>
<br>
<input type=submit name="submit" value="submit">
<br>
</form>
<p>
These settings control the relationship of the groups to this
product.
<p>
If any group has <b>Entry</b> selected, then this product will
restrict bug entry to only those users who are members of all the
groups with entry selected.
<p>
If any group has <b>Canedit</b> selected, then this product
will be read-only for any users who are not members of all of
the groups with Canedit selected. ONLY users who are members of
all the canedit groups will be able to edit. This is an additional
restriction that further restricts what can be edited by a user.
<p>
The <b>MemberControl</b> and <b>OtherControl</b> fields
indicate which bugs will be placed in
this group according to the following definitions.
<br>
<table border=1>
<tr>
<th>
MemberControl
</th>
<th>
OtherControl
</th>
<th>
Interpretation
</th>
</tr>
<tr>
<td>
NA
</td>
<td>
NA
</td>
<td>
Bugs in this product are never associated with this group.
</td>
</tr>
<tr>
<td>
Shown
</td>
<td>
NA
</td>
<td>
Bugs in this product are permitted to be restricted to this
group. Users who are a member of this group will be able
to place bugs in this group.
</td>
</tr>
<tr>
<td>
Shown
</td>
<td>
Shown
</td>
<td>
Bugs in this product can be placed in this group by anyone
with permission to edit the bug even if they are not a member
of this group.
</td>
</tr>
<tr>
<td>
Shown
</td>
<td>
Default
</td>
<td>
Bugs in this product can be placed in this group by anyone
with permission to edit the bug even if they are not a member
of this group. Non-members place bugs in this group by default.
</td>
</tr>
<tr>
<td>
Shown
</td>
<td>
Mandatory
</td>
<td>
Bugs in this product are permitted to be restricted to this
group. Users who are a member of this group will be able
to place bugs in this group.
Non-members will be forced to restrict bugs to this group
when they initially enter a bug in this product.
</td>
</tr>
<tr>
<td>
Default
</td>
<td>
NA
</td>
<td>
Bugs in this product are permitted to be restricted to this
group and are placed in this group by default.
Users who are a member of this group will be able
to place bugs in this group.
</td>
</tr>
<tr>
<td>
Default
</td>
<td>
Default
</td>
<td>
Bugs in this product are permitted to be restricted to this
group and are placed in this group by default.
Users who are a member of this group will be able
to place bugs in this group. Non-members will be able to
restrict bugs to this group on entry and will do so by default
</td>
</tr>
<tr>
<td>
Default
</td>
<td>
Mandatory
</td>
<td>
Bugs in this product are permitted to be restricted to this
group and are placed in this group by default.
Users who are a member of this group will be able
to place bugs in this group. Non-members will be forced
to place bugs in this group on entry.
</td>
</tr>
<tr>
<td>
Mandatory
</td>
<td>
Mandatory
</td>
<td>
Bugs in this product are required to be restricted to this
group. Users are not given any option.
</td>
</tr>
</table>
[% PROCESS global/footer.html.tmpl %]
...@@ -405,14 +405,21 @@ ...@@ -405,14 +405,21 @@
<br> <br>
[% IF groups.size > 0 %] [% IF groups.size > 0 %]
[% FOREACH group = groups %]
[% IF NOT group.mandatory %]
[% IF NOT emitted_description %]
[% emitted_description = 1 %]
<br> <br>
<b>Only users in all of the selected groups can view this bug:</b> <b>Only users in all of the selected groups can view this bug:</b>
<br> <br>
<font size="-1">(Unchecking all boxes makes this a public bug.)</font> <font size="-1">
(Unchecking all boxes makes this a more public bug.)
</font>
<br> <br>
<br> <br>
[% END %]
[% FOREACH group = groups %]
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;
<input type="checkbox" name="bit-[% group.bit %]" value="1" <input type="checkbox" name="bit-[% group.bit %]" value="1"
[% " checked=\"checked\"" IF group.ison %] [% " checked=\"checked\"" IF group.ison %]
...@@ -420,6 +427,7 @@ ...@@ -420,6 +427,7 @@
[% group.description %] [% group.description %]
<br> <br>
[% END %] [% END %]
[% END %]
[% IF NOT user.inallgroups %] [% IF NOT user.inallgroups %]
<b> <b>
...@@ -431,7 +439,7 @@ ...@@ -431,7 +439,7 @@
[% IF bug.inagroup %] [% IF bug.inagroup %]
<p> <p>
<b>But users in the roles selected below can always view this bug:</b> <b>Users in the roles selected below can always view this bug:</b>
<br> <br>
<small> <small>
(The assignee (The assignee
......
...@@ -81,14 +81,14 @@ ...@@ -81,14 +81,14 @@
<h3>Verify Bug Group</h3> <h3>Verify Bug Group</h3>
<p> <p>
Do you want to add the bug to its new product's group (if any)? Do you want to add the bug to its new product's default groups (if any)?
</p> </p>
<p> <p>
<input type="radio" name="addtonewgroup" value="no"><b>no</b><br> <input type="radio" name="addtonewgroup" value="no"><b>no</b><br>
<input type="radio" name="addtonewgroup" value="yes"><b>yes</b><br> <input type="radio" name="addtonewgroup" value="yes"><b>yes</b><br>
<input type="radio" name="addtonewgroup" value="yesifinold" checked="checked"> <input type="radio" name="addtonewgroup" value="yesifinold" checked="checked">
<b>yes, but only if the bug was in its old product's group</b><br> <b>yes, but only if the bug was in any of its old product's default groups</b><br>
</p> </p>
[% END %] [% END %]
......
...@@ -230,6 +230,12 @@ ...@@ -230,6 +230,12 @@
It must also not contain any of these special characters: It must also not contain any of these special characters:
<tt>\ ( ) &amp; &lt; &gt; , ; : &quot; [ ]</tt>, or any whitespace. <tt>\ ( ) &amp; &lt; &gt; , ; : &quot; [ ]</tt>, or any whitespace.
[% ELSIF error == "illegal_group_control_combination" %]
[% title = "Your Group Control Combination Is Illegal" %]
Your group control combination for group &quot;
[% groupname FILTER html %]
&quot; is illegal.
[% ELSIF error == "illegal_is_obsolete" %] [% ELSIF error == "illegal_is_obsolete" %]
[% title = "Your Query Makes No Sense" %] [% title = "Your Query Makes No Sense" %]
The only legal values for the <em>Attachment is obsolete</em> field are The only legal values for the <em>Attachment is obsolete</em> field are
...@@ -462,6 +468,10 @@ ...@@ -462,6 +468,10 @@
[% title = "Access Denied" %] [% title = "Access Denied" %]
You do not have the permissions necessary to access that product. You do not have the permissions necessary to access that product.
[% ELSIF error == "product_edit_denied" %]
[% title = "Product Edit Access Denied" %]
You are not permitted to edit bugs in product [% product %].
[% ELSIF error == "query_name_missing" %] [% ELSIF error == "query_name_missing" %]
[% title = "No Query Name Specified" %] [% title = "No Query Name Specified" %]
You must enter a name for your query. You must enter a name for your query.
......
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