aboutsummaryrefslogtreecommitdiffstats
path: root/extensions/Mageia/lib/Util.pm
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/Mageia/lib/Util.pm')
-rw-r--r--extensions/Mageia/lib/Util.pm100
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;