Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
bugzilla
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
bugzilla
Commits
c64d5111
Commit
c64d5111
authored
Nov 25, 2002
by
bugreport%peshkin.net
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bug 147275 Rearchitect product groups
Patch by joel r=bbaetz,justdave a=justdave
parent
e7720dcd
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1507 additions
and
197 deletions
+1507
-197
Config.pm
Bugzilla/Config.pm
+10
-0
Constants.pm
Bugzilla/Constants.pm
+76
-0
bug_form.pl
bug_form.pl
+34
-22
buglist.cgi
buglist.cgi
+0
-1
checksetup.pl
checksetup.pl
+63
-2
defparams.pl
defparams.pl
+3
-3
describecomponents.cgi
describecomponents.cgi
+3
-6
editgroups.cgi
editgroups.cgi
+41
-16
editproducts.cgi
editproducts.cgi
+527
-12
enter_bug.cgi
enter_bug.cgi
+26
-34
globals.pl
globals.pl
+112
-1
post_bug.cgi
post_bug.cgi
+30
-5
process_bug.cgi
process_bug.cgi
+155
-58
query.cgi
query.cgi
+3
-8
queryhelp.cgi
queryhelp.cgi
+1
-1
reports.cgi
reports.cgi
+7
-19
sanitycheck.cgi
sanitycheck.cgi
+50
-0
confirm-edit.html.tmpl
...efault/admin/products/groupcontrol/confirm-edit.html.tmpl
+55
-0
edit.html.tmpl
...ate/en/default/admin/products/groupcontrol/edit.html.tmpl
+284
-0
edit.html.tmpl
template/en/default/bug/edit.html.tmpl
+15
-7
verify-new-product.html.tmpl
template/en/default/bug/process/verify-new-product.html.tmpl
+2
-2
user-error.html.tmpl
template/en/default/global/user-error.html.tmpl
+10
-0
No files found.
Bugzilla/Config.pm
View file @
c64d5111
...
@@ -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
)
{
...
...
Bugzilla/Constants.pm
0 → 100644
View file @
c64d5111
# -*- 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
;
bug_form.pl
View file @
c64d5111
...
@@ -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 a
n 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,33 +281,48 @@ sub show_bug {
...
@@ -284,33 +281,48 @@ 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
;
push
(
@groups
,
{
"bit"
=>
$groupid
,
my
$mandatory
;
"ison"
=>
$ison
,
if
(
$isactive
&&
(
$membercontrol
==
CONTROLMAPMANDATORY
))
{
"ingroup"
=>
$ingroup
,
$mandatory
=
1
;
"description"
=>
$description
});
}
else
{
$mandatory
=
0
;
}
if
((
$ison
)
||
(
$ingroup
))
{
push
(
@groups
,
{
"bit"
=>
$groupid
,
"ison"
=>
$ison
,
"ingroup"
=>
$ingroup
,
"mandatory"
=>
$mandatory
,
"description"
=>
$description
});
}
}
}
}
}
...
...
buglist.cgi
View file @
c64d5111
...
@@ -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
...
...
checksetup.pl
View file @
c64d5111
...
@@ -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-0
5-10 - enhanchmen
t bug 143826
# 2002-0
8-19 - bugreport@peshkin.ne
t 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-0
8-XX
- bugreport@peshkin.net - bug 157756
# 2002-0
9-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
;
defparams.pl
View file @
c64d5111
...
@@ -244,7 +244,7 @@ sub check_netmask {
...
@@ -244,7 +244,7 @@ sub check_netmask {
},
},
{
{
name
=>
'
usebug
groups'
,
name
=>
'
makeproduct
groups'
,
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
=>
'use
buggroupsentry
'
,
name
=>
'use
entrygroupdefault
'
,
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
usebug
groups to be on as well.'
,
'who can enter bugs. Requires
makeproduct
groups to be on as well.'
,
type
=>
'b'
,
type
=>
'b'
,
default
=>
0
default
=>
0
},
},
...
...
describecomponents.cgi
View file @
c64d5111
...
@@ -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
...
...
editgroups.cgi
View file @
c64d5111
...
@@ -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
 </td>\n"
;
print
"<td>
"
.
html_quote
(
$regexp
)
.
"
 </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
