diff --git a/ldap_config.json b/ldap_config.json index fb9dff186f363a57153a5dbc8e06639e27925dd7..08c610e895ad81b2c100921235491cd45653ca39 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 7434e13a799a3adaf8b598f6bfccd58ce7c52bea..0b85a413091570f1f63f5630a1125f031f838d3f 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 49e5a3c99bb5ce3c0c75bc21012b9e6f76ce8670..df267f76c4461d98973c67078874bd67a3ed5838 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 bfb4567c5b18acb5816710d42b657274ca67f34f..d8438a74ff627ea1706e7244de295568f3fdfbc1 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;