Skip to content
Snippets Groups Projects
Commit eb3d73a1 authored by Quentin CHEVALIER's avatar Quentin CHEVALIER
Browse files

Améliorations LDAP

parent cf9576d1
No related branches found
No related tags found
No related merge requests found
...@@ -10,11 +10,13 @@ ...@@ -10,11 +10,13 @@
}, },
"dn_groups":"ou=groups,dc=frankiz,dc=net", "dn_groups":"ou=groups,dc=frankiz,dc=net",
"dn_users": "ou=eleves,dc=frankiz,dc=net", "dn_users": "ou=eleves,dc=frankiz,dc=net",
"filter_lm":"(brMemberOf=${id})", "key_al": "uid",
"filter_al":"(brMemberOf=${id})", "filter_id": "(uid=${id})",
"filter_lg":"(restrictedMemberUid=${id})", "filter_lg": "(restrictedMemberUid=${id})",
"filter_st": "(uid=${id})",
"attributes_id": ["uid"], "attributes_id": ["uid"],
"attributes_al": ["memberUid"],
"attributes_lm":["restrictedMemberUid"],
"attributes_lg":["brMemberOf"],
"attributes_all": ["jpegPhoto","givenName", "sn", "brBirthdate", "brPromo","telephoneNumber","mail","brRoom","brIP"], "attributes_all": ["jpegPhoto","givenName", "sn", "brBirthdate", "brPromo","telephoneNumber","mail","brRoom","brIP"],
"search_attributes_tol": ["givenName", "sn", "displayName", "country", "brMemberOf", "brPromo", "brMemberOf", "brMemberOf", "brMemberOf", "telephoneNumber","mail","brRoom","brIP"], "search_attributes_tol": ["givenName", "sn", "displayName", "country", "brMemberOf", "brPromo", "brMemberOf", "brMemberOf", "brMemberOf", "telephoneNumber","mail","brRoom","brIP"],
"sessionSecret":"change this" "sessionSecret":"change this"
......
...@@ -3,27 +3,27 @@ ...@@ -3,27 +3,27 @@
* @author hawkspar * @author hawkspar
*/ */
/* Ne pas hésiter à repasser en synthaxe ES5... Plus simple pour tester en solo avec node directement */ /* Ne pas hésiter à repasser en synthaxe ES5... Plus simple pour tester en solo avec node directement
import ldap from 'ldapjs'; import ldap from 'ldapjs';
import fs from 'fs'; import fs from 'fs';
import ldapEscape from 'ldap-escape'; import ldapEscape from 'ldap-escape'; */
/*var ldap = require('ldapjs'); /**/var ldap = require('ldapjs');
var fs = require('fs'); var fs = require('fs');
var ldapEscape = require('ldap-escape');*/ var ldapEscape = require('ldap-escape');
// Important ; permet de vérifier que l'utilisateur reste connecté. // Important ; permet de vérifier que l'utilisateur reste connecté.
var ensureLoggedin = require('connect-ensure-login').ensureLoggedIn; var ensureLoggedin = require('connect-ensure-login').ensureLoggedIn;
// Point central ; tous les champs de la BDD sont 'cachés' dans config.json et pas visibles directement // Point central ; tous les champs de la BDD sont 'cachés' dans config.json et pas visibles directement
let config = JSON.parse(fs.readFileSync('./config.json', 'utf8')); let config = JSON.parse(fs.readFileSync('../../config.json', 'utf8'));
// Connection au serveur LDAP avec des temps de timeout arbitraires // Connection au serveur LDAP avec des temps de timeout arbitraires
var client = ldap.createClient({ url: config.ldap.server}); var client = ldap.createClient({ url: config.ldap.server});
/** /**
* @summary Fonction qui interroge le LDAP selon un protocole bien précis et renvoit les valeurs trouvées. * @summary Fonction qui interroge le LDAP selon un protocole bien précis et renvoit les valeurs trouvées.
* @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). Il faut l'appeler suivant un schéma requeteLDAP(dic).then((res) => { truc avec res });. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). Il faut l'appeler suivant un schéma requeteLDAP(...).then((res) => { truc avec res });. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
* @arg {string} base - DN de l'emplacement de la requête * @arg {string} base - DN de l'emplacement de la requête
* @arg {string} filter - Filtre logique de la recherche (format RFC2254) * @arg {string} filter - Filtre logique de la recherche (format RFC2254)
* @arg {{}} filter_dic - Dictionnaire qui associe les faux champs dans filter aux vraies valeurs pertinentes de la recherche * @arg {{}} filter_dic - Dictionnaire qui associe les faux champs dans filter aux vraies valeurs pertinentes de la recherche
...@@ -31,6 +31,11 @@ var client = ldap.createClient({ url: config.ldap.server}); ...@@ -31,6 +31,11 @@ var client = ldap.createClient({ url: config.ldap.server});
* @return {string[]} Résultats de la recherche * @return {string[]} Résultats de la recherche
*/ */
function requeteLDAP(base, filter, filter_dic, attributes) { function requeteLDAP(base, filter, filter_dic, attributes) {
// Debug
//console.log(base);
//console.log(filter);
//console.log(filter_dic);
//console.log(attributes);
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
// A terme mettre id du type qui se connecte (permet de pas avoir trop de demandes trop rapides) // A terme mettre id du type qui se connecte (permet de pas avoir trop de demandes trop rapides)
client.bind(config.connexion.dn, config.connexion.passwd, (err, res) => {}); client.bind(config.connexion.dn, config.connexion.passwd, (err, res) => {});
...@@ -50,12 +55,13 @@ function requeteLDAP(base, filter, filter_dic, attributes) { ...@@ -50,12 +55,13 @@ function requeteLDAP(base, filter, filter_dic, attributes) {
res.on('searchEntry', function(entry) { res.on('searchEntry', function(entry) {
attributes.forEach((element) => { attributes.forEach((element) => {
eval("vals.push(entry.object."+element+")"); eval("vals.push(entry.object."+element+")");
console.log(vals);
}); });
}); });
// Si la recherche est finie on se déconnecte et on renvoit la liste // Si la recherche est finie on se déconnecte et on renvoit la liste
res.on('end', function(res) { res.on('end', function(res) {
client.bind("", "", (err, res) => {}); client.bind("", "", (err, res) => {});
// Debug
//console.log(vals);
resolve(vals); resolve(vals);
}); });
} }
...@@ -65,49 +71,60 @@ function requeteLDAP(base, filter, filter_dic, attributes) { ...@@ -65,49 +71,60 @@ function requeteLDAP(base, filter, filter_dic, attributes) {
/** /**
* @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre. * @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre.
* @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json. * @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma listGroups(...).then((res) => { truc avec res });
* @arg {int} uid - Identifiant de l'individu à interroger * @arg {string} uid - Identifiant de l'individu à interroger (le plus souvent prenom.nom, parfois l'année, supposé valide)
* @return {string} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre * @return {string} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
*/ */
function listGroups(uid) { function listGroups(uid) {
return new Promise(function(resolve, reject) {
resolve(requeteLDAP(config.dn_users, config.filter_id, { id : uid }, config.attributes_lg).then(res => res[0]));
});
}
/**
* @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre. Assez différente de la précédente en terme d'implémentation, plus lente mais renvoir moins de résultats plus pertinents, probablement plus pérenne.
* @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma listGroups2(...).then((res) => { truc avec res });
* @arg {string} uid - Identifiant de l'individu à interroger (le plus souvent prenom.nom, parfois l'année, supposé valide)
* @return {string} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
*/
function listGroups2(uid) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
resolve(requeteLDAP(config.dn_groups, config.filter_lg, { id : uid }, config.attributes_id)); resolve(requeteLDAP(config.dn_groups, config.filter_lg, { id : uid }, config.attributes_id));
}); });
} }
/** /**
* @summary Fonction qui interroge le LDAP et retrouve la liste des membres d'un groupe. * @summary Fonction qui interroge le LDAP et retrouve la liste des membres d'un groupe.
* @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json. * @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json.
* @arg {int} gid - Identifiant du groupe à interroger * @arg {string} gid - Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule)
* @return {string} Liste des uid des membres où l'id fournie est membre (noms flat des groupes) * @return {string} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
*/ */
function listMembers(gid) { function listMembers(gid) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
resolve(requeteLDAP(config.dn_users, config.filter_lm, { id: gid }, config.attributes_id)); resolve(requeteLDAP(config.dn_groups, config.filter_id, { id: gid }, config.attributes_lm).then(res => res[0]));
}); });
} }
/** /**
* @summary Fonction qui interroge le LDAP et retrouve la liste des admins d'un groupe. * @summary Fonction qui interroge le LDAP et retrouve la liste des admins d'un groupe.
* @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json. * @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json.
* @arg {int} gid - Identifiant du groupe à interroger * @arg {string} gid - Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule)
* @return {string} Liste des uid des membres où l'id fournie est membre (noms flat des groupes) * @return {string} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
*/ */
function listAdmins(gid) { function listAdmins(gid) {
//TBC
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
resolve(requeteLDAP(gid, config.ldap_data_al)); resolve(requeteLDAP(config.key_al+"="+gid+","+config.dn_groups, config.filter_id, { id: gid }, config.attributes_al).then(res => res[0]));
}); });
} }
/** /**
* @summary Fonction qui interroge le LDAP au sujet d'un uid particulier et qui renvoit toutes ses infos. * @summary Fonction qui interroge le LDAP au sujet d'un uid particulier et qui renvoit toutes ses infos.
* @arg {string} uid - Identifiants de l'utilisateur * @arg {string} uid - Identifiant de l'utilisateur
* @return {string[]} Informations recueillies ; même quand dans TOL voir config.json. * @return {string[]} Informations recueillies ; même quand dans TOL voir config.json.
*/ */
function rens(uid) { function rens(uid) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
resolve(requeteLDAP(config.dn_users, config.filter_st, { id: uid }, config.attributes_all)); resolve(requeteLDAP(config.dn_users, config.filter_id, { id: uid }, config.attributes_all));
}); });
} }
...@@ -149,7 +166,7 @@ function idTOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9 ...@@ -149,7 +166,7 @@ function idTOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9
resolve(requeteLDAP(config.dn_users, filter, filter_dic, config.attributes_id)); resolve(requeteLDAP(config.dn_users, filter, filter_dic, config.attributes_id));
}); });
} }
/** /**
* @summary Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche. Bien mais vite inutilisable car demande trop au LDAP. * @summary Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche. Bien mais vite inutilisable car demande trop au LDAP.
* @desc Accepte des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma TOL(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues. * @desc Accepte des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma TOL(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.
...@@ -166,7 +183,6 @@ function idTOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9 ...@@ -166,7 +183,6 @@ function idTOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9
* @arg {string} c10 - Adresse courriel * @arg {string} c10 - Adresse courriel
* @arg {string} c11 - Adresse physique * @arg {string} c11 - Adresse physique
* @arg {string} c12 - Adresse ip * @arg {string} c12 - Adresse ip
* @arg {int}
* @return {string[]} Informations recueillies ; voir config.json. * @return {string[]} Informations recueillies ; voir config.json.
*/ */
function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="", c10="", c11="", c12="") { function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="", c10="", c11="", c12="") {
...@@ -207,13 +223,13 @@ function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9=" ...@@ -207,13 +223,13 @@ function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="
// Toujours gestion différenciée début et fin // Toujours gestion différenciée début et fin
res.on('searchEntry', function(entry) { res.on('searchEntry', function(entry) {
// De nouveau, iteration sur les valeurs recherchées et entrée dans la liste // De nouveau, iteration sur les valeurs recherchées et entrée dans la liste
candidatesList.push([]);
config.ldap_data_tol.searchAttributes.forEach((element) => { config.ldap_data_tol.searchAttributes.forEach((element) => {
eval("candidatesList.push(entry.object."+element+")"); eval("candidatesList.slice(-1)[0].push(entry.object."+element+")");
}); });
}); });
res.on('page', function(result, cb) { res.on('page', function(result, cb) {
resolve(candidatesList); resolve(candidatesList);
console.log("page ends");
}); });
res.on('end', function(res) { resolve(candidatesList); }); res.on('end', function(res) { resolve(candidatesList); });
} }
...@@ -222,12 +238,14 @@ function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9=" ...@@ -222,12 +238,14 @@ function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="
} }
//listMembers("drakkes").then((meList) => { console.log(meList); }); //listMembers("drakkes").then((meList) => { console.log(meList); });
//listAdmins("br").then((adList) => { console.log(adList); });
//listGroups("agopia.1999").then((grList) => { console.log(grList); }); //listGroups("agopia.1999").then((grList) => { console.log(grList); });
//listGroups2("agopia.1999").then((grList) => { console.log(grList); });
//rens("quentin.louis").then((profil) => { console.log(profil); }); //rens("quentin.louis").then((profil) => { console.log(profil); });
//idTOL("","","","","","","bda","","","","","","").then((caList) => { console.log(caList); }); //idTOL("","","","","","","bda","","","","","","").then((caList) => { console.log(caList); });
//TOL("","","","","","","faerix","","","","","","").then((caList) => { console.log(caList); }); //TOL("","","","","","","faerix","","","","","","").then((caList) => { console.log(caList); });
/* Partage pour le reste du monde ; même remarque synthaxe que pour l'import */ /* Partage pour le reste du monde ; même remarque synthaxe que pour l'import
export { listGroups, listMembers, TOL }; export { listGroups, listMembers, TOL };*/
/*module.exports ={ listGroups, listMembers, TOL };*/ module.exports ={ listGroups, listMembers, TOL };/**/
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment