From e4e20d941a528c57d377116506cc4b39f70797ad Mon Sep 17 00:00:00 2001
From: hawkspar <quentin.chevalier@polytechnique.edu>
Date: Sat, 13 Apr 2019 17:20:12 +0200
Subject: [PATCH] Added G.G. and Hadrien's folly, new fields

---
 ldap_config.json           | 28 +++++++-----
 src/ldap/export/group.ts   | 33 ++++++++++----
 src/ldap/export/user.ts    | 90 +++++++++++++++++++++++++-------------
 src/ldap/internal/tools.ts | 12 ++++-
 4 files changed, 113 insertions(+), 50 deletions(-)

diff --git a/ldap_config.json b/ldap_config.json
index fb9dff1..08c610e 100644
--- a/ldap_config.json
+++ b/ldap_config.json
@@ -15,56 +15,62 @@
 	"user": {
 		"uid": "uid",
 		"password": "userPassword",
-
 		"givenName": "givenName",
 		"lastName": "sn",
-		
+
 		"fullName": "cn",
 		"cleanFullName": "gecos",
 		"cleanFullNameEn": "cn;lang-en",
 		
 		"nickname": "pseudonym",
-		"matricule": "matricule",
-		"import_dn": "ldapEnsDN",
+		"refNum": "refNum",
 
 		"gender": "gender",
 		"photo": "jpegPhoto",
 		"urlPhoto": "urlPhoto",
+
 		"phone": "telephoneNumber",
 		"address": "roomNumber",
 		"mail": "email",
 		"birthdate": "birthdate",
 		"nationality": "nationality",
-		"login": "loginShell",
-		"directory": "homeDirectory",
-		"classes": "objectClass",
-		
-		"idNumber": "uidNumber",
-		"const": "gidNumber",
 
 		"admins": "adminOf",
 		"speakers": "speakerOf",
 		"members": "memberOf",
-		"followers": "followerOf"
+		"followers": "followerOf",
+
+		"login": "loginShell",
+		"directory": "homeDirectory",
+
+		"classes": "objectClass",
+		"importDN": "ldapEnsDN",		
+		"idNumber": "uidNumber",
+		"const": "gidNumber"
 	},
 	"comment_4": "Placeholders et indications de contenu de certains champs du LDAP généré par frankiz pour les groupes",
 	"group": {
 		"gid": "cn",
 		"name": "sn",
 		"nameEn": "sn;lang-en",
+
 		"site": "website",
 		"email": "email",
+		
 		"description": "description",
 		"category": "groupCategory",
+		
 		"admins": "admin",
 		"admins2": "adminUid",
 		"speakers": "speaker",
 		"members": "member",
 		"followers": "follower",
+		
 		"adress": "roomNumber",
 		"idNumber": "gidNumber",
 		"logo": "jpegPhoto",
 		"urlLogo": "urlPhoto",
+
 		"classes": "objectClass",
 		"parents": "parent"
 	}
diff --git a/src/ldap/export/group.ts b/src/ldap/export/group.ts
index 7434e13..0b85a41 100644
--- a/src/ldap/export/group.ts
+++ b/src/ldap/export/group.ts
@@ -17,28 +17,38 @@ import {Tools} from '../internal/tools';
  * @class groupData
  * @var {string} gid - Identifiant du groupe
  * @var {string} name - Nom du groupe (souvent son nom mais pas nécessairement)
- * @var {string?} logo - Logo du groupe (en bytestring)
- * @var {string?} description - Description du groupe (script Markdown)
- * @var {string?} site - Site web du groupe (URL)
  * @var {"association"|"free"|"formation"|"promo"|"cours"|"sport"} category - Statut du groupe ; association, section sportive... (actuellement juste 'association' ou 'free')
  * @var {string[]} parents - Liste des groupes directement parents de celui-ci
  * @var {string[]} admins - Liste des admins du groupe
+ * @var {string[]} admins2 - Liste des admins du groupe, mais avec une synthaxe différente
  * @var {string[]} speakers - Liste des porte-parole du groupe
  * @var {string[]} members - Liste des membres du groupe
  * @var {string[]} followers - Liste des sympathisants du groupe
