Commit ce2c6035 authored by mkanat%bugzilla.org's avatar mkanat%bugzilla.org

Bug 440656: Implement Bugzilla::User::visible_bugs and have can_see_bug use it

Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=LpSolit, a=LpSolit
parent 080a6b71
...@@ -49,6 +49,8 @@ use Bugzilla::Product; ...@@ -49,6 +49,8 @@ use Bugzilla::Product;
use Bugzilla::Classification; use Bugzilla::Classification;
use Bugzilla::Field; use Bugzilla::Field;
use Scalar::Util qw(blessed);
use base qw(Bugzilla::Object Exporter); use base qw(Bugzilla::Object Exporter);
@Bugzilla::User::EXPORT = qw(is_available_username @Bugzilla::User::EXPORT = qw(is_available_username
login_to_id user_id_to_login validate_password login_to_id user_id_to_login validate_password
...@@ -561,44 +563,70 @@ sub can_edit_product { ...@@ -561,44 +563,70 @@ sub can_edit_product {
} }
sub can_see_bug { sub can_see_bug {
my ($self, $bugid) = @_; my ($self, $bug_id) = @_;
return @{ $self->visible_bugs([$bug_id]) } ? 1 : 0;
}
sub visible_bugs {
my ($self, $bugs) = @_;
# Allow users to pass in Bug objects and bug ids both.
my @bug_ids = map { blessed $_ ? $_->id : $_ } @$bugs;
# We only check the visibility of bugs that we haven't
# checked yet.
my $visible_cache = $self->{_visible_bugs_cache} ||= {};
my @check_ids = grep(!exists $visible_cache->{$_}, @bug_ids);
if (@check_ids) {
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
my $sth = $self->{sthCanSeeBug}; my $user_id = $self->id;
my $userid = $self->id; my $sth;
# Get fields from bug, presence of user on cclist, and determine if # Speed up the can_see_bug case.
# the user is missing any groups required by the bug. The prepared query if (scalar(@check_ids) == 1) {
# is cached because this may be called for every row in buglists or $sth = $self->{_sth_one_visible_bug};
# every bug in a dependency list. }
unless ($sth) { $sth ||= $dbh->prepare(
$sth = $dbh->prepare("SELECT 1, reporter, assigned_to, qa_contact, # This checks for groups that the bug is in that the user
reporter_accessible, cclist_accessible, # *isn't* in. Then, in the Perl code below, we check if
COUNT(cc.who), COUNT(bug_group_map.bug_id) # the user can otherwise access the bug (for example, by being
# the assignee or QA Contact).
#
# The DISTINCT exists because the bug could be in *several*
# groups that the user isn't in, but they will all return the
# same result for bug_group_map.bug_id (so DISTINCT filters
# out duplicate rows).
"SELECT DISTINCT bugs.bug_id, reporter, assigned_to, qa_contact,
reporter_accessible, cclist_accessible, cc.who,
bug_group_map.bug_id
FROM bugs FROM bugs
LEFT JOIN cc LEFT JOIN cc
ON cc.bug_id = bugs.bug_id ON cc.bug_id = bugs.bug_id
AND cc.who = $userid AND cc.who = $user_id
LEFT JOIN bug_group_map LEFT JOIN bug_group_map
ON bugs.bug_id = bug_group_map.bug_id ON bugs.bug_id = bug_group_map.bug_id
AND bug_group_map.group_ID NOT IN(" . AND bug_group_map.group_id NOT IN ("
$self->groups_as_string . . $self->groups_as_string . ')
") WHERE bugs.bug_id = ? WHERE bugs.bug_id IN (' . join(',', ('?') x @check_ids) . ')
AND creation_ts IS NOT NULL " . AND creation_ts IS NOT NULL ');
$dbh->sql_group_by('bugs.bug_id', 'reporter, ' . if (scalar(@check_ids) == 1) {
'assigned_to, qa_contact, reporter_accessible, ' . $self->{_sth_one_visible_bug} = $sth;
'cclist_accessible')); }
}
$sth->execute($bugid); $sth->execute(@check_ids);
my ($ready, $reporter, $owner, $qacontact, $reporter_access, $cclist_access, while (my $row = $sth->fetchrow_arrayref) {
$isoncclist, $missinggroup) = $sth->fetchrow_array(); my ($bug_id, $reporter, $owner, $qacontact, $reporter_access,
$sth->finish; $cclist_access, $isoncclist, $missinggroup) = @$row;
$self->{sthCanSeeBug} = $sth; $visible_cache->{$bug_id} ||=
return ($ready ((($reporter == $user_id) && $reporter_access)
&& ((($reporter == $userid) && $reporter_access)
|| (Bugzilla->params->{'useqacontact'} || (Bugzilla->params->{'useqacontact'}
&& $qacontact && ($qacontact == $userid)) && $qacontact && ($qacontact == $user_id))
|| ($owner == $userid) || ($owner == $user_id)
|| ($isoncclist && $cclist_access) || ($isoncclist && $cclist_access)
|| (!$missinggroup))); || !$missinggroup) ? 1 : 0;
}
}
return [grep { $visible_cache->{blessed $_ ? $_->id : $_} } @$bugs];
} }
sub can_see_product { sub can_see_product {
......
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