LDAP‎ > ‎

Récupération d'étudiants dans Supann

Contexte :
  • j'ai un accès distant en lecture à une branche de l'annuaire LDAP de l'université de Toulouse 1 (UT1) qui contient tous les utilisateurs valides, personnels et étudiants, en cours,
  • je ne gère localement dans mon IUT qu'une population d'étudiants dont je connais les codes étapes auxquels ils sont inscrits dans Apogée, codes correspondant aux formations dispensées dans mon IUT,
  • ces codes étapes sont stockés dans une base MySQL (ce sont des valeurs de nomenclature qui ne changent jamais).
Objectif :
Je veux produire un fichier CSV des étudiants valides afin d'alimenter d'abord une base MySQL locale et ensuite l'Active Directory, voire ma messagerie. Pour ceci, je vais récupérer les valeurs d'attributs nécessaires dans SupAnn, en particulier de quoi forger des comptes et des mots de passe locaux à partir des dates de naissance et des numéros d'étudiants (je n'ai pas envie que mes étudiants se logguent sur les machines Windows avec leur identifiant horrible '20908812' fourni par UT1, mais avec un plus joli 'prenom.nom')

Validé : avec ruby 1.8.6 et 1.8.7 sur Ubuntu 8.04 et 9.10

require 'ldap'
require 'mysql'

# Année de la rentrée
annee = '2010'

# Pour sortir le résultat en unicode
$KCODE = 'u'

# URL du serveur LDAP et ports (constantes utilisées si pas de ports exotiques)
# credentials du compte pour Rodez
$HOST =   'ldap.univ-truc.fr'                        # nom du serveur LDAP
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT
scope = LDAP::LDAP_SCOPE_SUBTREE
dniut = 'uid=MaitreDuMonde,ou=admins,dc=univ-truc,dc=fr'    # dn autorisé en lecture sur LDAP
passwdiut = 'SuperSecret'                                                    # mot de passe du dn

# paramètres de connexion à la base
hostname = 'mabase.iut.rdz'                                                   # nom du serveur MySQL
username = 'mysql_reader'                                                     # compte en lecture sur la base
password = 'mysql_paswd'                                                     # mot de passe du compte
databasename = 'iut'                                                              #  nom de la base

# connexion à la base, préparation et éxecution de la requête de sélection
puts "Connexion à la base de données ..."
my = Mysql.new(hostname, username, password, databasename)


# définition de la base de recherche et du filtre multi-opérandes
# pour ne récupérer que les étudiants de l'IUT par leur code étape
puts "Connexion à LDAP ..."
base = 'ou=people,dc=univ-truc,dc=fr'
ce = my.prepare('select code_etape from etapes')
ce.execute
filter = "mipCodeEtape=#{(ce.fetch)[0]}"                                                                    # on initialise le filtre de recherche LDAP avec les codes étapes trouvé dans la base
ce.each { |c| filter = "|(#{filter})(mipCodeEtape=#{c[0]})" }
filter = "(#{filter})"
# puts "filtre : #{filter}"                                                                                               # décommenter pour voir le filtre construit
my.close

# définitions des attributs à récupérer sur chaque entrée LDAP
attrs = ['displayName','sn','givenName','mipdatenaissance','supannCivilite',
'supannEtuId','uid','supannCodeINE','mipCodeDiplome','mipLibelleDiplome','mipCodeEtape']

# définition du fichier de sortie, des séparateurs de champ et du compteur
count = 0
sep = ','
fic = 'etudiants_ldap.csv'

# fonction de suppression des accents                                                                        # petite fonction pour supprimer les accents, les ' ou autres \ qui traineraient
                                                                                                                                                  # d'une saisie hasardeuse dans Apogée
def normalise(str)
   accents = { ['á','à','â','ä','ã','Ã','Ä','Â','À'] => 'a',
       ['é','è','ê','ë','Ë','É','È','Ê'] => 'e',
       ['í','ì','î','ï','Î','Ì','Ï'] => 'i',
       ['ó','ò','ô','ö','õ','Õ','Ö','Ô','Ò'] => 'o',
       ['œ'] => 'oe',
       ['ß'] => 'ss',
       ['ú','ù','û','ü','U','Û','Ù'] => 'u',
       ['ç','Ç'] => 'c',
       [' '] => '',
       ['\''] => ''
       }
     accents.each do |ac,rep|
       ac.each do |s|
         str.gsub!(s, rep)
       end
     end
     return str
end

# connexion au serveur et authentification
conn = LDAP::SSLConn.new($HOST, $SSLPORT)
begin
conn.bind(dniut,passwdiut)
rescue LDAP::ResultError
  conn.perror("bind")
  exit
end

# ouverture du fichier csv en écriture
fichier_dest = File.open(fic,"w")

# recherche des entrées et création d'une ligne csv pour chacune
begin
  conn.search(base, scope, filter, attrs) { |entry|
     lig_etu = normalise(entry.vals('givenName')[0] + '.' + entry.vals('sn')[0]).downcase[0,20] + sep
     lig_etu = lig_etu + annee + sep
     lig_etu = lig_etu + entry.vals('displayName')[0] + sep
     lig_etu = lig_etu + entry.vals('sn')[0] + sep
     lig_etu = lig_etu + entry.vals('givenName')[0] + sep
     lig_etu = lig_etu + entry.vals('mipdatenaissance')[0][0,8] + sep
     lig_etu = lig_etu + entry.vals('supannCivilite')[0] + sep
     lig_etu = lig_etu + entry.vals('supannEtuId')[0] + sep
     lig_etu = lig_etu + entry.vals('uid')[0] + sep
     lig_etu = lig_etu + entry.vals('supannCodeINE')[0] + sep
     if (entry.vals('mipCodeDiplome')[0][0,3]=='C2I' or entry.vals('mipCodeDiplome')[0][0,4]=='DUGJ' )then i=1 else i=0 end
      # on choisit le diplome principal pour les doubles inscriptions en C2I ou en DUJG
            #  mes étudiants n'ont qu'une inscription principale et éventuellement le C2I ou le DUJG, que je vais considérer comme "annexes"
     lig_etu = lig_etu + entry.vals('mipCodeDiplome')[i] + sep
     lig_etu = lig_etu + entry.vals('mipLibelleDiplome')[i] + sep
     lig_etu = lig_etu + entry.vals('mipCodeEtape')[i]
     fichier_dest.puts(lig_etu)
     count += 1
  }
rescue LDAP::ResultError
  conn.perror("search")
  exit
end

# fermeture du fichier
fichier_dest.close

# fermeture de la connexion et affichage du compteur
conn.perror("search")
puts "nombre d'étudiants récupérés dans LDAP : #{count}"
conn.unbind

# vérification du nombre de lignes écrites dans le csv
fichier = File.open(fic,"r")
puts "nombre d'étudiants écrits dans le CSV  : #{fichier.readlines.length}  (fichier #{fic})"
fichier.close

#########################################

Comments