diff options
Diffstat (limited to 'extensions/BMO/lib/Reports/Groups.pm')
-rw-r--r-- | extensions/BMO/lib/Reports/Groups.pm | 485 |
1 files changed, 244 insertions, 241 deletions
diff --git a/extensions/BMO/lib/Reports/Groups.pm b/extensions/BMO/lib/Reports/Groups.pm index ce7df767c..7b395aca9 100644 --- a/extensions/BMO/lib/Reports/Groups.pm +++ b/extensions/BMO/lib/Reports/Groups.pm @@ -19,25 +19,24 @@ use Bugzilla::Util qw(trim datetime_from); use JSON qw(encode_json); sub admins_report { - my ($vars) = @_; - my $dbh = Bugzilla->dbh; - my $user = Bugzilla->user; + my ($vars) = @_; + my $dbh = Bugzilla->dbh; + my $user = Bugzilla->user; - ($user->in_group('editbugs')) - || ThrowUserError('auth_failure', { group => 'editbugs', - action => 'run', - object => 'group_admins' }); + ($user->in_group('editbugs')) + || ThrowUserError('auth_failure', + {group => 'editbugs', action => 'run', object => 'group_admins'}); - my @grouplist = - ($user->in_group('editusers') || $user->in_group('infrasec')) - ? map { lc($_->name) } Bugzilla::Group->get_all - : _get_permitted_membership_groups(); + my @grouplist + = ($user->in_group('editusers') || $user->in_group('infrasec')) + ? map { lc($_->name) } Bugzilla::Group->get_all + : _get_permitted_membership_groups(); - my $groups = join(',', map { $dbh->quote($_) } @grouplist); + my $groups = join(',', map { $dbh->quote($_) } @grouplist); - my $query = " - SELECT groups.id, " . - $dbh->sql_group_concat('profiles.userid', "','", 1) . " + my $query = " + SELECT groups.id, " + . $dbh->sql_group_concat('profiles.userid', "','", 1) . " FROM groups LEFT JOIN user_group_map ON user_group_map.group_id = groups.id @@ -49,271 +48,275 @@ sub admins_report { AND groups.name IN ($groups) GROUP BY groups.name"; - my @groups; - foreach my $row (@{ $dbh->selectall_arrayref($query) }) { - my $group = Bugzilla::Group->new({ id => shift @$row, cache => 1}); - my @admins; - if (my $admin_ids = shift @$row) { - foreach my $uid (split(/,/, $admin_ids)) { - push(@admins, Bugzilla::User->new({ id => $uid, cache => 1 })); - } - } - push(@groups, { name => $group->name, - description => $group->description, - owner => $group->owner, - admins => \@admins }); + my @groups; + foreach my $row (@{$dbh->selectall_arrayref($query)}) { + my $group = Bugzilla::Group->new({id => shift @$row, cache => 1}); + my @admins; + if (my $admin_ids = shift @$row) { + foreach my $uid (split(/,/, $admin_ids)) { + push(@admins, Bugzilla::User->new({id => $uid, cache => 1})); + } } + push( + @groups, + { + name => $group->name, + description => $group->description, + owner => $group->owner, + admins => \@admins + } + ); + } - $vars->{'groups'} = \@groups; + $vars->{'groups'} = \@groups; } sub membership_report { - my ($page, $vars) = @_; - my $dbh = Bugzilla->dbh; - my $user = Bugzilla->user; - my $cgi = Bugzilla->cgi; - - ($user->in_group('editusers') || $user->in_group('infrasec')) - || ThrowUserError('auth_failure', { group => 'editusers', - action => 'run', - object => 'group_admins' }); - - my $who = $cgi->param('who'); - if (!defined($who) || $who eq '') { - if ($page eq 'group_membership.txt') { - print $cgi->redirect("page.cgi?id=group_membership.html&output=txt"); - exit; - } - $vars->{'output'} = $cgi->param('output'); - return; + my ($page, $vars) = @_; + my $dbh = Bugzilla->dbh; + my $user = Bugzilla->user; + my $cgi = Bugzilla->cgi; + + ($user->in_group('editusers') || $user->in_group('infrasec')) + || ThrowUserError('auth_failure', + {group => 'editusers', action => 'run', object => 'group_admins'}); + + my $who = $cgi->param('who'); + if (!defined($who) || $who eq '') { + if ($page eq 'group_membership.txt') { + print $cgi->redirect("page.cgi?id=group_membership.html&output=txt"); + exit; } + $vars->{'output'} = $cgi->param('output'); + return; + } - Bugzilla::User::match_field({ 'who' => {'type' => 'multi'} }); - $who = Bugzilla->input_params->{'who'}; - $who = ref($who) ? $who : [ $who ]; + Bugzilla::User::match_field({'who' => {'type' => 'multi'}}); + $who = Bugzilla->input_params->{'who'}; + $who = ref($who) ? $who : [$who]; - my @users; - foreach my $login (@$who) { - my $u = Bugzilla::User->new(login_to_id($login, 1)); + my @users; + foreach my $login (@$who) { + my $u = Bugzilla::User->new(login_to_id($login, 1)); - # this is lifted from $user->groups() - # we need to show which groups are direct and which are inherited + # this is lifted from $user->groups() + # we need to show which groups are direct and which are inherited - my $groups_to_check = $dbh->selectcol_arrayref( - q{SELECT DISTINCT group_id + my $groups_to_check = $dbh->selectcol_arrayref( + q{SELECT DISTINCT group_id FROM user_group_map - WHERE user_id = ? AND isbless = 0}, undef, $u->id); + WHERE user_id = ? AND isbless = 0}, undef, $u->id + ); - my $rows = $dbh->selectall_arrayref( - "SELECT DISTINCT grantor_id, member_id + my $rows = $dbh->selectall_arrayref( + "SELECT DISTINCT grantor_id, member_id FROM group_group_map - WHERE grant_type = " . GROUP_MEMBERSHIP); + WHERE grant_type = " . GROUP_MEMBERSHIP + ); - my %group_membership; - foreach my $row (@$rows) { - my ($grantor_id, $member_id) = @$row; - push (@{ $group_membership{$member_id} }, $grantor_id); - } + my %group_membership; + foreach my $row (@$rows) { + my ($grantor_id, $member_id) = @$row; + push(@{$group_membership{$member_id}}, $grantor_id); + } - my %checked_groups; - my %direct_groups; - my %indirect_groups; - my %groups; + my %checked_groups; + my %direct_groups; + my %indirect_groups; + my %groups; - foreach my $member_id (@$groups_to_check) { - $direct_groups{$member_id} = 1; - } + foreach my $member_id (@$groups_to_check) { + $direct_groups{$member_id} = 1; + } - while (scalar(@$groups_to_check) > 0) { - my $member_id = shift @$groups_to_check; - if (!$checked_groups{$member_id}) { - $checked_groups{$member_id} = 1; - my $members = $group_membership{$member_id}; - my @new_to_check = grep(!$checked_groups{$_}, @$members); - push(@$groups_to_check, @new_to_check); - foreach my $id (@new_to_check) { - $indirect_groups{$id} = $member_id; - } - $groups{$member_id} = 1; - } + while (scalar(@$groups_to_check) > 0) { + my $member_id = shift @$groups_to_check; + if (!$checked_groups{$member_id}) { + $checked_groups{$member_id} = 1; + my $members = $group_membership{$member_id}; + my @new_to_check = grep(!$checked_groups{$_}, @$members); + push(@$groups_to_check, @new_to_check); + foreach my $id (@new_to_check) { + $indirect_groups{$id} = $member_id; } + $groups{$member_id} = 1; + } + } - my @groups; - my $ra_groups = Bugzilla::Group->new_from_list([keys %groups]); - foreach my $group (@$ra_groups) { - my $via; - if ($direct_groups{$group->id}) { - $via = ''; - } else { - foreach my $g (@$ra_groups) { - if ($g->id == $indirect_groups{$group->id}) { - $via = $g->name; - last; - } - } - } - push @groups, { - name => $group->name, - desc => $group->description, - via => $via, - }; + my @groups; + my $ra_groups = Bugzilla::Group->new_from_list([keys %groups]); + foreach my $group (@$ra_groups) { + my $via; + if ($direct_groups{$group->id}) { + $via = ''; + } + else { + foreach my $g (@$ra_groups) { + if ($g->id == $indirect_groups{$group->id}) { + $via = $g->name; + last; + } } - - push @users, { - user => $u, - groups => \@groups, - }; + } + push @groups, {name => $group->name, desc => $group->description, via => $via,}; } - $vars->{'who'} = $who; - $vars->{'users'} = \@users; + push @users, {user => $u, groups => \@groups,}; + } + + $vars->{'who'} = $who; + $vars->{'users'} = \@users; } sub members_report { - my ($page, $vars) = @_; - my $dbh = Bugzilla->dbh; - my $user = Bugzilla->user; - my $cgi = Bugzilla->cgi; - - ($user->in_group('editbugs')) - || ThrowUserError('auth_failure', { group => 'editbugs', - action => 'run', - object => 'group_admins' }); - - my $privileged = $user->in_group('editusers') || $user->in_group('infrasec'); - $vars->{privileged} = $privileged; - - my @grouplist = $privileged - ? map { lc($_->name) } Bugzilla::Group->get_all - : _get_permitted_membership_groups(); - - my $include_disabled = $cgi->param('include_disabled') ? 1 : 0; - $vars->{'include_disabled'} = $include_disabled; - - # don't allow all groups, to avoid putting pain on the servers - my @group_names = - sort - grep { !/^(?:bz_.+|canconfirm|editbugs|editbugs-team|everyone)$/ } - @grouplist; - unshift(@group_names, ''); - $vars->{'groups'} = \@group_names; - - # load selected group - my $group = lc(trim($cgi->param('group') || '')); - $group = '' unless grep { $_ eq $group } @group_names; - return if $group eq ''; - my $group_obj = Bugzilla::Group->new({ name => $group }); - $vars->{'group'} = $group_obj; - - $vars->{'privileged'} = 1 if ($group_obj->owner && $group_obj->owner->id == $user->id); - - my @types; - my $members = $group_obj->members_complete(); - foreach my $name (sort keys %$members) { - push @types, { - name => ($name eq '_direct' ? 'direct' : $name), - members => _filter_userlist($members->{$name}), + my ($page, $vars) = @_; + my $dbh = Bugzilla->dbh; + my $user = Bugzilla->user; + my $cgi = Bugzilla->cgi; + + ($user->in_group('editbugs')) + || ThrowUserError('auth_failure', + {group => 'editbugs', action => 'run', object => 'group_admins'}); + + my $privileged = $user->in_group('editusers') || $user->in_group('infrasec'); + $vars->{privileged} = $privileged; + + my @grouplist + = $privileged + ? map { lc($_->name) } Bugzilla::Group->get_all + : _get_permitted_membership_groups(); + + my $include_disabled = $cgi->param('include_disabled') ? 1 : 0; + $vars->{'include_disabled'} = $include_disabled; + + # don't allow all groups, to avoid putting pain on the servers + my @group_names + = sort grep { !/^(?:bz_.+|canconfirm|editbugs|editbugs-team|everyone)$/ } + @grouplist; + unshift(@group_names, ''); + $vars->{'groups'} = \@group_names; + + # load selected group + my $group = lc(trim($cgi->param('group') || '')); + $group = '' unless grep { $_ eq $group } @group_names; + return if $group eq ''; + my $group_obj = Bugzilla::Group->new({name => $group}); + $vars->{'group'} = $group_obj; + + $vars->{'privileged'} = 1 + if ($group_obj->owner && $group_obj->owner->id == $user->id); + + my @types; + my $members = $group_obj->members_complete(); + foreach my $name (sort keys %$members) { + push @types, + { + name => ($name eq '_direct' ? 'direct' : $name), + members => _filter_userlist($members->{$name}), + }; + } + + # make it easy for the template to detect an empty group + my $has_members = 0; + foreach my $type (@types) { + $has_members += scalar(@{$type->{members}}); + last if $has_members; + } + @types = () unless $has_members; + + if ($page eq 'group_members.json') { + my %users; + foreach my $rh (@types) { + foreach my $member (@{$rh->{members}}) { + my $login = $member->login; + if (exists $users{$login}) { + push @{$users{$login}->{groups}}, $rh->{name} if $privileged; } - } - - # make it easy for the template to detect an empty group - my $has_members = 0; - foreach my $type (@types) { - $has_members += scalar(@{ $type->{members} }); - last if $has_members; - } - @types = () unless $has_members; - - if ($page eq 'group_members.json') { - my %users; - foreach my $rh (@types) { - foreach my $member (@{ $rh->{members} }) { - my $login = $member->login; - if (exists $users{$login}) { - push @{ $users{$login}->{groups} }, $rh->{name} if $privileged; - } - else { - my $rh_user = { - login => $login, - membership => $rh->{name} eq 'direct' ? 'direct' : 'indirect', - rh_name => $rh->{name}, - }; - if ($privileged) { - $rh_user->{group} = $rh->{name}; - $rh_user->{groups} = [ $rh->{name} ]; - $rh_user->{lastseeon} = $member->last_seen_date; - $rh_user->{mfa} = $member->mfa; - $rh_user->{api_key_only} = $member->settings->{api_key_only}->{value} eq 'on' - ? JSON::true : JSON::false; - } - $users{$login} = $rh_user; - } - } + else { + my $rh_user = { + login => $login, + membership => $rh->{name} eq 'direct' ? 'direct' : 'indirect', + rh_name => $rh->{name}, + }; + if ($privileged) { + $rh_user->{group} = $rh->{name}; + $rh_user->{groups} = [$rh->{name}]; + $rh_user->{lastseeon} = $member->last_seen_date; + $rh_user->{mfa} = $member->mfa; + $rh_user->{api_key_only} + = $member->settings->{api_key_only}->{value} eq 'on' + ? JSON::true + : JSON::false; + } + $users{$login} = $rh_user; } - $vars->{types_json} = JSON->new->pretty->canonical->utf8->encode([ values %users ]); + } } - else { - my %users; - foreach my $rh (@types) { - foreach my $member (@{ $rh->{members} }) { - $users{$member->login} = 1 unless exists $users{$member->login}; - } - } - $vars->{types} = \@types; - $vars->{count} = scalar(keys %users); + $vars->{types_json} + = JSON->new->pretty->canonical->utf8->encode([values %users]); + } + else { + my %users; + foreach my $rh (@types) { + foreach my $member (@{$rh->{members}}) { + $users{$member->login} = 1 unless exists $users{$member->login}; + } } + $vars->{types} = \@types; + $vars->{count} = scalar(keys %users); + } } sub _filter_userlist { - my ($list, $include_disabled) = @_; - $list = [ grep { $_->is_enabled } @$list ] unless $include_disabled; - my $now = DateTime->now(); - my $never = DateTime->from_epoch( epoch => 0 ); - foreach my $user (@$list) { - my $last_seen = $user->last_seen_date ? datetime_from($user->last_seen_date) : $never; - $user->{last_seen_days} = sprintf( - '%.0f', - $now->subtract_datetime_absolute($last_seen)->delta_seconds / (28 * 60 * 60)); - } - return [ sort { lc($a->identity) cmp lc($b->identity) } @$list ]; + my ($list, $include_disabled) = @_; + $list = [grep { $_->is_enabled } @$list] unless $include_disabled; + my $now = DateTime->now(); + my $never = DateTime->from_epoch(epoch => 0); + foreach my $user (@$list) { + my $last_seen + = $user->last_seen_date ? datetime_from($user->last_seen_date) : $never; + $user->{last_seen_days} = sprintf('%.0f', + $now->subtract_datetime_absolute($last_seen)->delta_seconds / (28 * 60 * 60)); + } + return [sort { lc($a->identity) cmp lc($b->identity) } @$list]; } # Groups that any user with editbugs can see the membership or admin lists for. # Transparency FTW. sub _get_permitted_membership_groups { - my $user = Bugzilla->user; - - # Default publicly viewable groups - my %default_public_groups = map { $_ => 1 } qw( - bugzilla-approvers - bugzilla-reviewers - can_restrict_comments - community-it-team - mozilla-employee-confidential - mozilla-foundation-confidential - mozilla-reps - qa-approvers - ); - - # We add the group to the permitted list if: - # 1. it is a drivers group - this gives us a little - # future-proofing - # 2. it is a one of the default public groups - # 3. the user is the group's owner - # 4. or the user can bless others into the group - my @permitted_groups; - foreach my $group (Bugzilla::Group->get_all) { - my $name = $group->name; - if ($name =~ /-drivers$/ - || exists $default_public_groups{$name} - || ($group->owner && $group->owner->id == $user->id) - || $user->can_bless($group->id)) - { - push(@permitted_groups, $name); - } + my $user = Bugzilla->user; + + # Default publicly viewable groups + my %default_public_groups = map { $_ => 1 } qw( + bugzilla-approvers + bugzilla-reviewers + can_restrict_comments + community-it-team + mozilla-employee-confidential + mozilla-foundation-confidential + mozilla-reps + qa-approvers + ); + + # We add the group to the permitted list if: + # 1. it is a drivers group - this gives us a little + # future-proofing + # 2. it is a one of the default public groups + # 3. the user is the group's owner + # 4. or the user can bless others into the group + my @permitted_groups; + foreach my $group (Bugzilla::Group->get_all) { + my $name = $group->name; + if ( $name =~ /-drivers$/ + || exists $default_public_groups{$name} + || ($group->owner && $group->owner->id == $user->id) + || $user->can_bless($group->id)) + { + push(@permitted_groups, $name); } + } - return @permitted_groups; + return @permitted_groups; } 1; |