diff options
Diffstat (limited to 'extensions/Mageia/lib/Util.pm')
-rw-r--r-- | extensions/Mageia/lib/Util.pm | 100 |
1 files changed, 99 insertions, 1 deletions
diff --git a/extensions/Mageia/lib/Util.pm b/extensions/Mageia/lib/Util.pm index 60447fa28..11f4fcaf6 100644 --- a/extensions/Mageia/lib/Util.pm +++ b/extensions/Mageia/lib/Util.pm @@ -11,9 +11,17 @@ use 5.10.1; use strict; use warnings; +use Bugzilla::Auth::Verify::LDAP; +use Bugzilla::Group; +use Bugzilla::User; +use Bugzilla::Util qw(diff_arrays); + use parent qw(Exporter); -our @EXPORT = qw(compare_datetimes); +our @EXPORT = qw(compare_datetimes sync_ldap_groups_check); + +# Use Mageia Robot user ID = 2122 for LDAP groups sync. +use constant LDAP_SYNC_USER_ID => 2122; # This file can be loaded by your extension via # "use Bugzilla::Extension::Mageia::Util". You can put functions @@ -41,4 +49,94 @@ sub compare_datetimes { return 0; } +sub sync_ldap_groups_check { + my ($status, $repair) = @_; + my $ldap = Bugzilla::Auth::Verify::LDAP->new(); + $ldap->_bind_ldap_for_search; + + my $result = $ldap->ldap->search( + base => 'ou=Group,dc=mageia,dc=org', + filter => '(objectClass=groupOfNames)', + attrs => ['cn', 'member'] + ); + + if ($result->is_error) { + &$status('ldap_sync_alert', { ldap_error => $result->error }, 'alert'); + return; + } + + my (%groups, %users); + my $dbh = Bugzilla->dbh; + + my %bz_groups = map { $_->name => $_ } grep { $_->name =~ /^mga-/ } Bugzilla::Group->get_all; + + foreach my $ldap_group ($result->entries) { + my $group = $ldap_group->get_value('cn'); + next unless $bz_groups{$group}; + + $groups{$group} = {}; + + foreach my $user ($ldap_group->get_value('member')) { + unless (exists $users{$user}) { + my $result = $ldap->ldap->search( + base => $user, + scope => 'base', + filter => '(objectClass=inetOrgPerson)', + attrs => ['uid', 'mail'] + ); + if ($result->is_error) { + &$status('ldap_sync_alert', { ldap_error => $result->error }, 'alert'); + next; + } + + # Some entries are not valid user accounts. + my $ldap_user = $result->entry(0) or next; + my $uid = $ldap_user->get_value('uid'); + my $mail = $ldap_user->get_value('mail'); + # Some accounts lack an email address. They cannot log into Bugzilla. + next unless $uid && $mail; + + # Ignore the LDAP account if it does not exist in Bugzilla. + my $bz_user = Bugzilla::User->new({ extern_id => $uid }) or next; + $users{$user} = $bz_user; + } + $groups{$group}->{$users{$user}->extern_id} = $users{$user}; + } + } + + my $current_user = Bugzilla->user; + my $ldap_sync_needs_repair = 0; + + if ($repair) { + # We need to log in as a super user in order to update group memberships. + # Bugzilla needs a valid user ID to log changes, though. + my $super_user = Bugzilla::User->super_user; + $super_user->{userid} = LDAP_SYNC_USER_ID; + Bugzilla->set_user($super_user); + } + + foreach my $group (sort keys %groups) { + my %members = map { $_->extern_id => $_ } @{$bz_groups{$group}->members_direct}; + my ($removed, $added) = diff_arrays([keys %members], [keys %{$groups{$group}}]); + if ($repair) { + foreach my $old_user (@$removed) { + $members{$old_user}->set_groups({ remove => [$group] }); + $members{$old_user}->update; + } + + foreach my $new_user (@$added) { + $groups{$group}->{$new_user}->set_groups({ add => [$group] }); + $groups{$group}->{$new_user}->update; + } + } + elsif (@$removed || @$added) { + &$status('ldap_sync_group_mismatch_alert', { group => $group, old_users => $removed, new_users => $added }, 'alert'); + $ldap_sync_needs_repair = 1; + } + } + # Restore the original user. + Bugzilla->set_user($current_user) if $repair; + &$status('ldap_sync_repair_link') if $ldap_sync_needs_repair; +} + 1; |