+ * @var {string?} logo - Logo du groupe (en bytestring)
+ * @var {string?} urlLogo - Lien vers le logo du groupe
+ * @var {string?} description - Description du groupe (script Markdown)
+ * @var {string?} email - Mail pour joindre le groupe
+ * @var {string?} site - Site web du groupe (URL)
+ * @var {string?} adress - Local du groupe
+ * @var {string?} idNumber - Identifiant numérique unique du groupe
  */
 export class groupData {
     gid: string;
 	name: string;
-	logo?: string;
-    description?: string;
-    site?: string;
 	category: "association"|"free"|"formation"|"promo"|"cours"|"sport";
     parents: string[] = [];
     admins: string[] = [];
+    admins2: string[] = [];
     speakers: string[] = [];
     members: string[] = [];
     followers: string[] = [];
+	logo?: string;
+	urlLogo?: string;
+    description?: string;
+    email?: string;
+    site?: string;
+    adress?: string;
+    idNumber?: string,
 }
 
 //------------------------------------------------------------------------------------------------------------------------
@@ -194,9 +204,12 @@ export class Group {
      */
     static reformat(data: groupData, vals : any) : void {
         // Ecriture de toutes les valeurs directement inscrites dans le LDAP
-        for (let key_att of ["name","logo","description","site","category"]) {
+        for (let key_att of ["name","logo","urlLogo","description","site","email","category","adress"]) {
             if (data[key_att] != undefined) vals[ldapConfig.group[key_att]]=data[key_att]
         };
+
+        // Elimination des accents
+        vals[ldapConfig.user['nameEn']] = data['name'].normalize('NFD').replace(/[\u0300-\u036f]/g, "");
     }
 
     /**
@@ -233,8 +246,12 @@ export class Group {
         // Appel à la fonction de base
         if (!await Basics.add("group", vals)) throw "Erreur lors de la création d'une nouvelle feuille dans l'arbre des groupes.";
 
+        // Certains champs nécessitent de petits calculs
+        
         // IMPORTANT
-        if (!await Basics.change("group", gid, "add", { [ldapConfig.group['idNumber']]: "5000" })) throw "Erreur lors de l'ajout de l'identifiant numérique du nouveau groupe.";
+        if (!await Basics.change("group", gid, "add", { [ldapConfig.group['idNumber']]: await Tools.generateId(ldapConfig.user['idNumber'], "group") })) {
+            throw "Erreur lors de l'ajout de l'identifiant numérique du nouveau groupe.";
+        }
 
         ["posixGroup", "brGroup"].forEach(cst => {
             let vals3 = { [ldapConfig.group['classes']] : cst };
diff --git a/src/ldap/export/user.ts b/src/ldap/export/user.ts
index 49e5a3c..df267f7 100644
--- a/src/ldap/export/user.ts
+++ b/src/ldap/export/user.ts
@@ -15,48 +15,51 @@ import {Tools} from '../internal/tools';
 /**
  * @memberof LDAP
  * @class partUserData
- * @desc Interface avec les données visibles au mponde extérieur.
+ * @desc Interface avec les données visibles au mpnde extérieur.
  * @var {string} uid - Identifiant utilisateur
  * @var {string} givenName - Prénom
  * @var {string} lastName - Nom
+ * @var {string?} nickname - Surnom
  * @var {string?} gender - Sexe
  * @var {string?} photo - Bytestring de la photo de l'utilisateur
+ * @var {string?} urlPhoto - Adresse de la photo de l'utilisateur
  * @var {string?} address - Adresse(s)
  * @var {string[]} admins - Liste des gid (group id, inclus section sportive, binet, PA...) dont l'utilisateur est admin ; pas forcément sous-liste de members
- * @var {string[]} speakers - Liste des gid dont l'utilisateur est porte-parole ; pas forcément sous-liste de members
- * @var {string[]} members - Liste des gid dont l'utilisateur est membre
- * @var {string[]} followers - Liste des gid dont l'utilisateur est sympathisant
+ * @var {string[]} speakers - Liste des gid dont l'utilisateur est porte-parole ; pas forcément sous-liste de members. Valeur par défaut est vide.
+ * @var {string[]} members - Liste des gid dont l'utilisateur est membre. Valeur par défaut est vide.
+ * @var {string[]} followers - Liste des gid dont l'utilisateur est sympathisant. Valeur par défaut est vide.
+ * @var {string?} phone - Numéro(s) de téléphone
+ * @var {string?} mail - Adresse(s) courriel
+ * @var {string} birthdate - Date d'anniversaire
+ * @var {string} nationality - Nationalité d'origine
+ * @var {string} refNum - Matricule
+ * @var {string?} password - Mot  de passe (jamais transmis en clair)
+ * @var {string?} importDN - Domain Name d'importation pour les inscriptions en masse
+ * @var {string?} login - Adresse de connexion à l'utilisateur directe 
+ * @var {string?} directory - Zone du serveur où sont stockés les données utilisateur
  */
-export class partUserData {
+export class userData {
     uid: string;
     givenName: string;
     lastName: string;
+    nickname?: string;
     gender?: 'M'|'F'|'U';
     photo?: string;
+    urlPhoto?: string = '';
     address?: string;
     admins: string[] = [];
     speakers: string[] = [];
     members: string[] = [];
     followers: string[] = [];
-}
-/**
- * @memberof LDAP
- * @class userData
- * @desc Interface avec toutes les données extractables pour un utilisateur.
- * @var {string?} password - Mot  de passe (jamais transmis en clair)
- * @var {string?} nickname - Surnom
- * @var {string?} phone - Numéro(s) de téléphone
- * @var {string?} mail - Adresse(s) courriel
- * @var {string} birthdate - Date d'anniversaire
- * @var {string} nationality - Nationalité d'origine
- */
-export class userData extends partUserData {
-    nickname?: string;
-    password?: string;
     phone?: string;
     mail?: string;
     birthdate: string;
     nationality?: string;
+    refNum: string;
+    password?: string;
+    importDN?: string;
+    login?: string;
+    directory?: string;
 }
 
 //------------------------------------------------------------------------------------------------------------------------
@@ -71,10 +74,10 @@ export class User {
      * @summary Constructeur vide.
      */
     constructor() {}
-     
+    
     /**
      * @memberof LDAP
-     * @summary Fonction qui renvoit les infos de base relatives à un utilisateur particulier.
+     * @summary Fonction qui renvoit les infos du niveau voulues relatives à un utilisateur particulier.
      * @desc Cette fonction utilise {@link Tools.peek} avec l'interface {@link userData}.
      * @arg {string} uid - Identifiant de l'utilisateur, supposé valide.
      * @return {Promise(userData)} Informations recueillies au format {@link userData}.
@@ -110,11 +113,26 @@ export class User {
      * @arg {dic} vals - Dictionnaire passé par référence pour être enrichi des données utilisateurs reformattées
      */
     static reformat(data: userData, vals : any) : void {
+        // Majuscule sur les premières lettres
+        vals[ldapConfig.user['givenName']] = data["givenName"][0].toUpperCase() + data["givenName"].toLowerCase().slice(1);
+        vals[ldapConfig.user['lastName']] = data["lastName"][0].toUpperCase() + data["lastName"].toLowerCase().slice(1);
+
         // Génère une erreur si un champ n'est pas rempli
-        for (let key_att of ["givenName","lastName","nickname","gender","photo","phone","adress","mail","birthdate","nationality"]) {
+        for (let key_att of ["nickname","gender","photo","urlPhoto","phone","adress","mail","birthdate","nationality","refNum","importDN"]) {
             // Ecriture de toutes les valeurs uniques
-            if (data[key_att] != undefined) vals[ldapConfig.user[key_att]]=data[key_att];
+            if (data[key_att] != undefined && data[key_att] != '')  vals[ldapConfig.user[key_att]]=data[key_att];
+            else                                                    vals[ldapConfig.user[key_att]]='';
         }
+
+        // Mot de passe crypté et salé
+        vals[ldapConfig.user['password']] = "{CRYPT}"+data['password'];
+
+        // Noms complets
+        vals[ldapConfig.user['fullName']] = data["givenName"].toLowerCase() + " " + data["lastName"].toUpperCase();
+        vals[ldapConfig.user['cleanFullName']] = vals[ldapConfig.user['fullName']];
+
+        // Elimination des accents
+        vals[ldapConfig.user['cleanFullNameEn']] = vals[ldapConfig.user['fullName']].normalize('NFD').replace(/[\u0300-\u036f]/g, "");
     }
     
     /**
@@ -148,17 +166,29 @@ export class User {
         // Appel à la fonction de base
         if (!await Basics.add("user", vals)) throw "Erreur de l'ajout de la feuille à l'arbre utilisateur.";
         
-        // Certains champs nécessitent de petits calculs        
+        // Certains champs nécessitent de petits calculs
+        let vals2 = {}
+
+        // Adressage root
+        if (data['members'].includes("on_platal")) { vals2[ldapConfig.user['login']] = "/bin/bash"; }
+        else  { vals2[ldapConfig.user['login']] = "/sbin/nologin"; }
+        
+        // Stockage machine ; dépend du prénom
+        vals2[ldapConfig.user['directory']] = '/hosting/users/' + vals['cleanFullNameEn'][0];
+
+        // Valeur nécessaire ASKIP mais inutile
+        vals2[ldapConfig.user['const']] ='5000';
+        // Création identifiant unique numérique aléatoire        
+        vals2[ldapConfig.user['idNumber']] = await Tools.generateId(ldapConfig.user['idNumber'], "user");
+
+        // Ajout LDAP
         try {
-            // Génération id aléatoire unique
-            if (!await Basics.change("user", uid, "add", { [ldapConfig.user['idNumber']]: await Tools.generateId(ldapConfig.user['idNumber'], "user") })) {
-                throw "Erreur lors de l'ajout des valeurs calculées à la feuille du nouvel utilisateur.";
-            }
+            if (!await Basics.change("user", uid, "add", vals2)) throw "Erreur lors de l'ajout des valeurs calculées à la feuille du nouvel utilisateur.";
         }
         catch(err) { throw "Erreur lors de la génération d'un id numérique pour un nouvel utilisateur."; }
 
         ["posixAccount", "shadowAccount", "brUser"].forEach(cst => {
-            let tmp = { [ldapConfig.user['class']] : cst };
+            let tmp = { [ldapConfig.user['classes']] : cst };
             Basics.change("user", uid, "add", tmp).then(res => {
                 if (!res) throw "Erreur lors de l'ajout d'une valeur constante à la feuille du nouvel utilisateur.";
             });
diff --git a/src/ldap/internal/tools.ts b/src/ldap/internal/tools.ts
index bfb4567..d8438a7 100644
--- a/src/ldap/internal/tools.ts
+++ b/src/ldap/internal/tools.ts
@@ -138,6 +138,7 @@ export class Tools {
      * @desc Cette fonction rajoute 2 dans 1 pour un des deux arbres si cette entrée n'était pas déjà présente de façon à ne pas créer de doublon.
      * La symétrie entre 1 et 2 est voulue et permet de gérer indifférement l'ajout d'un individu dans un groupe ou d'un groupe à un individu.
      * Renvoie vrai si une modification a été nécessaire, faux sinon.
+     * Gestion différenciée des admins, qui doivent être inscrit deux fois pour groupe.
      * @arg {string} id1 - uid/gid
      * @arg {"group"|"user"} domain1 - Arbre concerné pour l'id1
      * @arg {string} id2 - gid/uid
@@ -156,6 +157,11 @@ export class Tools {
                 else                    var id = ldapConfig[domain2].uid;
                 let tmp = { [ldapConfig[domain1][category]] : id+"="+id2+","+ldapConfig.dn[domain2] };
                 if (!await Basics.change(domain1, id1, "add", tmp)) throw "Erreur lors de la modification dans l'arbre "+domain2+" pour ajouter une entrée dans la catégorie voulue.";
+                // Cas spécial pour les admins
+                if (category == "admins" && domain1 == "group") {
+                    let tmp2 = { [ldapConfig[domain1]["admins"]] : id2 };
+                    if (!await Basics.change("group", id1, "add", tmp2)) throw "Erreur lors de la modification dans l'arbre "+domain2+" pour la modif admin spéciale.";
+                }
                 return true;
             }
             // Renvoie faux si aucune modification n'est nécessaire
@@ -281,13 +287,17 @@ export class Tools {
                 var catName = ldapConfig[domain1][category];
                 if (!await Basics.change(domain1, id1, "del", catName)) throw "Erreur lors de la suppression de tous les "+category+" de l'identifiant "+id1+".";
                 // Les rajoute un par un, sauf pour le supprimé
-                l.forEach(id => {
+                l.forEach(async function(id) {
                     if (id!=id2) {
                         if (domain2 == "group") var id_n = ldapConfig[domain2].gid;
                         else                    var id_n = ldapConfig[domain2].uid;
                         Basics.change(domain1, id1, "add", {catName: id_n+'='+id+','+ldapConfig[domain2].dn}).then(res => {
                             if (!res) throw "Erreur lors du ré-ajout d'un autre "+domain1+" de la catégorie "+category+".";
                         });
+                        // Cas spécial pour les admins
+                        if (category == "admins" && domain1 == "group") {
+                            if (!await Basics.change("group", id1, "add", {catName : id})) throw "Erreur lors de la modification dans l'arbre "+domain2+" pour la modif admin spéciale.";
+                        }
                     }
                 });
                 return true;
-- 
GitLab