" </td>\n"
;
print
" </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>"
;
...
...
editproducts.cgi
View file @
c64d5111
...
@@ -29,7 +29,8 @@
...
@@ -29,7 +29,8 @@
use
strict
;
use
strict
;
use
lib
"."
;
use
lib
"."
;
use
vars
qw ($template
$vars
);
use
Bugzilla::
Constants
;
require
"CGI.pl"
;
require
"CGI.pl"
;
require
"globals.pl"
;
require
"globals.pl"
;
...
@@ -38,9 +39,16 @@ require "globals.pl";
...
@@ -38,9 +39,16 @@ require "globals.pl";
sub
sillyness
{
sub
sillyness
{
my
$zz
;
my
$zz
;
$zz
=
%::
MFORM
;
$zz
=
$::unconfirmedstate
;
$zz
=
$::unconfirmedstate
;
}
}
my
%
ctl
=
(
&::
CONTROLMAPNA
=>
'NA'
,
&::
CONTROLMAPSHOWN
=>
'Shown'
,
&::
CONTROLMAPDEFAULT
=>
'Default'
,
&::
CONTROLMAPMANDATORY
=>
'Mandatory'
);
# TestProduct: just returns if the specified product does exists
# TestProduct: just returns if the specified product does exists
# CheckProduct: same check, optionally emit an error text
# CheckProduct: same check, optionally emit an error text
...
@@ -187,10 +195,9 @@ unless (UserInGroup("editcomponents")) {
...
@@ -187,10 +195,9 @@ unless (UserInGroup("editcomponents")) {
#
#
my
$product
=
trim
(
$::FORM
{
product
}
||
''
);
my
$product
=
trim
(
$::FORM
{
product
}
||
''
);
my
$action
=
trim
(
$::FORM
{
action
}
||
''
);
my
$action
=
trim
(
$::FORM
{
action
}
||
''
);
my
$headerdone
=
0
;
my
$localtrailer
=
"<A HREF=\"editproducts.cgi\">edit</A> more products"
;
my
$localtrailer
=
"<A HREF=\"editproducts.cgi\">edit</A> more products"
;
#
#
# action='' -> Show nice list of products
# action='' -> Show nice list of products
#
#
...
@@ -342,7 +349,7 @@ if ($action eq 'new') {
...
@@ -342,7 +349,7 @@ if ($action eq 'new') {
# If we're using bug groups, then we need to create a group for this
# If we're using bug groups, then we need to create a group for this
# product as well. -JMR, 2/16/00
# product as well. -JMR, 2/16/00
if
(
Param
(
"
usebug
groups"
))
{
if
(
Param
(
"
makeproduct
groups"
))
{
# Next we insert into the groups table
# Next we insert into the groups table
SendSQL
(
"INSERT INTO groups "
.
SendSQL
(
"INSERT INTO groups "
.
"(name, description, isbuggroup, last_changed) "
.
"(name, description, isbuggroup, last_changed) "
.
...
@@ -356,6 +363,35 @@ if ($action eq 'new') {
...
@@ -356,6 +363,35 @@ 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)"
);
# Associate the new group and new product.
SendSQL
(
"INSERT INTO group_control_map "
.
"(group_id, product_id, entry, "
.
"membercontrol, othercontrol, canedit) VALUES "
.
"($gid, $product_id, "
.
Param
(
"useentrygroupdefault"
)
.
", "
.
CONTROLMAPDEFAULT
.
", "
.
CONTROLMAPNA
.
", 0)"
);
# Permit the new product to use any non-product bug groups.
SendSQL
(
"SELECT groups.id, products.id IS NULL FROM groups "
.
"LEFT JOIN products "
.
"ON groups.name = products.name "
.
"WHERE isactive != 0 AND isbuggroup != 0 "
);
while
(
MoreSQLData
())
{
my
(
$grpid
,
$nonproductgroup
)
=
FetchSQLData
();
if
(
$nonproductgroup
)
{
PushGlobalSQLState
();
SendSQL
(
"INSERT INTO group_control_map "
.
"(group_id, product_id, entry, "
.
"membercontrol, othercontrol, canedit) VALUES "
.
"entry, control, canedit) VALUES "
.
"($grpid, $product_id, 0, "
.
CONTROLMAPSHOWN
.
", "
.
CONTROLMAPNA
.
", 0)"
);
PopGlobalSQLState
();
}
}
}
}
...
@@ -510,7 +546,7 @@ one.";
...
@@ -510,7 +546,7 @@ one.";
print
"<INPUT TYPE=SUBMIT VALUE=\"Yes, delete\">\n"
;
print
"<INPUT TYPE=SUBMIT VALUE=\"Yes, delete\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"delete\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"delete\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"product\" VALUE=\""
.
print
"<INPUT TYPE=HIDDEN NAME=\"product\" VALUE=\""
.
value
_quote
(
$product
)
.
"\">\n"
;
html
_quote
(
$product
)
.
"\">\n"
;
print
"</FORM>"
;
print
"</FORM>"
;
PutTrailer
(
$localtrailer
);
PutTrailer
(
$localtrailer
);
...
@@ -538,6 +574,7 @@ if ($action eq 'delete') {
...
@@ -538,6 +574,7 @@ if ($action eq 'delete') {
versions WRITE,
versions WRITE,
products WRITE,
products WRITE,
groups WRITE,
groups WRITE,
group_control_map WRITE,
profiles WRITE,
profiles WRITE,
milestones WRITE,
milestones WRITE,
flaginclusions WRITE,
flaginclusions WRITE,
...
@@ -583,6 +620,10 @@ if ($action eq 'delete') {
...
@@ -583,6 +620,10 @@ if ($action eq 'delete') {
WHERE product_id=$product_id"
);
WHERE product_id=$product_id"
);
print
"Milestones deleted.<BR>\n"
;
print
"Milestones deleted.<BR>\n"
;
SendSQL
(
"DELETE FROM group_control_map
WHERE product_id=$product_id"
);
print
"Group controls deleted.<BR>\n"
;
SendSQL
(
"DELETE FROM flaginclusions
SendSQL
(
"DELETE FROM flaginclusions
WHERE product_id=$product_id"
);
WHERE product_id=$product_id"
);
SendSQL
(
"DELETE FROM flagexclusions
SendSQL
(
"DELETE FROM flagexclusions
...
@@ -593,7 +634,6 @@ if ($action eq 'delete') {
...
@@ -593,7 +634,6 @@ if ($action eq 'delete') {
WHERE id=$product_id"
);
WHERE id=$product_id"
);
print
"Product '$product' deleted.<BR>\n"
;
print
"Product '$product' deleted.<BR>\n"
;
SendSQL
(
"UNLOCK TABLES"
);
SendSQL
(
"UNLOCK TABLES"
);
unlink
"data/versioncache"
;
unlink
"data/versioncache"
;
...
@@ -693,6 +733,27 @@ if ($action eq 'edit') {
...
@@ -693,6 +733,27 @@ if ($action eq 'edit') {
}
}
print
"</TD>\n</TR><TR>\n"
;
print
"</TD>\n</TR><TR>\n"
;
print
" <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editproducts.cgi?action=editgroupcontrols&product="
,
url_quote
(
$product
),
"\">Edit Group Access Controls</A></TH>\n"
;
print
"<TD>\n"
;
SendSQL
(
"SELECT id, name, isactive, entry, membercontrol, othercontrol, canedit "
.
"FROM groups, "
.
"group_control_map "
.
"WHERE group_control_map.group_id = id AND product_id = $product_id "
.
"AND isbuggroup != 0 ORDER BY name"
);
while
(
MoreSQLData
())
{
my
(
$id
,
$name
,
$isactive
,
$entry
,
$membercontrol
,
$othercontrol
,
$canedit
)
=
FetchSQLData
();
print
"<B>"
.
html_quote
(
$name
)
.
":</B> "
;
if
(
$isactive
)
{
print
$ctl
{
$membercontrol
}
.
"/"
.
$ctl
{
$othercontrol
};
print
", ENTRY"
if
$entry
;
print
", CANEDIT"
if
$canedit
;
}
else
{
print
"DISABLED"
;
}
print
"<BR>\n"
;
}
print
"</TD>\n</TR><TR>\n"
;
print
" <TH ALIGN=\"right\">Bugs:</TH>\n"
;
print
" <TH ALIGN=\"right\">Bugs:</TH>\n"
;
print
" <TD>"
;
print
" <TD>"
;
SendSQL
(
"SELECT count(bug_id),product_id
SendSQL
(
"SELECT count(bug_id),product_id
...
@@ -706,11 +767,11 @@ if ($action eq 'edit') {
...
@@ -706,11 +767,11 @@ if ($action eq 'edit') {
print
"</TD>\n</TR></TABLE>\n"
;
print
"</TD>\n</TR></TABLE>\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"productold\" VALUE=\""
.
print
"<INPUT TYPE=HIDDEN NAME=\"productold\" VALUE=\""
.
value
_quote
(
$product
)
.
"\">\n"
;
html
_quote
(
$product
)
.
"\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"descriptionold\" VALUE=\""
.
print
"<INPUT TYPE=HIDDEN NAME=\"descriptionold\" VALUE=\""
.
value
_quote
(
$description
)
.
"\">\n"
;
html
_quote
(
$description
)
.
"\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"milestoneurlold\" VALUE=\""
.
print
"<INPUT TYPE=HIDDEN NAME=\"milestoneurlold\" VALUE=\""
.
value
_quote
(
$milestoneurl
)
.
"\">\n"
;
html
_quote
(
$milestoneurl
)
.
"\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"disallownewold\" VALUE=\"$disallownew\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"disallownewold\" VALUE=\"$disallownew\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"votesperuserold\" VALUE=\"$votesperuser\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"votesperuserold\" VALUE=\"$votesperuser\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"maxvotesperbugold\" VALUE=\"$maxvotesperbug\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"maxvotesperbugold\" VALUE=\"$maxvotesperbug\">\n"
;
...
@@ -729,6 +790,230 @@ if ($action eq 'edit') {
...
@@ -729,6 +790,230 @@ if ($action eq 'edit') {
}
}
#
# action='updategroupcontrols' -> update the product
#
if
(
$action
eq
'updategroupcontrols'
)
{
my
$product_id
=
get_product_id
(
$product
);
my
@now_na
=
();
my
@now_mandatory
=
();
foreach
my
$f
(
keys
%::
FORM
)
{
if
(
$f
=~
/^membercontrol_(\d+)$/
)
{
my
$id
=
$1
;
if
(
$::FORM
{
$f
}
==
CONTROLMAPNA
)
{
push
@now_na
,
$id
;
}
elsif
(
$::FORM
{
$f
}
==
CONTROLMAPMANDATORY
)
{
push
@now_mandatory
,
$id
;
}
}
}
if
(
!
(
$::FORM
{
'confirmed'
}))
{
$vars
->
{
'form'
}
=
\%::
FORM
;
$vars
->
{
'mform'
}
=
\%::
MFORM
;
my
@na_groups
=
();
if
(
@now_na
)
{
SendSQL
(
"SELECT groups.name, COUNT(bugs.bug_id)
FROM bugs, bug_group_map, groups
WHERE groups.id IN("
.
join
(
','
,
@now_na
)
.
")
AND bug_group_map.group_id = groups.id
AND bug_group_map.bug_id = bugs.bug_id
AND bugs.product_id = $product_id
GROUP BY groups.name"
);
while
(
MoreSQLData
())
{
my
(
$groupname
,
$bugcount
)
=
FetchSQLData
();
my
%
g
=
();
$g
{
'name'
}
=
$groupname
;
$g
{
'count'
}
=
$bugcount
;
push
@na_groups
,
\%
g
;
}
}
my
@mandatory_groups
=
();
if
(
@now_mandatory
)
{
SendSQL
(
"SELECT groups.name, COUNT(bugs.bug_id)
FROM bugs, groups
LEFT JOIN bug_group_map
ON bug_group_map.group_id = groups.id
AND bug_group_map.bug_id = bugs.bug_id
WHERE groups.id IN("
.
join
(
','
,
@now_mandatory
)
.
")
AND bugs.product_id = $product_id
AND bug_group_map.bug_id IS NULL
GROUP BY groups.name"
);
while
(
MoreSQLData
())
{
my
(
$groupname
,
$bugcount
)
=
FetchSQLData
();
my
%
g
=
();
$g
{
'name'
}
=
$groupname
;
$g
{
'count'
}
=
$bugcount
;
push
@mandatory_groups
,
\%
g
;
}
}
if
((
@na_groups
)
||
(
@mandatory_groups
))
{
$vars
->
{
'product'
}
=
$product
;
$vars
->
{
'na_groups'
}
=
\
@na_groups
;
$vars
->
{
'mandatory_groups'
}
=
\
@mandatory_groups
;
$template
->
process
(
"admin/products/groupcontrol/confirm-edit.html.tmpl"
,
$vars
)
||
ThrowTemplateError
(
$template
->
error
());
exit
;
}
}
PutHeader
(
"Update group access controls for product \"$product\""
);
$headerdone
=
1
;
SendSQL
(
"SELECT id, name FROM groups "
.
"WHERE isbuggroup != 0 AND isactive != 0"
);
while
(
MoreSQLData
()){
my
(
$groupid
,
$groupname
)
=
FetchSQLData
();
my
$newmembercontrol
=
$::FORM
{
"membercontrol_$groupid"
}
||
0
;
my
$newothercontrol
=
$::FORM
{
"othercontrol_$groupid"
}
||
0
;
# Legality of control combination is a function of
# membercontrol\othercontrol
# NA SH DE MA
# NA + - - -
# SH + + + +
# DE + - + +
# MA - - - +
unless
((
$newmembercontrol
==
$newothercontrol
)
||
(
$newmembercontrol
==
CONTROLMAPSHOWN
)
||
((
$newmembercontrol
==
CONTROLMAPDEFAULT
)
&&
(
$newothercontrol
!=
CONTROLMAPSHOWN
)))
{
ThrowUserError
(
'illegal_group_control_combination'
,
{
groupname
=>
$groupname
,
header_done
=>
1
});
}
}
SendSQL
(
"LOCK TABLES groups READ,
group_control_map WRITE,
bugs WRITE,
bugs_activity WRITE,
bug_group_map WRITE,
fielddefs READ"
);
SendSQL
(
"SELECT id, name, entry, membercontrol, othercontrol, canedit "
.
"FROM groups "
.
"LEFT JOIN group_control_map "
.
"ON group_control_map.group_id = id AND product_id = $product_id "
.
"WHERE isbuggroup != 0 AND isactive != 0"
);
while
(
MoreSQLData
())
{
my
(
$groupid
,
$groupname
,
$entry
,
$membercontrol
,
$othercontrol
,
$canedit
)
=
FetchSQLData
();
my
$newentry
=
$::FORM
{
"entry_$groupid"
}
||
0
;
my
$newmembercontrol
=
$::FORM
{
"membercontrol_$groupid"
}
||
0
;
my
$newothercontrol
=
$::FORM
{
"othercontrol_$groupid"
}
||
0
;
my
$newcanedit
=
$::FORM
{
"canedit_$groupid"
}
||
0
;
my
$oldentry
=
$entry
;
$entry
=
$entry
||
0
;
$membercontrol
=
$membercontrol
||
0
;
$othercontrol
=
$othercontrol
||
0
;
$canedit
=
$canedit
||
0
;
detaint_natural
(
$newentry
);
detaint_natural
(
$newothercontrol
);
detaint_natural
(
$newmembercontrol
);
detaint_natural
(
$newcanedit
);
if
((
!
defined
(
$oldentry
))
&&
((
$newentry
)
||
(
$newmembercontrol
)
||
(
$newcanedit
)))
{
PushGlobalSQLState
();
SendSQL
(
"INSERT INTO group_control_map "
.
"(group_id, product_id, entry, "
.
"membercontrol, othercontrol, canedit) "
.
"VALUES "
.
"($groupid, $product_id, $newentry, "
.
"$newmembercontrol, $newothercontrol, $newcanedit)"
);
PopGlobalSQLState
();
}
elsif
((
$newentry
!=
$entry
)
||
(
$newmembercontrol
!=
$membercontrol
)
||
(
$newothercontrol
!=
$othercontrol
)
||
(
$newcanedit
!=
$canedit
))
{
PushGlobalSQLState
();
SendSQL
(
"UPDATE group_control_map "
.
"SET entry = $newentry, "
.
"membercontrol = $newmembercontrol, "
.
"othercontrol = $newothercontrol, "
.
"canedit = $newcanedit "
.
"WHERE group_id = $groupid "
.
"AND product_id = $product_id"
);
PopGlobalSQLState
();
}
if
((
$newentry
==
0
)
&&
(
$newmembercontrol
==
0
)
&&
(
$newothercontrol
==
0
)
&&
(
$newcanedit
==
0
))
{
PushGlobalSQLState
();
SendSQL
(
"DELETE FROM group_control_map "
.
"WHERE group_id = $groupid "
.
"AND product_id = $product_id"
);
PopGlobalSQLState
();
}
}
foreach
my
$groupid
(
@now_na
)
{
print
"Removing bugs from NA group "
.
html_quote
(
GroupIdToName
(
$groupid
))
.
"<P>\n"
;
my
$count
=
0
;
SendSQL
(
"SELECT bugs.bug_id,
(lastdiffed >= delta_ts)
FROM bugs, bug_group_map
WHERE group_id = $groupid
AND bug_group_map.bug_id = bugs.bug_id
AND bugs.product_id = $product_id
ORDER BY bugs.bug_id"
);
while
(
MoreSQLData
())
{
my
(
$bugid
,
$mailiscurrent
)
=
FetchSQLData
();
PushGlobalSQLState
();
SendSQL
(
"DELETE FROM bug_group_map WHERE
bug_id = $bugid AND group_id = $groupid"
);
SendSQL
(
"SELECT name, NOW() FROM groups WHERE id = $groupid"
);
my
(
$removed
,
$timestamp
)
=
FetchSQLData
();
LogActivityEntry
(
$bugid
,
"bug_group"
,
$removed
,
""
,
$::userid
,
$timestamp
);
if
(
$mailiscurrent
!=
0
)
{
SendSQL
(
"UPDATE bugs SET lastdiffed = "
.
SqlQuote
(
$timestamp
)
.
" WHERE bug_id = $bugid"
);
}
SendSQL
(
"UPDATE bugs SET delta_ts = "
.
SqlQuote
(
$timestamp
)
.
" WHERE bug_id = $bugid"
);
PopGlobalSQLState
();
$count
++
;
}
print
"dropped $count bugs<p>\n"
;
}
foreach
my
$groupid
(
@now_mandatory
)
{
print
"Adding bugs to Mandatory group "
.
html_quote
(
GroupIdToName
(
$groupid
))
.
"<P>\n"
;
my
$count
=
0
;
SendSQL
(
"SELECT bugs.bug_id,
(lastdiffed >= delta_ts)
FROM bugs
LEFT JOIN bug_group_map
ON bug_group_map.bug_id = bugs.bug_id
AND group_id = $groupid
WHERE bugs.product_id = $product_id
AND bug_group_map.bug_id IS NULL
ORDER BY bugs.bug_id"
);
while
(
MoreSQLData
())
{
my
(
$bugid
,
$mailiscurrent
)
=
FetchSQLData
();
PushGlobalSQLState
();
SendSQL
(
"INSERT INTO bug_group_map (bug_id, group_id)
VALUES ($bugid, $groupid)"
);
SendSQL
(
"SELECT name, NOW() FROM groups WHERE id = $groupid"
);
my
(
$added
,
$timestamp
)
=
FetchSQLData
();
LogActivityEntry
(
$bugid
,
"bug_group"
,
""
,
$added
,
$::userid
,
$timestamp
);
if
(
$mailiscurrent
!=
0
)
{
SendSQL
(
"UPDATE bugs SET lastdiffed = "
.
SqlQuote
(
$timestamp
)
.
" WHERE bug_id = $bugid"
);
}
SendSQL
(
"UPDATE bugs SET delta_ts = "
.
SqlQuote
(
$timestamp
)
.
" WHERE bug_id = $bugid"
);
PopGlobalSQLState
();
$count
++
;
}
print
"added $count bugs<p>\n"
;
}
SendSQL
(
"UNLOCK TABLES"
);
print
"Group control updates done<P>\n"
;
PutTrailer
(
$localtrailer
);
exit
;
}
#
#
# action='update' -> update the product
# action='update' -> update the product
...
@@ -770,6 +1055,7 @@ if ($action eq 'update') {
...
@@ -770,6 +1055,7 @@ if ($action eq 'update') {
SendSQL
(
"LOCK TABLES products WRITE,
SendSQL
(
"LOCK TABLES products WRITE,
versions READ,
versions READ,
groups WRITE,
groups WRITE,
group_control_map WRITE,
profiles WRITE,
profiles WRITE,
milestones READ"
);
milestones READ"
);
...
@@ -863,9 +1149,9 @@ if ($action eq 'update') {
...
@@ -863,9 +1149,9 @@ if ($action eq 'update') {
}
}
SendSQL
(
"UPDATE products SET name=$qp WHERE id=$product_id"
);
SendSQL
(
"UPDATE products SET name=$qp WHERE id=$product_id"
);
# Need to do an update to groups as well. If there is
a corresponding
# Need to do an update to groups as well. If there is
#
bug group, whether usebuggroups is currently set or not, we want to
#
a corresponding bug group, we want to update it so it will
#
update it so it will
match in the future. If there is no group, this
# match in the future. If there is no group, this
# update statement will do nothing, so no harm done. -JMR, 3/8/00
# update statement will do nothing, so no harm done. -JMR, 3/8/00
SendSQL
(
"UPDATE groups "
.
SendSQL
(
"UPDATE groups "
.
"SET name = $qp, "
.
"SET name = $qp, "
.
...
@@ -945,6 +1231,235 @@ if ($action eq 'update') {
...
@@ -945,6 +1231,235 @@ if ($action eq 'update') {
exit
;
exit
;
}
}
#
# action='editgroupcontrols' -> update product group controls
#
if
(
$action
eq
'editgroupcontrols'
)
{
my
$product_id
=
get_product_id
(
$product
);
# Display a group if it is either enabled or has bugs for this product.
SendSQL
(
"SELECT id, name, entry, membercontrol, othercontrol, canedit, "
.
"isactive, COUNT(bugs.bug_id) "
.
"FROM groups "
.
"LEFT JOIN group_control_map "
.
"ON group_control_map.group_id = id "
.
"AND group_control_map.product_id = $product_id "
.
"LEFT JOIN bug_group_map "
.
"ON bug_group_map.group_id = groups.id "
.
"LEFT JOIN bugs "
.
"ON bugs.bug_id = bug_group_map.bug_id "
.
"AND bugs.product_id = $product_id "
.
"WHERE isbuggroup != 0 "
.
"AND (isactive != 0 OR entry IS NOT NULL "
.
"OR bugs.bug_id IS NOT NULL) "
.
"GROUP BY name"
);
my
@groups
=
();
while
(
MoreSQLData
())
{
my
%
group
=
();
my
(
$groupid
,
$groupname
,
$entry
,
$membercontrol
,
$othercontrol
,
$canedit
,
$isactive
,
$bugcount
)
=
FetchSQLData
();
$group
{
'id'
}
=
$groupid
;
$group
{
'name'
}
=
$groupname
;
$group
{
'entry'
}
=
$entry
;
$group
{
'membercontrol'
}
=
$membercontrol
;
$group
{
'othercontrol'
}
=
$othercontrol
;
$group
{
'canedit'
}
=
$canedit
;
$group
{
'isactive'
}
=
$isactive
;
$group
{
'bugcount'
}
=
$bugcount
;
push
@groups
,
\%
group
;
}
$vars
->
{
'header_done'
}
=
$headerdone
;
$vars
->
{
'product'
}
=
$product
;
$vars
->
{
'groups'
}
=
\
@groups
;
$vars
->
{
'const'
}
=
{
'CONTROLMAPNA'
=>
CONTROLMAPNA
,
'CONTROLMAPSHOWN'
=>
CONTROLMAPSHOWN
,
'CONTROLMAPDEFAULT'
=>
CONTROLMAPDEFAULT
,
'CONTROLMAPMANDATORY'
=>
CONTROLMAPMANDATORY
,
};
$template
->
process
(
"admin/products/groupcontrol/edit.html.tmpl"
,
$vars
)
||
ThrowTemplateError
(
$template
->
error
());
exit
;
print
"<!-- \n"
;
print
"<script type=\"text/javascript\">\n"
;
print
"function hide(id) {\n"
;
print
" id.visibility = 0\n"
;
print
" alert(id)\n"
;
print
"}\n"
;
print
"</script>"
;
print
" -->\n"
;
print
"<STYLE type=\"text/css\">\n"
;
print
" .hstyle { visibility: visible; color: red; }\n"
;
print
"</STYLE>\n"
;
print
"<FORM METHOD=POST ACTION=editproducts.cgi>\n"
;
print
"<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0><TR BGCOLOR=\"#6666FF\">\n"
;
print
" <TH ALIGN=\"left\">Group</TH>\n"
;
print
" <TH ALIGN=\"left\">Entry</TH>\n"
;
print
" <TH ALIGN=\"left\">MemberControl</TH>\n"
;
print
" <TH ALIGN=\"left\">OtherControl</TH>\n"
;
print
" <TH ALIGN=\"left\">Canedit</TH>\n"
;
while
(
MoreSQLData
())
{
print
"</TR>\n"
;
my
(
$groupid
,
$groupname
,
$entry
,
$membercontrol
,
$othercontrol
,
$canedit
)
=
FetchSQLData
();
print
"<TR id=\"row_$groupname\" class=\"hstyle\" "
;
print
"onload=\"document.row.row_$groupname.color=green\">\n"
;
print
" <TD>\n"
;
print
" $groupname\n"
;
print
" </TD><TD>\n"
;
$entry
|=
0
;
print
" <INPUT TYPE=CHECKBOX NAME=\"entry_$groupid\" VALUE=1"
;
print
" CHECKED "
if
$entry
;
print
">\n"
;
print
" </TD><TD>\n"
;
$membercontrol
|=
0
;
$othercontrol
|=
0
;
print
" <SELECT NAME=\"membercontrol_$groupid\">\n"
;
print
" <OPTION VALUE="
.
CONTROLMAPNA
;
print
" selected=\"selected\""
if
(
$membercontrol
==
CONTROLMAPNA
);
print
">NA</OPTION>\n"
;
print
" <OPTION VALUE="
.
CONTROLMAPSHOWN
;
print
" selected=\"selected\""
if
(
$membercontrol
==
CONTROLMAPSHOWN
);
print
">Shown</OPTION>\n"
;
print
" <OPTION VALUE="
.
CONTROLMAPDEFAULT
;
print
" selected=\"selected\""
if
(
$membercontrol
==
CONTROLMAPDEFAULT
);
print
">Default</OPTION>\n"
;
print
" <OPTION VALUE="
.
CONTROLMAPMANDATORY
;
print
" selected=\"selected\""
if
(
$membercontrol
==
CONTROLMAPMANDATORY
);
print
">Mandatory</OPTION>\n"
;
print
"</SELECT>\n"
;
print
" </TD><TD>\n"
;
print
" <SELECT NAME=\"othercontrol_$groupid\">\n"
;
print
" <OPTION VALUE="
.
CONTROLMAPNA
;
print
" selected=\"selected\""
if
(
$othercontrol
==
CONTROLMAPNA
);
print
">NA</OPTION>\n"
;
print
" <OPTION VALUE="
.
CONTROLMAPSHOWN
;
print
" selected=\"selected\""
if
(
$othercontrol
==
CONTROLMAPSHOWN
);
print
">Shown</OPTION>\n"
;
print
" <OPTION VALUE="
.
CONTROLMAPDEFAULT
;
print
" selected=\"selected\""
if
(
$othercontrol
==
CONTROLMAPDEFAULT
);
print
">Default</OPTION>\n"
;
print
" <OPTION VALUE="
.
CONTROLMAPMANDATORY
;
print
" selected=\"selected\""
if
(
$othercontrol
==
CONTROLMAPMANDATORY
);
print
">Mandatory</OPTION>\n"
;
print
"</SELECT>\n"
;
print
" </TD><TD>\n"
;
$canedit
|=
0
;
print
" <INPUT TYPE=CHECKBOX NAME=\"canedit_$groupid\" VALUE=1"
;
print
" CHECKED "
if
$canedit
;
print
">\n"
;
}
print
"</TR>\n"
;
print
"</TABLE><BR>"
;
print
"Add controls to the panel above:<BR>\n"
;
print
"<SELECT NAME=\"newgroups\" SIZE=\"10\" MULTIPLE=\"MULTIPLE\">\n"
;
SendSQL
(
"SELECT id, name "
.
"FROM groups "
.
"LEFT JOIN group_control_map "
.
"ON group_control_map.group_id = id AND product_id = $product_id "
.
"WHERE canedit IS NULL AND isbuggroup != 0 AND isactive != 0 "
.
"ORDER BY name"
);
while
(
MoreSQLData
())
{
my
(
$groupid
,
$groupname
)
=
FetchSQLData
();
print
"<OPTION VALUE=\"$groupid\">$groupname</OPTION>\n"
;
}
print
"</SELECT><BR><BR>\n"
;
print
"<INPUT TYPE=SUBMIT VALUE=\"Update\">\n"
;
print
"<INPUT TYPE=RESET>\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"updategroupcontrols\">\n"
;
print
"<INPUT TYPE=HIDDEN NAME=\"product\" VALUE=\"$product\">\n"
;
print
"</FORM>\n"
;
print
"<P>note: Any group controls Set to NA/NA with no other checkboxes "
;
print
"will automatically be removed from the panel the next time "
;
print
"update is clicked.\n"
;
print
"<P>These settings control the relationship of the groups to this "
;
print
"product.\n"
;
print
"<P>If any group has <B>Entry</B> selected, then this product will "
;
print
"restrict bug entry to only those users who are members of all the "
;
print
"groups with entry selected.\n"
;
print
"<P>If any group has <B>Canedit</B> selected, then this product "
;
print
"will be read-only for any users who are not members of all of "
;
print
"the groups with Canedit selected. ONLY users who are members of "
;
print
"all the canedit groups will be able to edit. This is an additional "
;
print
"restriction that further restricts what can be edited by a user.\n"
;
print
"<P>The <B>MemberControl</B> and <B>OtherControl</B> fields "
;
print
"indicate which bugs will be placed in "
;
print
"this group according to the following definitions.\n"
;
print
"<BR><TABLE BORDER=1>"
;
print
"<TR>"
;
print
"<TH>MemberControl</TH><TH>OtherControl</TH><TH>Interpretation</TH>"
;
print
"</TR><TR>"
;
print
"<TD>NA</TD>\n"
;
print
"<TD>NA</TD>\n"
;
print
"<TD>Bugs in this product are never associated with this group.</TD>\n"
;
print
"</TR><TR>"
;
print
"<TD>Shown</TD>\n"
;
print
"<TD>NA</TD>\n"
;
print
"<TD>Bugs in this product are permitted to be restricted to this "
;
print
"group. Users who are a member of this group will be able "
;
print
"to place bugs in this group.</TD>\n"
;
print
"</TR><TR>"
;
print
"<TD>Shown</TD>\n"
;
print
"<TD>Shown</TD>\n"
;
print
"<TD>Bugs in this product can be placed in this group by anyone "
;
print
"with permission to edit the bug even if they are not a member "
;
print
"of this group.</TD>\n"
;
print
"</TR><TR>"
;
print
"<TD>Shown</TD>\n"
;
print
"<TD>Default</TD>\n"
;
print
"<TD>Bugs in this product can be placed in this group by anyone "
;
print
"with permission to edit the bug even if they are not a member "
;
print
"of this group. Non-members place bugs in this group by default."
;
print
"</TD>\n"
;
print
"</TR><TR>"
;
print
"<TD>Shown</TD>\n"
;
print
"<TD>Mandatory</TD>\n"
;
print
"<TD>Bugs in this product are permitted to be restricted to this "
;
print
"group. Users who are a member of this group will be able "
;
print
"to place bugs in this group."
;
print
"Non-members will be forced to restrict bugs to this group "
;
print
"when they initially enter a bug in this product."
;
print
"</TD>\n"
;
print
"</TR><TR>"
;
print
"<TD>Default</TD>\n"
;
print
"<TD>NA</TD>\n"
;
print
"<TD>Bugs in this product are permitted to be restricted to this "
;
print
"group and are placed in this group by default."
;
print
"Users who are a member of this group will be able "
;
print
"to place bugs in this group.</TD>\n"
;
print
"</TR><TR>"
;
print
"<TD>Default</TD>\n"
;
print
"<TD>Default</TD>\n"
;
print
"<TD>Bugs in this product are permitted to be restricted to this "
;
print
"group and are placed in this group by default."
;
print
"Users who are a member of this group will be able "
;
print
"to place bugs in this group. Non-members will be able to "
;
print
"restrict bugs to this group on entry and will do so by default "
;
print
"</TD>\n"
;
print
"</TR><TR>"
;
print
"<TD>Default</TD>\n"
;
print
"<TD>Mandatory</TD>\n"
;
print
"<TD>Bugs in this product are permitted to be restricted to this "
;
print
"group and are placed in this group by default."
;
print
"Users who are a member of this group will be able "
;
print
"to place bugs in this group. Non-members will be forced "
;
print
"to place bugs in this group on entry."
;
print
"</TR><TR>"
;
print
"<TD>Mandatory</TD>\n"
;
print
"<TD>Mandatory</TD>\n"
;
print
"<TD>Bugs in this product are required to be restricted to this "
;
print
"group. Users are not given any option.</TD>\n"
;
print
"</TABLE>"
;
PutTrailer
(
$localtrailer
);
exit
;
}
#
#
...
...
enter_bug.cgi
View file @
c64d5111
...
@@ -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, w
e need to check and make sure
#
W
e 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
=
...
...
globals.pl
View file @
c64d5111
...
@@ -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
;
post_bug.cgi
View file @
c64d5111
...
@@ -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,9 +102,8 @@ if (defined $::FORM{'maketemplate'}) {
...
@@ -101,9 +102,8 @@ 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
});
}
}
my
$component_id
=
get_component_id
(
$product_id
,
$::FORM
{
component
});
my
$component_id
=
get_component_id
(
$product_id
,
$::FORM
{
component
});
...
@@ -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
...
...
process_bug.cgi
View file @
c64d5111
...
@@ -31,6 +31,7 @@ my $UserInCanConfirmGroupSet = -1;
...
@@ -31,6 +31,7 @@ my $UserInCanConfirmGroupSet = -1;
use
lib
qw(.)
;
use
lib
qw(.)
;
use
Bugzilla::
Constants
;
require
"CGI.pl"
;
require
"CGI.pl"
;
require
"bug_form.pl"
;
require
"bug_form.pl"
;
...
@@ -236,7 +237,7 @@ if ((($::FORM{'id'} && $::FORM{'product'} ne $::oldproduct)
...
@@ -236,7 +237,7 @@ if ((($::FORM{'id'} && $::FORM{'product'} ne $::oldproduct)
# If the product-specific fields need to be verified, or we need to verify
# If the product-specific fields need to be verified, or we need to verify
# whether or not to add the bugs to their new product's group, display
# whether or not to add the bugs to their new product's group, display
# a verification form.
# a verification form.
if
(
!
$vok
||
!
$cok
||
!
$mok
||
(
Param
(
'usebuggroups'
)
&&
!
defined
(
$::FORM
{
'addtonewgroup'
})))
{
if
(
!
$vok
||
!
$cok
||
!
$mok
||
(
AnyDefaultGroups
(
)
&&
!
defined
(
$::FORM
{
'addtonewgroup'
})))
{
$vars
->
{
'form'
}
=
\%::
FORM
;
$vars
->
{
'form'
}
=
\%::
FORM
;
$vars
->
{
'mform'
}
=
\%::
MFORM
;
$vars
->
{
'mform'
}
=
\%::
MFORM
;
...
@@ -276,7 +277,7 @@ if ((($::FORM{'id'} && $::FORM{'product'} ne $::oldproduct)
...
@@ -276,7 +277,7 @@ if ((($::FORM{'id'} && $::FORM{'product'} ne $::oldproduct)
$vars
->
{
"verify_fields"
}
=
0
;
$vars
->
{
"verify_fields"
}
=
0
;
}
}
$vars
->
{
'verify_bug_group'
}
=
(
Param
(
'usebuggroups'
)
$vars
->
{
'verify_bug_group'
}
=
(
AnyDefaultGroups
(
)
&&
!
defined
(
$::FORM
{
'addtonewgroup'
}));
&&
!
defined
(
$::FORM
{
'addtonewgroup'
}));
$template
->
process
(
"bug/process/verify-new-product.html.tmpl"
,
$vars
)
$template
->
process
(
"bug/process/verify-new-product.html.tmpl"
,
$vars
)
...
@@ -594,11 +595,9 @@ sub ChangeResolution {
...
@@ -594,11 +595,9 @@ sub ChangeResolution {
# select lists. This means that instead of looking for the bit-X values in
# select lists. This means that instead of looking for the bit-X values in
# the form, we need to loop through all the bug groups this user has access
# the form, we need to loop through all the bug groups this user has access
# to, and for each one, see if it's selected.
# to, and for each one, see if it's selected.
# In order to make mass changes work correctly, keep a sum of bits for groups
# added, and another one for groups removed, and then let mysql do the bit
# operations
# If the form element isn't present, or the user isn't in the group, leave
# If the form element isn't present, or the user isn't in the group, leave
# it as-is
# it as-is
my
@groupAdd
=
();
my
@groupAdd
=
();
my
@groupDel
=
();
my
@groupDel
=
();
...
@@ -1070,7 +1069,10 @@ foreach my $id (@idlist) {
...
@@ -1070,7 +1069,10 @@ foreach my $id (@idlist) {
"bug_group_map $write, flags $write, duplicates $write,"
.
"bug_group_map $write, flags $write, duplicates $write,"
.
"user_group_map READ, flagtypes READ, "
.
"user_group_map READ, flagtypes READ, "
.
"flaginclusions AS i READ, flagexclusions AS e READ, "
.
"flaginclusions AS i READ, flagexclusions AS e READ, "
.
"keyworddefs READ, groups READ, attachments READ"
);
"keyworddefs READ, groups READ, attachments READ, "
.
"group_control_map AS oldcontrolmap READ, "
.
"group_control_map AS newcontrolmap READ, "
.
"group_control_map READ"
);
my
@oldvalues
=
SnapShotBug
(
$id
);
my
@oldvalues
=
SnapShotBug
(
$id
);
my
%
oldhash
;
my
%
oldhash
;
# Fun hack. @::log_columns only contains the component_id,
# Fun hack. @::log_columns only contains the component_id,
...
@@ -1104,6 +1106,18 @@ foreach my $id (@idlist) {
...
@@ -1104,6 +1106,18 @@ foreach my $id (@idlist) {
$i
++
;
$i
++
;
}
}
$oldhash
{
'product'
}
=
get_product_name
(
$oldhash
{
'product_id'
});
$oldhash
{
'product'
}
=
get_product_name
(
$oldhash
{
'product_id'
});
if
(
!
CanEditProductId
(
$oldhash
{
'product_id'
}))
{
$vars
->
{
'product'
}
=
$oldhash
{
'product'
};
ThrowUserError
(
"product_edit_denied"
);
}
if
(
defined
$::FORM
{
'product'
}
&&
$::FORM
{
'product'
}
ne
$::FORM
{
'dontchange'
}
&&
$::FORM
{
'product'
}
ne
$oldhash
{
'product'
}
&&
!
CanEnterProduct
(
$::FORM
{
'product'
}))
{
$vars
->
{
'product'
}
=
$::FORM
{
'product'
};
ThrowUserError
(
"entry_access_denied"
);
}
if
(
$requiremilestone
)
{
if
(
$requiremilestone
)
{
my
$value
=
$::FORM
{
'target_milestone'
};
my
$value
=
$::FORM
{
'target_milestone'
};
if
(
!
defined
$value
||
$value
eq
$::FORM
{
'dontchange'
})
{
if
(
!
defined
$value
||
$value
eq
$::FORM
{
'dontchange'
})
{
...
@@ -1268,6 +1282,7 @@ foreach my $id (@idlist) {
...
@@ -1268,6 +1282,7 @@ foreach my $id (@idlist) {
if
(
$::comma
ne
""
)
{
if
(
$::comma
ne
""
)
{
SendSQL
(
$query
);
SendSQL
(
$query
);
}
}
# Check for duplicates if the bug is [re]open
# Check for duplicates if the bug is [re]open
SendSQL
(
"SELECT resolution FROM bugs WHERE bug_id = $id"
);
SendSQL
(
"SELECT resolution FROM bugs WHERE bug_id = $id"
);
my
$resolution
=
FetchOneColumn
();
my
$resolution
=
FetchOneColumn
();
...
@@ -1275,8 +1290,34 @@ foreach my $id (@idlist) {
...
@@ -1275,8 +1290,34 @@ foreach my $id (@idlist) {
SendSQL
(
"DELETE FROM duplicates WHERE dupe = $id"
);
SendSQL
(
"DELETE FROM duplicates WHERE dupe = $id"
);
}
}
my
$newproduct_id
=
$oldhash
{
'product_id'
};
if
((
defined
$::FORM
{
'product'
})
&&
(
$::FORM
{
'product'
}
ne
$::FORM
{
'dontchange'
}))
{
my
$newproduct_id
=
get_product_id
(
$::FORM
{
'product'
});
}
my
%
groupsrequired
=
();
my
%
groupsforbidden
=
();
SendSQL
(
"SELECT id, membercontrol
FROM groups LEFT JOIN group_control_map
ON id = group_id
AND product_id = $newproduct_id WHERE isactive != 0"
);
while
(
MoreSQLData
())
{
my
(
$group
,
$control
)
=
FetchSQLData
();
$control
||=
0
;
unless
(
$control
>
&::
CONTROLMAPNA
)
{
$groupsforbidden
{
$group
}
=
1
;
}
if
(
$control
==
&::
CONTROLMAPMANDATORY
)
{
$groupsrequired
{
$group
}
=
1
;
}
}
my
@groupAddNames
=
();
my
@groupAddNames
=
();
foreach
my
$grouptoadd
(
@groupAdd
)
{
my
@groupAddNamesAll
=
();
foreach
my
$grouptoadd
(
@groupAdd
,
keys
%
groupsrequired
)
{
next
if
$groupsforbidden
{
$grouptoadd
};
push
(
@groupAddNamesAll
,
GroupIdToName
(
$grouptoadd
));
if
(
!
BugInGroupId
(
$id
,
$grouptoadd
))
{
if
(
!
BugInGroupId
(
$id
,
$grouptoadd
))
{
push
(
@groupAddNames
,
GroupIdToName
(
$grouptoadd
));
push
(
@groupAddNames
,
GroupIdToName
(
$grouptoadd
));
SendSQL
(
"INSERT INTO bug_group_map (bug_id, group_id)
SendSQL
(
"INSERT INTO bug_group_map (bug_id, group_id)
...
@@ -1284,7 +1325,10 @@ foreach my $id (@idlist) {
...
@@ -1284,7 +1325,10 @@ foreach my $id (@idlist) {
}
}
}
}
my
@groupDelNames
=
();
my
@groupDelNames
=
();
foreach
my
$grouptodel
(
@groupDel
)
{
my
@groupDelNamesAll
=
();
foreach
my
$grouptodel
(
@groupDel
,
keys
%
groupsforbidden
)
{
push
(
@groupDelNamesAll
,
GroupIdToName
(
$grouptodel
));
next
if
$groupsrequired
{
$grouptodel
};
if
(
BugInGroupId
(
$id
,
$grouptodel
))
{
if
(
BugInGroupId
(
$id
,
$grouptodel
))
{
push
(
@groupDelNames
,
GroupIdToName
(
$grouptodel
));
push
(
@groupDelNames
,
GroupIdToName
(
$grouptodel
));
}
}
...
@@ -1399,63 +1443,117 @@ foreach my $id (@idlist) {
...
@@ -1399,63 +1443,117 @@ foreach my $id (@idlist) {
# group or add it to the new one. There are a very specific series of
# group or add it to the new one. There are a very specific series of
# conditions under which these activities take place, more information
# conditions under which these activities take place, more information
# about which can be found in comments within the conditionals below.
# about which can be found in comments within the conditionals below.
# Check if the user has changed the product to which the bug belongs;
if
(
if
(
# the "usebuggroups" parameter is on, indicating that products
defined
$::FORM
{
'product'
}
# are associated with groups of the same name;
Param
(
'usebuggroups'
)
# the user has changed the product to which the bug belongs;
&&
defined
$::FORM
{
'product'
}
&&
$::FORM
{
'product'
}
ne
$::FORM
{
'dontchange'
}
&&
$::FORM
{
'product'
}
ne
$::FORM
{
'dontchange'
}
&&
$::FORM
{
'product'
}
ne
$oldhash
{
'product'
}
&&
$::FORM
{
'product'
}
ne
$oldhash
{
'product'
}
)
{
)
{
if
(
my
$newproduct_id
=
get_product_id
(
$::FORM
{
'product'
});
# the user wants to add the bug to the new product's group;
# Depending on the "addtonewgroup" variable, groups with
(
$::FORM
{
'addtonewgroup'
}
eq
'yes'
# defaults will change.
||
(
$::FORM
{
'addtonewgroup'
}
eq
'yesifinold'
#
&&
BugInGroup
(
$id
,
$oldhash
{
'product'
})))
# For each group, determine
# - The group id and if it is active
# the new product is associated with a group;
# - The control map value for the old product and this group
&&
GroupExists
(
$::FORM
{
'product'
})
# - The control map value for the new product and this group
# - Is the user in this group?
# the bug is not already in the group; (This can happen when the user
# - Is the bug in this group?
# goes to the "edit multiple bugs" form with a list of bugs at least
SendSQL
(
"SELECT DISTINCT groups.id, isactive, "
.
# one of which is in the new group. In this situation, the user can
"oldcontrolmap.membercontrol, newcontrolmap.membercontrol, "
.
# simultaneously change the bugs to a new product and move the bugs
"user_group_map.user_id IS NOT NULL, "
.
# into that product's group, which happens earlier in this script
"bug_group_map.group_id IS NOT NULL "
.
# and thus is already done. If we didn't check for this, then this
"FROM groups "
.
# situation would cause us to add the bug to the group twice, which
"LEFT JOIN group_control_map AS oldcontrolmap "
.
# would result in the bug being added to a totally different group.)
"ON oldcontrolmap.group_id = groups.id "
.
&&
!
BugInGroup
(
$id
,
$::FORM
{
'product'
})
"AND oldcontrolmap.product_id = "
.
$oldhash
{
'product_id'
}
.
" LEFT JOIN group_control_map AS newcontrolmap "
.
# the user is a member of the associated group, indicating they
"ON newcontrolmap.group_id = groups.id "
.
# are authorized to add bugs to that group, *or* the "usebuggroupsentry"
"AND newcontrolmap.product_id = $newproduct_id "
.
# parameter is off, indicating that users can add bugs to a product
"LEFT JOIN user_group_map "
.
# regardless of whether or not they belong to its associated group;
"ON user_group_map.group_id = groups.id "
.
&&
(
UserInGroup
(
$::FORM
{
'product'
})
||
!
Param
(
'usebuggroupsentry'
))
"AND user_group_map.user_id = $::userid "
.
"AND user_group_map.isbless = 0 "
.
# the associated group is active, indicating it can accept new bugs;
"LEFT JOIN bug_group_map "
.
&&
GroupIsActive
(
GroupNameToId
(
$::FORM
{
'product'
}))
"ON bug_group_map.group_id = groups.id "
.
)
{
"AND bug_group_map.bug_id = $id "
# Add the bug to the group associated with its new product.
);
my
$groupid
=
GroupNameToId
(
$::FORM
{
'product'
});
my
@groupstoremove
=
();
if
(
!
BugInGroupId
(
$id
,
$groupid
))
{
my
@groupstoadd
=
();
SendSQL
(
"INSERT INTO bug_group_map (bug_id, group_id) VALUES ($id, $groupid)"
);
my
@defaultstoremove
=
();
my
@defaultstoadd
=
();
my
@allgroups
=
();
my
$buginanydefault
=
0
;
my
$buginanychangingdefault
=
0
;
while
(
MoreSQLData
())
{
my
(
$groupid
,
$isactive
,
$oldcontrol
,
$newcontrol
,
$useringroup
,
$bugingroup
)
=
FetchSQLData
();
# An undefined newcontrol is none.
$newcontrol
=
CONTROLMAPNA
unless
$newcontrol
;
$oldcontrol
=
CONTROLMAPNA
unless
$oldcontrol
;
push
(
@allgroups
,
$groupid
);
if
((
$bugingroup
)
&&
(
$isactive
)
&&
(
$oldcontrol
==
CONTROLMAPDEFAULT
))
{
# Bug was in a default group.
$buginanydefault
=
1
;
if
(
$newcontrol
!=
CONTROLMAPDEFAULT
)
{
# Bug was in a default group that no longer is.
$buginanychangingdefault
=
1
;
push
(
@defaultstoremove
,
$groupid
);
}
}
if
((
$isactive
)
&&
(
!
$bugingroup
)
&&
(
$newcontrol
==
CONTROLMAPDEFAULT
)
&&
(
$useringroup
))
{
push
(
@defaultstoadd
,
$groupid
);
}
if
((
$bugingroup
)
&&
(
$isactive
)
&&
(
$newcontrol
==
CONTROLMAPNA
))
{
# Group is no longer permitted.
push
(
@groupstoremove
,
$groupid
);
}
if
((
!
$bugingroup
)
&&
(
$isactive
)
&&
(
$newcontrol
==
CONTROLMAPMANDATORY
))
{
# Group is now required.
push
(
@groupstoadd
,
$groupid
);
}
}
}
}
# If addtonewgroups = "yes", old default groups will be removed
if
(
# and new default groups will be added.
# the old product is associated with a group;
# If addtonewgroups = "yesifinold", old default groups will be removed
GroupExists
(
$oldhash
{
'product'
})
# and new default groups will be added only if the bug was in ANY
# of the old default groups.
# the bug is a member of that group;
# If addtonewgroups = "no", old default groups will be removed and not
&&
BugInGroup
(
$id
,
$oldhash
{
'product'
})
# replaced.
)
{
push
(
@groupstoremove
,
@defaultstoremove
);
# Remove the bug from the group associated with its old product.
if
(
AnyDefaultGroups
()
my
$groupid
=
GroupNameToId
(
$oldhash
{
'product'
});
&&
((
$::FORM
{
'addtonewgroup'
}
eq
'yes'
)
SendSQL
(
"DELETE FROM bug_group_map WHERE bug_id = $id AND group_id = $groupid"
);
||
((
$::FORM
{
'addtonewgroup'
}
eq
'yesifinold'
)
&&
(
$buginanydefault
))))
{
push
(
@groupstoadd
,
@defaultstoadd
);
}
}
# Now actually update the bug_group_map.
my
@DefGroupsAdded
=
();
my
@DefGroupsRemoved
=
();
foreach
my
$groupid
(
@allgroups
)
{
my
$thisadd
=
grep
(
(
$_
==
$groupid
),
@groupstoadd
);
my
$thisdel
=
grep
(
(
$_
==
$groupid
),
@groupstoremove
);
if
(
$thisadd
)
{
push
(
@DefGroupsAdded
,
GroupIdToName
(
$groupid
));
SendSQL
(
"INSERT INTO bug_group_map (bug_id, group_id) VALUES "
.
"($id, $groupid)"
);
}
elsif
(
$thisdel
)
{
push
(
@DefGroupsRemoved
,
GroupIdToName
(
$groupid
));
SendSQL
(
"DELETE FROM bug_group_map WHERE bug_id = $id "
.
"AND group_id = $groupid"
);
}
}
if
((
@DefGroupsAdded
)
||
(
@DefGroupsRemoved
))
{
LogActivityEntry
(
$id
,
"bug_group"
,
join
(
', '
,
@DefGroupsRemoved
),
join
(
', '
,
@DefGroupsAdded
),
$whoid
,
$timestamp
);
}
}
}
# get a snapshot of the newly set values out of the database,
# get a snapshot of the newly set values out of the database,
...
@@ -1471,7 +1569,6 @@ foreach my $id (@idlist) {
...
@@ -1471,7 +1569,6 @@ foreach my $id (@idlist) {
$newhash
{
$col
}
=
$newvalues
[
$i
];
$newhash
{
$col
}
=
$newvalues
[
$i
];
$i
++
;
$i
++
;
}
}
# for passing to processmail to ensure that when someone is removed
# for passing to processmail to ensure that when someone is removed
# from one of these fields, they get notified of that fact (if desired)
# from one of these fields, they get notified of that fact (if desired)
#
#
...
...
query.cgi
View file @
c64d5111
...
@@ -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
;
...
...
queryhelp.cgi
View file @
c64d5111
...
@@ -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
++
;
...
...
reports.cgi
View file @
c64d5111
...
@@ -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, w
e don't want people to be able to view
#
W
e 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
...
...
sanitycheck.cgi
View file @
c64d5111
...
@@ -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
###########################################################################
###########################################################################
...
...
template/en/default/admin/products/groupcontrol/confirm-edit.html.tmpl
0 → 100644
View file @
c64d5111
<!-- 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 %]
template/en/default/admin/products/groupcontrol/edit.html.tmpl
0 → 100644
View file @
c64d5111
<!-- 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 %]
template/en/default/bug/edit.html.tmpl
View file @
c64d5111
...
@@ -405,20 +405,28 @@
...
@@ -405,20 +405,28 @@
<br>
<br>
[% IF groups.size > 0 %]
[% IF groups.size > 0 %]
<br>
<b>Only users in all of the selected groups can view this bug:</b>
<br>
<font size="-1">(Unchecking all boxes makes this a public bug.)</font>
<br>
<br>
[% FOREACH group = groups %]
[% FOREACH group = groups %]
[% IF NOT group.mandatory %]
[% IF NOT emitted_description %]
[% emitted_description = 1 %]
<br>
<b>Only users in all of the selected groups can view this bug:</b>
<br>
<font size="-1">
(Unchecking all boxes makes this a more public bug.)
</font>
<br>
<br>
[% END %]
<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 %]
[% " disabled=\"disabled\"" IF NOT group.ingroup %]>
[% " disabled=\"disabled\"" IF NOT group.ingroup %]>
[% group.description %]
[% group.description %]
<br>
<br>
[% END %]
[% END %]
[% END %]
[% IF NOT user.inallgroups %]
[% IF NOT user.inallgroups %]
...
@@ -431,7 +439,7 @@
...
@@ -431,7 +439,7 @@
[% IF bug.inagroup %]
[% IF bug.inagroup %]
<p>
<p>
<b>
But u
sers in the roles selected below can always view this bug:</b>
<b>
U
sers in the roles selected below can always view this bug:</b>
<br>
<br>
<small>
<small>
(The assignee
(The assignee
...
...
template/en/default/bug/process/verify-new-product.html.tmpl
View file @
c64d5111
...
@@ -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 %]
...
...
template/en/default/global/user-error.html.tmpl
View file @
c64d5111
...
@@ -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>\ ( ) & < > , ; : " [ ]</tt>, or any whitespace.
<tt>\ ( ) & < > , ; : " [ ]</tt>, or any whitespace.
[% ELSIF error == "illegal_group_control_combination" %]
[% title = "Your Group Control Combination Is Illegal" %]
Your group control combination for group "
[% groupname FILTER html %]
" 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.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment