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

Bug 240325: Keep regexp-based groups up-to-date

parent 769f4071
...@@ -50,6 +50,10 @@ use base qw(Exporter); ...@@ -50,6 +50,10 @@ use base qw(Exporter);
LOGOUT_ALL LOGOUT_ALL
LOGOUT_CURRENT LOGOUT_CURRENT
LOGOUT_KEEP_CURRENT LOGOUT_KEEP_CURRENT
GRANT_DIRECT
GRANT_DERIVED
GRANT_REGEXP
); );
@Bugzilla::Constants::EXPORT_OK = qw(contenttypes); @Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
...@@ -114,4 +118,8 @@ use constant contenttypes => ...@@ -114,4 +118,8 @@ use constant contenttypes =>
"ics" => "text/calendar" , "ics" => "text/calendar" ,
}; };
use constant GRANT_DIRECT => 0;
use constant GRANT_DERIVED => 1;
use constant GRANT_REGEXP => 2;
1; 1;
...@@ -35,6 +35,7 @@ package Bugzilla::User; ...@@ -35,6 +35,7 @@ package Bugzilla::User;
use Bugzilla::Config; use Bugzilla::Config;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Constants;
################################################################################ ################################################################################
# Functions # Functions
...@@ -246,9 +247,10 @@ sub derive_groups { ...@@ -246,9 +247,10 @@ sub derive_groups {
# first remove any old derived stuff for this user # first remove any old derived stuff for this user
$dbh->do(q{DELETE FROM user_group_map $dbh->do(q{DELETE FROM user_group_map
WHERE user_id = ? WHERE user_id = ?
AND isderived = 1}, AND grant_type != ?},
undef, undef,
$id); $id,
GRANT_DIRECT);
my %groupidsadded = (); my %groupidsadded = ();
# add derived records for any matching regexps # add derived records for any matching regexps
...@@ -260,10 +262,10 @@ sub derive_groups { ...@@ -260,10 +262,10 @@ sub derive_groups {
while (my $row = $sth->fetch) { while (my $row = $sth->fetch) {
if ($self->{login} =~ m/$row->[1]/i) { if ($self->{login} =~ m/$row->[1]/i) {
$group_insert ||= $dbh->prepare(q{INSERT INTO user_group_map $group_insert ||= $dbh->prepare(q{INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES (?, ?, 0, 1)}); VALUES (?, ?, 0, ?)});
$groupidsadded{$row->[0]} = 1; $groupidsadded{$row->[0]} = 1;
$group_insert->execute($id, $row->[0]); $group_insert->execute($id, $row->[0], GRANT_REGEXP);
} }
} }
...@@ -294,9 +296,9 @@ sub derive_groups { ...@@ -294,9 +296,9 @@ sub derive_groups {
if (!$groupidsadded{$groupid}) { if (!$groupidsadded{$groupid}) {
$groupidsadded{$groupid} = 1; $groupidsadded{$groupid} = 1;
$group_insert ||= $dbh->prepare(q{INSERT INTO user_group_map $group_insert ||= $dbh->prepare(q{INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES (?, ?, 0, 1)}); VALUES (?, ?, 0, ?)});
$group_insert->execute($id, $groupid); $group_insert->execute($id, $groupid, GRANT_DERIVED);
} }
} }
} }
......
...@@ -1894,16 +1894,17 @@ $table{tokens} = ...@@ -1894,16 +1894,17 @@ $table{tokens} =
# directly or due to regexp and which groups can be blessed # directly or due to regexp and which groups can be blessed
# by a user. # by a user.
# #
# isderived: # grant_type:
# if 0 - record was explicitly granted # if GRANT_DIRECT - record was explicitly granted
# if 1 - record was created by evaluating a regexp or group hierarchy # if GRANT_DERIVED - record was derived from expanding a group hierarchy
# if GRANT_REGEXP - record was created by evaluating a regexp
$table{user_group_map} = $table{user_group_map} =
'user_id mediumint not null, 'user_id mediumint not null,
group_id mediumint not null, group_id mediumint not null,
isbless tinyint not null default 0, isbless tinyint not null default 0,
isderived tinyint not null default 0, grant_type tinyint not null default 0,
unique(user_id, group_id, isderived, isbless)'; unique(user_id, group_id, grant_type, isbless)';
$table{group_group_map} = $table{group_group_map} =
'member_id mediumint not null, 'member_id mediumint not null,
...@@ -3455,8 +3456,8 @@ if (GetFieldDef("profiles", "groupset")) { ...@@ -3455,8 +3456,8 @@ if (GetFieldDef("profiles", "groupset")) {
$sth3->execute(); $sth3->execute();
if ( !$sth3->fetchrow_array() ) { if ( !$sth3->fetchrow_array() ) {
$dbh->do("INSERT INTO user_group_map $dbh->do("INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES($uid, $gid, 0, 0)"); VALUES($uid, $gid, 0, " . GRANT_DIRECT . ")");
} }
} }
# Create user can bless group grants for old groupsets. # Create user can bless group grants for old groupsets.
...@@ -3466,8 +3467,8 @@ if (GetFieldDef("profiles", "groupset")) { ...@@ -3466,8 +3467,8 @@ if (GetFieldDef("profiles", "groupset")) {
$sth2->execute(); $sth2->execute();
while (my ($uid) = $sth2->fetchrow_array) { while (my ($uid) = $sth2->fetchrow_array) {
$dbh->do("INSERT INTO user_group_map $dbh->do("INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES($uid, $gid, 1, 0)"); VALUES($uid, $gid, 1, " . GRANT_DIRECT . ")");
} }
# Create bug_group_map records for old groupsets. # Create bug_group_map records for old groupsets.
# Get each bug with the old group bit set. # Get each bug with the old group bit set.
...@@ -3899,6 +3900,36 @@ if (!$series_exists) { ...@@ -3899,6 +3900,36 @@ if (!$series_exists) {
AddFDef("owner_idle_time", "Time Since Owner Touched", 0); AddFDef("owner_idle_time", "Time Since Owner Touched", 0);
# 2004-04-12 - Keep regexp-based group permissions up-to-date - Bug 240325
if (GetFieldDef("user_group_map", "isderived")) {
AddField('user_group_map', 'grant_type', 'tinyint not null default 0');
$dbh->do("UPDATE user_group_map SET grant_type = " .
"IF(isderived, " . GRANT_DERIVED . ", " .
GRANT_DIRECT . ")");
$dbh->do("DELETE FROM user_group_map
WHERE isbless = 0 AND grant_type != " . GRANT_DIRECT);
DropField("user_group_map", "isderived");
DropIndexes("user_group_map");
$dbh->do("ALTER TABLE user_group_map
ADD UNIQUE (user_id, group_id, grant_type, isbless)");
# Evaluate regexp-based group memberships
my $sth = $dbh->prepare("SELECT profiles.userid, profiles.login_name,
groups.id, groups.userregexp
FROM profiles, groups
WHERE userregexp != ''");
$sth->execute();
my $sth2 = $dbh->prepare("INSERT IGNORE INTO user_group_map
(user_id, group_id, isbless, grant_type)
VALUES(?, ?, 0, " . GRANT_REGEXP . ")");
while (my ($uid, $login, $gid, $rexp) = $sth->fetchrow_array()) {
if ($login =~ m/$rexp/i) {
$sth2->execute($uid, $gid);
}
}
}
# 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.
# #
...@@ -3927,8 +3958,8 @@ if (!GroupDoesExist("editbugs")) { ...@@ -3927,8 +3958,8 @@ if (!GroupDoesExist("editbugs")) {
$sth->execute(); $sth->execute();
while (my ($userid) = $sth->fetchrow_array()) { while (my ($userid) = $sth->fetchrow_array()) {
$dbh->do("INSERT INTO user_group_map $dbh->do("INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES ($userid, $id, 0, 0)"); VALUES ($userid, $id, 0, " . GRANT_DIRECT . ")");
} }
} }
...@@ -3938,8 +3969,8 @@ if (!GroupDoesExist("canconfirm")) { ...@@ -3938,8 +3969,8 @@ if (!GroupDoesExist("canconfirm")) {
$sth->execute(); $sth->execute();
while (my ($userid) = $sth->fetchrow_array()) { while (my ($userid) = $sth->fetchrow_array()) {
$dbh->do("INSERT INTO user_group_map $dbh->do("INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES ($userid, $id, 0, 0)"); VALUES ($userid, $id, 0, " . GRANT_DIRECT . ")");
} }
} }
...@@ -3965,15 +3996,15 @@ if (@admins) { ...@@ -3965,15 +3996,15 @@ if (@admins) {
my ($adminid) = $sth->fetchrow_array(); my ($adminid) = $sth->fetchrow_array();
foreach my $userid (@admins) { foreach my $userid (@admins) {
$dbh->do("INSERT INTO user_group_map $dbh->do("INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES ($userid, $adminid, 0, 0)"); VALUES ($userid, $adminid, 0, " . GRANT_DIRECT . ")");
# Existing administrators are made blessers of group "admin" # Existing administrators are made blessers of group "admin"
# but only explitly defined blessers can bless group admin. # but only explitly defined blessers can bless group admin.
# Other groups can be blessed by any admin (by default) or additional # Other groups can be blessed by any admin (by default) or additional
# defined blessers. # defined blessers.
$dbh->do("INSERT INTO user_group_map $dbh->do("INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES ($userid, $adminid, 1, 0)"); VALUES ($userid, $adminid, 1, " . GRANT_DIRECT . ")");
} }
$sth = $dbh->prepare("SELECT id FROM groups"); $sth = $dbh->prepare("SELECT id FROM groups");
$sth->execute(); $sth->execute();
...@@ -4167,8 +4198,8 @@ if ($sth->rows == 0) { ...@@ -4167,8 +4198,8 @@ if ($sth->rows == 0) {
$sth->execute(); $sth->execute();
if ( !$sth->fetchrow_array() ) { if ( !$sth->fetchrow_array() ) {
$dbh->do("INSERT INTO user_group_map $dbh->do("INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES ($userid, $group, 0, 0)"); VALUES ($userid, $group, 0, " . GRANT_DIRECT . ")");
} }
} }
# the admin also gets an explicit bless capability for the admin group # the admin also gets an explicit bless capability for the admin group
...@@ -4177,8 +4208,8 @@ if ($sth->rows == 0) { ...@@ -4177,8 +4208,8 @@ if ($sth->rows == 0) {
$sth->execute(); $sth->execute();
my ($id) = $sth->fetchrow_array(); my ($id) = $sth->fetchrow_array();
$dbh->do("INSERT INTO user_group_map $dbh->do("INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES ($userid, $id, 1, 0)"); VALUES ($userid, $id, 1, " . GRANT_DIRECT . ")");
foreach my $group ( @groups ) { foreach my $group ( @groups ) {
$dbh->do("INSERT INTO group_group_map $dbh->do("INSERT INTO group_group_map
(member_id, grantor_id, isbless) (member_id, grantor_id, isbless)
...@@ -4262,6 +4293,11 @@ if (GetFieldDef('bugs', 'short_desc')->[2]) { # if it allows nulls ...@@ -4262,6 +4293,11 @@ if (GetFieldDef('bugs', 'short_desc')->[2]) { # if it allows nulls
ChangeFieldType('bugs', 'short_desc', 'mediumtext not null'); ChangeFieldType('bugs', 'short_desc', 'mediumtext not null');
} }
# 2004-04-12 - Keep regexp-based group permissions up-to-date - Bug 240325
# Make sure groups get rederived
$dbh->do("UPDATE groups SET last_changed = NOW() WHERE name = 'admin'");
# #
# Final checks... # Final checks...
......
...@@ -49,6 +49,30 @@ if (!UserInGroup("creategroups")) { ...@@ -49,6 +49,30 @@ if (!UserInGroup("creategroups")) {
my $action = trim($::FORM{action} || ''); my $action = trim($::FORM{action} || '');
# RederiveRegexp: update user_group_map with regexp-based grants
sub RederiveRegexp ($$)
{
my $regexp = shift;
my $gid = shift;
my $dbh = Bugzilla->dbh;
my $sth = $dbh->prepare("SELECT userid, login_name FROM profiles");
my $sthadd = $dbh->prepare("INSERT IGNORE INTO user_group_map
(user_id, group_id, grant_type, isbless)
VALUES (?, ?, ?, 0)");
my $sthdel = $dbh->prepare("DELETE FROM user_group_map
WHERE user_id = ? AND group_id = ?
AND grant_type = ? and isbless = 0");
$sth->execute();
while (my ($uid, $login) = $sth->fetchrow_array()) {
if ($login =~ m/$regexp/i)
{
$sthadd->execute($uid, $gid, GRANT_REGEXP);
} else {
$sthdel->execute($uid, $gid, GRANT_REGEXP);
}
}
}
# TestGroup: check if the group name exists # TestGroup: check if the group name exists
sub TestGroup ($) sub TestGroup ($)
{ {
...@@ -384,6 +408,7 @@ if ($action eq 'new') { ...@@ -384,6 +408,7 @@ if ($action eq 'new') {
CONTROLMAPNA . ", 0 " . CONTROLMAPNA . ", 0 " .
"FROM products"); "FROM products");
} }
RederiveRegexp($regexp, $gid);
print "OK, done.<p>\n"; print "OK, done.<p>\n";
PutTrailer("<a href=\"editgroups.cgi?action=add\">add</a> another group", PutTrailer("<a href=\"editgroups.cgi?action=add\">add</a> another group",
"back to the <a href=\"editgroups.cgi\">group list</a>"); "back to the <a href=\"editgroups.cgi\">group list</a>");
...@@ -625,9 +650,9 @@ if (($action eq 'remove_all_regexp') || ($action eq 'remove_all')) { ...@@ -625,9 +650,9 @@ if (($action eq 'remove_all_regexp') || ($action eq 'remove_all')) {
FROM user_group_map, profiles FROM user_group_map, profiles
WHERE user_group_map.user_id = profiles.userid WHERE user_group_map.user_id = profiles.userid
AND user_group_map.group_id = ? AND user_group_map.group_id = ?
AND isderived = 0 AND grant_type = ?
AND isbless = 0"); AND isbless = 0");
$sth->execute($gid); $sth->execute($gid, GRANT_DIRECT);
my $sth2 = $dbh->prepare("DELETE FROM user_group_map my $sth2 = $dbh->prepare("DELETE FROM user_group_map
WHERE user_id = ? WHERE user_id = ?
AND isbless = 0 AND isbless = 0
...@@ -739,6 +764,7 @@ sub doGroupChanges { ...@@ -739,6 +764,7 @@ sub doGroupChanges {
} }
SendSQL("UPDATE groups SET userregexp = " . SendSQL("UPDATE groups SET userregexp = " .
SqlQuote($::FORM{"rexp"}) . " WHERE id = $gid"); SqlQuote($::FORM{"rexp"}) . " WHERE id = $gid");
RederiveRegexp($::FORM{"rexp"}, $gid);
} }
if (($isbuggroup == 1) && ($::FORM{"oldisactive"} ne $::FORM{"isactive"})) { if (($isbuggroup == 1) && ($::FORM{"oldisactive"} ne $::FORM{"isactive"})) {
$chgs = 1; $chgs = 1;
......
...@@ -138,8 +138,9 @@ sub EmitFormElements ($$$$) ...@@ -138,8 +138,9 @@ sub EmitFormElements ($$$$)
if($user ne "") { if($user ne "") {
print "</TR><TR><TH VALIGN=TOP ALIGN=RIGHT>Group Access:</TH><TD><TABLE><TR>"; print "</TR><TR><TH VALIGN=TOP ALIGN=RIGHT>Group Access:</TH><TD><TABLE><TR>";
SendSQL("SELECT groups.id, groups.name, groups.description, " . SendSQL("SELECT groups.id, groups.name, groups.description, " .
"COUNT(user_id), " . "MAX(grant_type = " . GRANT_DIRECT . "), " .
"MAX(isderived) " . "MAX(grant_type = " . GRANT_DERIVED . "), " .
"MAX(grant_type = " . GRANT_REGEXP . ") " .
"FROM groups " . "FROM groups " .
"LEFT JOIN user_group_map " . "LEFT JOIN user_group_map " .
"ON user_group_map.group_id = groups.id " . "ON user_group_map.group_id = groups.id " .
...@@ -153,10 +154,8 @@ sub EmitFormElements ($$$$) ...@@ -153,10 +154,8 @@ sub EmitFormElements ($$$$)
} }
print "<TD COLSPAN=2 ALIGN=LEFT><B>User is a member of these groups</B></TD>\n"; print "<TD COLSPAN=2 ALIGN=LEFT><B>User is a member of these groups</B></TD>\n";
while (MoreSQLData()) { while (MoreSQLData()) {
my ($groupid, $name, $description, $member, $isderived) = FetchSQLData(); my ($groupid, $name, $description, $checked, $isderived, $isregexp) = FetchSQLData();
next if (!$editall && !UserCanBlessGroup($name)); next if (!$editall && !UserCanBlessGroup($name));
$isderived = $isderived || 0;
my $checked = $member - $isderived;
PushGlobalSQLState(); PushGlobalSQLState();
SendSQL("SELECT user_id " . SendSQL("SELECT user_id " .
"FROM user_group_map " . "FROM user_group_map " .
...@@ -174,7 +173,7 @@ sub EmitFormElements ($$$$) ...@@ -174,7 +173,7 @@ sub EmitFormElements ($$$$)
my $derivedbless = FetchOneColumn(); my $derivedbless = FetchOneColumn();
PopGlobalSQLState(); PopGlobalSQLState();
print "</TR><TR"; print "</TR><TR";
print ' bgcolor=#cccccc' if ($isderived); print ' bgcolor=#cccccc' if ($isderived || $isregexp);
print ">\n"; print ">\n";
print "<INPUT TYPE=HIDDEN NAME=\"oldgroup_$groupid\" VALUE=\"$checked\">\n"; print "<INPUT TYPE=HIDDEN NAME=\"oldgroup_$groupid\" VALUE=\"$checked\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"oldbless_$groupid\" VALUE=\"$blchecked\">\n"; print "<INPUT TYPE=HIDDEN NAME=\"oldbless_$groupid\" VALUE=\"$blchecked\">\n";
...@@ -189,8 +188,10 @@ sub EmitFormElements ($$$$) ...@@ -189,8 +188,10 @@ sub EmitFormElements ($$$$)
$checked = ($checked) ? "CHECKED" : ""; $checked = ($checked) ? "CHECKED" : "";
print "<TD ALIGN=CENTER>"; print "<TD ALIGN=CENTER>";
print '[' if ($isderived); print '[' if ($isderived);
print '*' if ($isregexp);
print "<INPUT TYPE=CHECKBOX NAME=\"group_$groupid\" $checked VALUE=\"$groupid\">"; print "<INPUT TYPE=CHECKBOX NAME=\"group_$groupid\" $checked VALUE=\"$groupid\">";
print ']' if ($isderived); print ']' if ($isderived);
print '*' if ($isregexp);
print "</TD><TD><B>"; print "</TD><TD><B>";
print ucfirst($name) . "</B>: $description</TD>\n"; print ucfirst($name) . "</B>: $description</TD>\n";
} }
...@@ -704,13 +705,13 @@ if ($action eq 'edit') { ...@@ -704,13 +705,13 @@ if ($action eq 'edit') {
value_quote($disabledtext) . "\">\n"; value_quote($disabledtext) . "\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"update\">\n"; print "<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"update\">\n";
print "<INPUT TYPE=SUBMIT VALUE=\"Update\">\n"; print "<INPUT TYPE=SUBMIT VALUE=\"Update\">\n";
print "<BR>User is a member of any groups shown with grey bars and print "<BR>User is a member of any groups shown with a check or grey bar.
marked with brackets surrounding the membership checkbox as a A grey bar indicates indirect membership, either derived from other
result of a regular expression match groups (marked with square brackets) or via regular expression
or membership in another group. (marked with '*').<p>
User can bless any group Square brackets around the bless checkbox indicate the ability
marked with brackets surrounding the bless checkbox as a to bless users (grant them membership in the group) as a result
result of membership in another group. of membership in another group.
<BR>"; <BR>";
print "</FORM>"; print "</FORM>";
...@@ -761,11 +762,11 @@ if ($action eq 'update') { ...@@ -761,11 +762,11 @@ if ($action eq 'update') {
WHERE user_id = $thisuserid WHERE user_id = $thisuserid
AND group_id = $groupid AND group_id = $groupid
AND isbless = 0 AND isbless = 0
AND isderived = 0"); AND grant_type = " . GRANT_DIRECT);
if ($::FORM{"group_$groupid"}) { if ($::FORM{"group_$groupid"}) {
SendSQL("INSERT INTO user_group_map SendSQL("INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES ($thisuserid, $groupid, 0, 0)"); VALUES ($thisuserid, $groupid, 0," . GRANT_DIRECT . ")");
print "Added user to group $name<BR>\n"; print "Added user to group $name<BR>\n";
push(@grpadd, $name); push(@grpadd, $name);
} else { } else {
...@@ -781,11 +782,11 @@ if ($action eq 'update') { ...@@ -781,11 +782,11 @@ if ($action eq 'update') {
WHERE user_id = $thisuserid WHERE user_id = $thisuserid
AND group_id = $groupid AND group_id = $groupid
AND isbless = 1 AND isbless = 1
AND isderived = 0"); AND grant_type = " . GRANT_DIRECT);
if ($::FORM{"bless_$groupid"}) { if ($::FORM{"bless_$groupid"}) {
SendSQL("INSERT INTO user_group_map SendSQL("INSERT INTO user_group_map
(user_id, group_id, isbless, isderived) (user_id, group_id, isbless, grant_type)
VALUES ($thisuserid, $groupid, 1, 0)"); VALUES ($thisuserid, $groupid, 1," . GRANT_DIRECT . ")");
print "Granted user permission to bless group $name<BR>\n"; print "Granted user permission to bless group $name<BR>\n";
} else { } else {
print "Revoked user's permission to bless group $name<BR>\n"; print "Revoked user's permission to bless group $name<BR>\n";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment