Hallo,
ich habe mir jetzt ein kleines perl-Skript geschrieben, dass die Nutzer mit ihren eMails aus der moodle Datenbank holt. Dann vergleicht es die eMails mit denen im Ldap und setzt sie im Fall einer Änderung mit smbldap-usermod neu.
Man benötigt einen moodle-Datenbank Benutzer der lesend auf die Tabelle mdl_user zugreifen kann. Benutzer, Passwort, Datenbank, etc. müssen oben im Skript eingetragen werden (Z 10-15). Das Skript wird auf dem lm-Server ausgeführt, die Datenbank muss von da erreichbar ein.
Die ldap-Konfiguration und das Passwort wird automatisch aus der /etc/ldap/slapd.conf gelesen.
Als cronjob kann man es dann jede Nacht laufen lassen und man hat die eMails aktuell im LDAP und z. B. in der nextcloud.
Da gelegentlich Lehrer ihre private eMail in moodle hinterlegen, im ldap aber mit der Dienstemail stehen sollen, muss man diese gesondert behandeln. Wenn man dieses benötigt, muss man die Zeile 98 auskommentieren. In der Subroutine teacherEmail kann man dann aus Vorname, Nachname, loginname die Dienstemail rekonstruieren (Zeile 129-129).
# 2020, Martin Schulte
use strict;
use warnings;
use Data::Dumper;
use Net::LDAP;
use DBI;
# Konfiguration
# Moodle Datenbank
my $db_host = 'dockerhost'; # host/ip auf dem die Datenbank läuft
my $db_user = 'backupuser'; # Benutzer der auf die moodle DB zugreifen kann
my $db_pass = 'strenggeheim!'; # Passwort des Benutzers
my $db = 'moodle'; # Name der Datenbank
my $db_preffix = "mdl_"; # Suffix für Moodel-Datenbank
my $db_port = "3306"; # Port der moodel Datenbank
## LDAP Zugriff einrichten, Konfiguration aus /etc/ldap/slapd.conf lesen.
open( INPUTFILE, "</etc/ldap/slapd.conf" ) or die "$!";
my @slapd_conf = <INPUTFILE>;
close(INPUTFILE);
#rootpw, rootcn, suffix
# grep erzeugt array mit einem Element: rootpw <viele Leerzeichen> <password>
# split erzeugt ein Array mit Elementenzahl ensprechend der Leerzeichen. [-1] nimmt das letzte dieser Elemente
my $rootpw = (split(/ /,(grep { /rootpw/ } (@slapd_conf))[0]))[-1];
my $rootdn = (split(/ /,(grep { /rootdn/ } (@slapd_conf))[0]))[-1];
my $suffix = (split(/ /,(grep { /suffix/ } (@slapd_conf))[0]))[-1];
chomp($rootpw);
chomp($rootdn);
chomp($suffix);
# Anführungsstriche entfernen.
$rootdn= substr($rootdn,1,-1);
$suffix= substr($suffix,1,-1);
# LDAP
my $ldap = Net::LDAP->new ( "localhost" ) or die "$@";
# bind
my $mesg = $ldap->bind ( $rootdn,
password => $rootpw,
version => 3 );
#Alle Nutzer und eMails holen
my $result = $ldap->search ( base => "ou=accounts,".$suffix,
# scope => "sub",
filter => "(!(sn=Account))",
attrs => "uid"
);
# hash %uldapUsers: uid => { mail=> <email>, givenname => <givenname>, surname => <surname>}
my %ldapUsers=();
foreach my $entry ($result->entries) {
if(defined $entry->get_value('uid')){
$ldapUsers{$entry->get_value('uid')}{'mail'}=$entry->get_value('mail');
$ldapUsers{$entry->get_value('uid')}{'givenname'}=$entry->get_value('givenName');
$ldapUsers{$entry->get_value('uid')}{'surname'}=$entry->get_value('sn');
}
}
# alle Lehrer holen
$result = $ldap->search ( base => $suffix,
filter => "(&(cn=teachers))",
attrs => "memberUid"
);
#%teachers: uid => email
my @teachers;
foreach my $entry ($result->entries) {
@teachers = $entry->get_value('memberUid');
}
$ldap->unbind;
# moodle-user holen
my $moodleDB = DBI->connect("DBI:mysql:database=$db:port=$db_port:$db_host",$db_user,$db_pass);
my $query = $moodleDB->prepare('SELECT username, email FROM '.$db_preffix.'user WHERE auth="ldap"');
$query->execute() or die $query->err_str;
my %moodleUsers;
#%moodleUsers: username => mail
while (my $ref = $query->fetchrow_hashref()) {
$moodleUsers{$ref->{'username'}}= $ref->{'email'};
}
$query->finish();
$moodleDB->disconnect();
# Finde user, bei denen die eMail noch nicht im ldap stand oder die Adresse in moodle geändert wurde.
my $counter = 0;
foreach my $moodleUser (keys %moodleUsers) {
if(exists $ldapUsers{$moodleUser}){
if($ldapUsers{$moodleUser}{mail} ne $moodleUsers{$moodleUser} and $moodleUsers{$moodleUser} ne ''){
#print "--".$ldapUsers{$moodleUser}{mail}."--".$moodleUsers{$moodleUser}."\n";
my $newMail = $moodleUsers{$moodleUser};
# Ist es ein Lehrer?
if ( grep( /^$moodleUser$/, @teachers ) ) {
# Bei Lehrern evtl. Dienstmail rekonstruieren.
### $newMail = teacherEmail($moodleUser,$ldapUsers{$moodleUser}{mail},$ldapUsers{$moodleUser}{surname},$ldapUsers{$moodleUser}{givenname});
# Hat sich die eMail geändert?
if($newMail eq $ldapUsers{$moodleUser}{mail}){
next; # Nichts zu tun
}
}
# Änderungen ins ldap schreiben.
print "Ändere eMail von $moodleUser in $newMail.\n";
system("smbldap-usermod -M $newMail $moodleUser");
$counter++;
# print "smbldap-usermod -M $newMail $moodleUser;\n";
}
}
}
# Wird in Zeile 98 aufgerufen (vorher auskommentieren). Dient dazu die Dienstmail
# eines Lehrers zu rekonstruieren. Denn es kann sein, dass er sich in moodle mit
# seiner privaten Adresse angemeldet hat.
# Der Quelltext unten z.B. erzeugt die Adresse <vornam>.<nachname>@meine-schule.de
# Muss nach Bedarf angepasst werden.
sub teacherEmail{
my $teacher = $_[0];
my $teacherMail = $_[1];
my $teacherSurname = $_[2];
my $teacherGivenname = $_[3];
if($teacher eq "spezial"){
return 'extra-spezial@meine-schule.de';
}
return $teacherGivenname.".".$teacherSurname.'@meine-schule.de'
}
print $counter." eMail-Adressen hinzugefügt.\n";
#print Dumper(%ldapUsers);
Besten Gruß, Martin