summaryrefslogtreecommitdiffstats
path: root/Bugzilla
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla')
-rw-r--r--Bugzilla/Constants.pm8
-rw-r--r--Bugzilla/User.pm118
2 files changed, 112 insertions, 14 deletions
diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm
index e3cdf539d..d580dddc7 100644
--- a/Bugzilla/Constants.pm
+++ b/Bugzilla/Constants.pm
@@ -54,6 +54,10 @@ use base qw(Exporter);
GRANT_DIRECT
GRANT_DERIVED
GRANT_REGEXP
+
+ GROUP_MEMBERSHIP
+ GROUP_BLESS
+ GROUP_VISIBLE
);
@Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
@@ -122,4 +126,8 @@ use constant GRANT_DIRECT => 0;
use constant GRANT_DERIVED => 1;
use constant GRANT_REGEXP => 2;
+use constant GROUP_MEMBERSHIP => 0;
+use constant GROUP_BLESS => 1;
+use constant GROUP_VISIBLE => 2;
+
1;
diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm
index b3d953945..e9b7fe0c4 100644
--- a/Bugzilla/User.pm
+++ b/Bugzilla/User.pm
@@ -227,6 +227,40 @@ sub in_group {
return defined($res);
}
+# visible_groups_inherited returns a reference to a list of all the groups
+# whose members are visible to this user.
+sub visible_groups_inherited {
+ my $self = shift;
+ return $self->{visible_groups_inherited} if defined $self->{visible_groups_inherited};
+ my @visgroups = @{$self->visible_groups_direct};
+ @visgroups = flatten_group_membership(@visgroups);
+ $self->{visible_groups_inherited} = \@visgroups;
+ return $self->{visible_groups_inherited};
+}
+
+# visible_groups_direct returns a reference to a list of all the groups that
+# are visible to this user.
+sub visible_groups_direct {
+ my $self = shift;
+ my @visgroups = ();
+ return $self->{visible_groups_direct} if defined $self->{visible_groups_direct};
+
+ my $dbh = Bugzilla->dbh;
+ my $glist = join(',',(-1,values(%{$self->groups})));
+ my $sth = $dbh->prepare("SELECT DISTINCT grantor_id
+ FROM group_group_map
+ WHERE member_id IN($glist)
+ AND grant_type=" . GROUP_VISIBLE);
+ $sth->execute();
+
+ while (my ($row) = $sth->fetchrow_array) {
+ push @visgroups,$row;
+ }
+ $self->{visible_groups_direct} = \@visgroups;
+
+ return $self->{visible_groups_direct};
+}
+
sub derive_groups {
my ($self, $already_locked) = @_;
@@ -287,9 +321,10 @@ sub derive_groups {
$group_sth ||= $dbh->prepare(q{SELECT grantor_id
FROM group_group_map
WHERE member_id=?
- AND isbless=0});
+ AND grant_type=' .
+ GROUP_MEMBERSHIP . '});
$group_sth->execute($group);
- while (my $groupid = $group_sth->fetchrow_array) {
+ while (my ($groupid) = $group_sth->fetchrow_array) {
if (!defined($groupidschecked{"$groupid"})) {
push(@groupidstocheck,$groupid);
}
@@ -332,7 +367,8 @@ sub can_bless {
FROM user_group_map, group_group_map
WHERE user_group_map.user_id=?
AND user_group_map.group_id=member_id
- AND group_group_map.isbless=1},
+ AND group_group_map.grant_type=} .
+ GROUP_BLESS,
undef,
$self->{id});
}
@@ -342,6 +378,30 @@ sub can_bless {
return $self->{can_bless};
}
+sub flatten_group_membership {
+ my (@groups) = @_;
+
+ my $dbh = Bugzilla->dbh;
+ my $sth;
+ my @groupidstocheck = @groups;
+ my %groupidschecked = ();
+ $sth = $dbh->prepare("SELECT member_id FROM group_group_map
+ WHERE grantor_id = ?
+ AND grant_type = " . GROUP_MEMBERSHIP);
+ while (my $node = shift @groupidstocheck) {
+ $sth->execute($node);
+ my $member;
+ while (($member) = $sth->fetchrow_array) {
+ if (!$groupidschecked{$member}) {
+ $groupidschecked{$member} = 1;
+ push @groupidstocheck, $member;
+ push @groups, $member unless grep $_ == $member, @groups;
+ }
+ }
+ }
+ return @groups;
+}
+
sub match {
# Generates a list of users whose login name (email address) or real name
# matches a substring or wildcard.
@@ -364,17 +424,28 @@ sub match {
# first try wildcards
my $wildstr = $str;
+ my $user = Bugzilla->user;
if ($wildstr =~ s/\*/\%/g && # don't do wildcards if no '*' in the string
Param('usermatchmode') ne 'off') { # or if we only want exact matches
# Build the query.
my $sqlstr = &::SqlQuote($wildstr);
- my $query = "SELECT userid, realname, login_name " .
- "FROM profiles " .
- "WHERE (login_name LIKE $sqlstr " .
+ my $query = "SELECT DISTINCT userid, realname, login_name " .
+ "FROM profiles ";
+ if (&::Param('usevisibilitygroups')) {
+ $query .= ", user_group_map ";
+ }
+ $query .= "WHERE (login_name LIKE $sqlstr " .
"OR realname LIKE $sqlstr) ";
- $query .= "AND disabledtext = '' " if $exclude_disabled;
+ if (&::Param('usevisibilitygroups')) {
+ $query .= "AND user_group_map.user_id = userid " .
+ "AND isbless = 0 " .
+ "AND group_id IN(" .
+ join(', ', (-1, @{$user->visible_groups_inherited})) . ") " .
+ "AND grant_type <> " . GRANT_DERIVED;
+ }
+ $query .= " AND disabledtext = '' " if $exclude_disabled;
$query .= "ORDER BY length(login_name) ";
$query .= "LIMIT $limit " if $limit;
@@ -410,14 +481,23 @@ sub match {
my $sqlstr = &::SqlQuote(uc($str));
- my $query = "SELECT userid, realname, login_name " .
- "FROM profiles " .
- "WHERE (INSTR(UPPER(login_name), $sqlstr) " .
- "OR INSTR(UPPER(realname), $sqlstr)) ";
- $query .= "AND disabledtext = '' " if $exclude_disabled;
+ my $query = "SELECT DISTINCT userid, realname, login_name " .
+ "FROM profiles ";
+ if (&::Param('usevisibilitygroups')) {
+ $query .= ", user_group_map ";
+ }
+ $query .= "WHERE (INSTR(UPPER(login_name), $sqlstr) " .
+ "OR INSTR(UPPER(realname), $sqlstr)) ";
+ if (&::Param('usevisibilitygroups')) {
+ $query .= "AND user_group_map.user_id = userid " .
+ "AND isbless = 0 " .
+ "AND group_id IN(" .
+ join(', ', (-1, @{$user->visible_groups_inherited})) . ") " .
+ "AND grant_type <> " . GRANT_DERIVED;
+ }
+ $query .= " AND disabledtext = '' " if $exclude_disabled;
$query .= "ORDER BY length(login_name) ";
$query .= "LIMIT $limit " if $limit;
-
&::PushGlobalSQLState();
&::SendSQL($query);
push(@users, new Bugzilla::User(&::FetchSQLData())) while &::MoreSQLData();
@@ -843,10 +923,20 @@ care of by the constructor. However, when updating the email address, the
user may be placed into different groups, based on a new email regexp. This
method should be called in such a case to force reresolution of these groups.
+=item C<visible_groups_inherited>
+
+Returns a list of all groups whose members should be visible to this user.
+Since this list is flattened already, there is no need for all users to
+be have derived groups up-to-date to select the users meeting this criteria.
+
+=item C<visible_groups_direct>
+
+Returns a list of groups that the user is aware of.
+
=begin undocumented
This routine takes an optional argument. If true, then this routine will not
-lock the tables, but will rely on the caller to ahve done so itsself.
+lock the tables, but will rely on the caller to have done so itsself.
This is required because mysql will only execute a query if all of the tables
are locked, or if none of them are, not a mixture. If the caller has already