From 10e9ab7735b71b2ac19e1a53da0d57e4d76ab01c Mon Sep 17 00:00:00 2001
From: hawkspar <quentin.chevalier@polytechnique.edu>
Date: Sat, 9 Feb 2019 14:11:14 +0100
Subject: [PATCH] Fin gestion sabotage GRZ

---
 src/ldap/export/group.ts    | 27 +++----------------
 src/ldap/export/user.ts     |  4 +--
 src/ldap/internal/basics.ts | 16 ++++++++----
 src/ldap/internal/tools.ts  | 52 ++++++++++++++-----------------------
 4 files changed, 37 insertions(+), 62 deletions(-)

diff --git a/src/ldap/export/group.ts b/src/ldap/export/group.ts
index 4796b52..8ead0ac 100644
--- a/src/ldap/export/group.ts
+++ b/src/ldap/export/group.ts
@@ -128,26 +128,7 @@ export class Group {
      * @async
      * @static
      */
-    static async remMember(uid: string, gid: string): Promise<boolean> {
-        return await Tools.remove(uid, gid, "members");
-
-        // Ce qui suit est une suppression récursive du membre dans tous les groupes fils
-        let stack = [];
-        let res = true;
-        let visited = {};
-        stack.push(gid);
-        while (stack.length>0) {
-            let cur_id = stack.pop();
-            if (visited[cur_id] == undefined) {
-                visited[cur_id] = true;
-                res = res   &&  await Tools.remove(uid, cur_id, "admins") &&
-                                await Tools.remove(uid, cur_id, "speakers") &&
-                                await Tools.remove(uid, cur_id, "members");
-                stack.concat(await Basics.searchSingle("group", ldapConfig.group.childs, cur_id));
-            }
-        }
-        return  res;
-    }
+    static async remMember(uid: string, gid: string): Promise<boolean> { return await Tools.remove(uid, gid, "members"); }
 
     /**
      * @memberof LDAP
@@ -190,8 +171,8 @@ export class Group {
 
         // gid de base généré à partir du nom standardisé, pas à partir de l'entrée 'gid' !
         try {
-            Tools.generateReadableId(data['name']).then(id => {
-                vals[ldapConfig.key_id]=id;
+            Tools.generateReadableId("group", data['name']).then(id => {
+                vals[ldapConfig.group.gid]=id;
                 vals[ldapConfig.group['name']]=id;
             });
         }
@@ -199,7 +180,7 @@ export class Group {
             throw "Erreur lors de la génération d'un hruid pour créer un nouveau groupe.";
         }
 
-        let gid: string = vals[ldapConfig.key_id];
+        let gid: string = vals[ldapConfig.group.gid];
 
         // Ecriture de toutes les valeurs directement inscrites dans le LDAP
         for (let key_att in data) { vals[ldapConfig.group[key_att]]=data[key_att] };
diff --git a/src/ldap/export/user.ts b/src/ldap/export/user.ts
index 0d192ec..cd9c643 100644
--- a/src/ldap/export/user.ts
+++ b/src/ldap/export/user.ts
@@ -85,13 +85,13 @@ export class User {
         // uid de base généré à partir de nom et prénom, plus potentiellement promo et un offset
         // MEF mélange de Promise et de fonction standard
         try {
-            Tools.generateUid(data['givenName'],data['lastName'],data['birthdate']).then(id => { vals[ldapConfig.key_id]=id; } );
+            Tools.generateUid("user",data['givenName'],data['lastName'],data['birthdate']).then(id => { vals[ldapConfig.user.uid]=id; } );
         }
         catch(err) {
             throw "Erreur lors de la génération d'un hruid pour un nouvel utilisateur.";
         }
 
-        let uid = vals[ldapConfig.key_id];
+        let uid = vals[ldapConfig.user.uid];
 
         // Génère une erreur si un champ n'est pas rempli
         for (let key_att in data) {
diff --git a/src/ldap/internal/basics.ts b/src/ldap/internal/basics.ts
index 942790d..88a741b 100644
--- a/src/ldap/internal/basics.ts
+++ b/src/ldap/internal/basics.ts
@@ -197,8 +197,10 @@ export class Basics {
      */
     static async change(domain: 'group'|'user', id: string, op: "add"|"del"|"replace", mod: dic) : Promise<boolean> {
         Basics.adminBind();
-        let dn = ldapConfig.key_id+'='+id+','
-        dn+=ldapConfig.dn[domain];
+        let dn ="";
+        if (domain == 'group')  { dn += ldapConfig.group.gid; }
+        else                    { dn += ldapConfig.user.uid; }
+        dn+='='+id+','+ldapConfig.dn[domain];
         // Modification LDAP selon dn fourni en argument (pourrait prendre une liste de Changes)
         client.modify(ldapEscape.dn("${txt}", {txt: dn}), new ldap.Change({
             operation: op,
@@ -217,7 +219,7 @@ export class Basics {
      * @summary Fonction qui permet de rajouter un élément sur le LDAP.
      * @desc  Cette fonction traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode add).
      * @arg {'gr'|'us'} domain - Emplacement de la requête (groupe ou utilisateur)
-     * @arg {Object.<string, string>} vals - Dictionnaire contenant les valeurs à créer (contient un champ en ldapConfig.key_id)
+     * @arg {Object.<string, string>} vals - Dictionnaire contenant les valeurs à créer (contient un champ en ldapConfig)
      * @arg {Object} vals[key] - Nouvelle valeur pour le champ key
      * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon.
      * @static
@@ -225,7 +227,9 @@ export class Basics {
      */
     static async add(domain: 'group'|'user', vals) : Promise<boolean> {
         Basics.adminBind();
-        let dn = ldapConfig.key_id+"="+vals[ldapConfig.key_id];
+        let dn = "";
+        if (domain == "group")  { dn+=ldapConfig.group.gid+"="+vals[ldapConfig.group.gid]; }
+        else                    { dn+=ldapConfig.user.uid+"="+vals[ldapConfig.user.uid]; }
         dn+=ldapConfig.dn[domain];
         // Ajout LDAP selon la ldapConfiguration en argument
         client.add(ldapEscape.dn("${txt}", { txt: dn}), vals, err => {
@@ -249,7 +253,9 @@ export class Basics {
      */
     static async clear(domain: 'group'|'user', id: string) : Promise<boolean> {
         Basics.adminBind();
-        let dn = ldapConfig.key_id+'='+id+','
+        let dn = "";
+        if (domain == "group")  { dn+=ldapConfig.group.gid+"="+id; }
+        else                    { dn+=ldapConfig.user.uid+"="+id; }
         dn+=ldapConfig.dn[domain];
         // Suppression LDAP
         client.del(ldapEscape.dn("${txt}", {txt: dn}), err => {
diff --git a/src/ldap/internal/tools.ts b/src/ldap/internal/tools.ts
index 1c5a6b2..1879fbd 100644
--- a/src/ldap/internal/tools.ts
+++ b/src/ldap/internal/tools.ts
@@ -84,8 +84,10 @@ export class Tools {
                 });
             }
         }
-        // Appel avec filtre de l'espace 
-        return Basics.searchSingle(domain, ldapConfig.key_id, null, filter);
+        // Appel avec filtre de l'espace
+        if (domain == "group")  { var att=ldapConfig.group.gid; }
+        else                    { var att=ldapConfig.user.uid; }
+        return Basics.searchSingle(domain, att, null, filter);        
     }
     
     /**
@@ -241,7 +243,9 @@ export class Tools {
     static async ensureUnique(value: string, attribute: string, domain: 'group'|'user', changeValue: (string, number) => string, n: number=0) : Promise<string> {
         // Recherche d'autres occurences de l'id
         try {
-            return Basics.searchSingle(domain, ldapConfig.key_id, null, "("+attribute+"="+value+")").then(function (matches: string[]) {
+            if (domain == "group")  { var att=ldapConfig.group.gid; }
+            else                    { var att=ldapConfig.user.uid; }
+            return Basics.searchSingle(domain, att, null, "("+attribute+"="+value+")").then(function (matches: string[]) {
                 if (!matches) { throw ""; }
                 // On renvoit la valeur si elle est bien unique
                 else if (matches.length=0) { return value; }
@@ -258,6 +262,7 @@ export class Tools {
      * @memberof LDAP
      * @summary Cette fonction génère un uid standard, puis le fait évoluer jusqu'à ce qu'il soit unique.
      * @desc Limité à un appel à {@link Tools.ensureUnique} avec les bons paramètres, et quelques opérations sur l'uid pour qu'il soit valide (escape, normalisation).
+     * @param {"group"|"user"} domain - Arbre à parcourir
      * @param {string} givenName - Prénom
      * @param {string} lastName - Nom
      * @param {string} promotion - Année de promotion
@@ -265,10 +270,12 @@ export class Tools {
      * @static
      * @async
      */
-    static async generateUid(givenName: string, lastName: string, promotion: string) : Promise<string> {
+    static async generateUid(domain : "group"|"user", givenName: string, lastName: string, promotion: string) : Promise<string> {
         try {
+            if (domain == "group")  { var att=ldapConfig.group.gid; }
+            else                    { var att=ldapConfig.user.uid; }
             // normalize et lowerCase standardisent le format
-            return Tools.ensureUnique((givenName+'.'+lastName).toLowerCase().normalize('UFD'), ldapConfig.key_id, "user", (id: string, n: number) => {
+            return Tools.ensureUnique((givenName+'.'+lastName).toLowerCase().normalize('UFD'), att, "user", (id: string, n: number) => {
                 if (n=1) { id+='.'+promotion; }                // Si prénom.nom existe déjà, on rajoute la promo
                 else if (n=2) { id+='.'+(n-1).toString(); }    // Puis si prénom.nom.promo existe déjà on passe à nom.prenom.promo .1
                 else if (n>2) { id+=n; }                        // Ensuite on continue .123, .1234, etc...
@@ -284,15 +291,18 @@ export class Tools {
      * @memberof LDAP
      * @summary Cette fonction génère un id lisible, puis le fait évoluer jusqu'à ce qu'il soit unique.
      * @desc Limité à un appel à {@link Tools.ensureUnique} avec les bons paramètres, et quelques opérations sur l'uid pour qu'il soit valide (escape, normalisation).
+     * @param {"group"|"user"} domain - Arbre à parcourir
      * @param {string} name - Nom
      * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié
      * @static
      * @async
      */
-    static async generateReadableId(name: string) : Promise<string> {
+    static async generateReadableId(domain : "group"|"user", name: string) : Promise<string> {
         try {
+            if (domain == "group")  { var att=ldapConfig.group.gid; }
+            else                    { var att=ldapConfig.user.uid; }
             // normalize et lowerCase standardisent le format
-            return Tools.ensureUnique(name.toLowerCase().normalize('UFD'), ldapConfig.key_id, "group", (id: string, n: number) => {
+            return Tools.ensureUnique(name.toLowerCase().normalize('UFD'), att, domain, (id: string, n: number) => {
                 if (n=1)        { id+='.'+n.toString(); }   // Si nom existe déjà, on essaie nom.1
                 else if (n>1)   { id+=n.toString(); }       // Ensuite on continue .12, .123, etc...
                 return id;
@@ -306,15 +316,15 @@ export class Tools {
     /**
      * @memberof LDAP
      * @summary Cette fonction teste une valeur dummy (0) pour un identifiant numérique puis le fait évoluer aléatoirement (entre 1 et 100 000) jusqu'à ce qu'il soit unique.
-     * @param {string} attribut - Intitulé exact de l'id concerné
+     * @param {string} attribute - Intitulé exact de l'id concerné
      * @param {"gr"|"us"} domain - Domaine dans lequel l'attribut doit être unique
      * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié
      * @static
      * @async
      */
-    static async generateId(attribut: string, domain: "group"|"user") : Promise<string> {
+    static async generateId(attribute: string, domain: "group"|"user") : Promise<string> {
         try {
-            return Tools.ensureUnique("0", attribut, domain, (id,n) => { return Math.floor((Math.random() * 100000) + 1).toString(); });
+            return Tools.ensureUnique("0", attribute, domain, (id,n) => { return Math.floor((Math.random() * 100000) + 1).toString(); });
         }
         catch(err) {
             throw "Erreur lors de l'assurance de l'unicité d'un unique identifier numérique.";
@@ -336,28 +346,6 @@ export class Tools {
     static async get(id : string, domain : "user"|"group", category : string): Promise<string[]> {
         try {
             return await Basics.searchSingle(domain, ldapConfig[domain][category], id);
-            
-            // Ce qui suit est une récursion qui sera déplacée dans la gestion des autorisations 
-            if (!(category in ["admins","members"]) || domain=="user") {
-                return await Basics.searchSingle(domain, ldapConfig[domain][category], id);
-            }
-            else {
-                // Clean depth-first search for inherited members and admins
-                let stack = [];
-                let res = [];
-                let visited = {};
-                stack.push(id);
-                while (stack.length>0) {
-                    let cur_id = stack.pop();
-                    if (visited[cur_id] == undefined) {
-                        visited[cur_id] = true;
-                        res.concat(await Basics.searchSingle("group", ldapConfig.group[category], cur_id));
-                        // In the end, the precise category only changes the iteration direction
-                        if (category == "members")  { stack.concat(await Basics.searchSingle("group", ldapConfig.group.childs, cur_id)); }
-                        else                        { stack.concat(await Basics.searchSingle("group", ldapConfig.group.parents, cur_id)); }
-                    }
-                }
-            }
         }
         catch(err) {
             throw "Erreur lors d'une recherche générique d'un membre d'une certaine catégorie d'un groupe.";
-- 
GitLab