diff --git a/src/ldap/internal/tools.ts b/src/ldap/internal/tools.ts index 4976592eb72543d174a3e7c58512634a571f730a..a00066eef55daabd77b1f23817084e8caa05d858 100644 --- a/src/ldap/internal/tools.ts +++ b/src/ldap/internal/tools.ts @@ -136,7 +136,7 @@ export class Tools { try { if (domain == "group") var dirtyId = ldapConfig.group.gid; else var dirtyId = ldapConfig.user.uid; - dirtyId += "="+ldapEscape.filter("${txt}", { txt: id }) + "," + ldapConfig.dn[domain]; + dirtyId += "=" + ldapEscape.filter("${txt}", { txt: id }) + "," + ldapConfig.dn[domain]; return await Basics.searchSingle(domain, ldapConfig[domain][category], dirtyId); } catch(err) { @@ -236,11 +236,11 @@ export class Tools { /** * @memberof LDAP * @summary Fonction essentielle qui permet d'ajouter un utilisateur à une catégorie d'un groupe. - * @desc Cette fonction fait essentiellement appel à d'autres fonctions de {@link Tools} ; {@link Tools.addIfNotPresent} et {@link Tools.manageInclusions}. - * Puis elle gère en interne la récursion et utilise {@link LDAP.change} pour cela. + * @desc Cette fonction fait essentiellement appel à d'autres fonctions de {@link Tools} ; {@link Tools.addIncluded} et {@link Tools.addIfAbsent}. + * Elle utilise {@link LDAP.addDFS} pour gèrer la récursion. * @arg {string} uid - Identifiant du futur membre * @arg {string} gid - Identifiant du groupe - * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné (admin, speaker, member ou follower) + * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné au type non contraint mais en pratique limité * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static @@ -261,8 +261,8 @@ export class Tools { /** * @memberof LDAP - * @summary Fonction intermédiaire naïve. - * @desc Cette fonction enlève 2 d'1 pour un des deux arbres si cette entrée n'était pas déjà absente. + * @summary Fonction intermédiaire naïve qui supprime une entrée d'une feuille si elle y existe. + * @desc Cette fonction enlève 2 d'1, feuille d'un des deux arbres si cette entrée y existe. * 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. * @arg {string} id1 - uid/gid * @arg {"group"|"user"} domain1 - Arbre concerné pour l'id1 @@ -299,12 +299,12 @@ export class Tools { /** * @memberof LDAP - * @summary Fonction intermédiaire. - * @desc Cette fonction gère les inclusions de droits. Elle ne rajoute pas un admin pour les admins, mais elle le rajoute en tant que speaker. - * Cette fonction appelle {@link remove} directement pour vraiment éliminer le personnage. + * @summary Fonction intermédiaire de suppression des droits obtenus par inclusion. + * @desc Cette fonction gère les inclusions de droits, et donc les rétrogadations. Elle ne supprime pas un admin pour les admins, mais le rajoute en tant que speaker. + * Cette fonction appelle {@link remove} directement pour vraiment éliminer le personnage des rôles inclus et {@link add} pour vraiment le rajouter. * @arg {string} uid - uid de l'utilisateur à ajouter * @arg {string} gid - gid du groupe concerné - * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné (admin, speaker, member ou follower) + * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, `false` sinon * @async * @static @@ -312,10 +312,17 @@ export class Tools { static async remIncluded(uid: string, gid: string, category: string): Promise<boolean> { switch (category) { case "members": + Tools.remove(uid, gid, "admins"); Tools.remove(uid, gid, "speakers"); + break; case "speakers": Tools.remove(uid, gid, "admins"); + // Speaker -> member + Tools.add(uid, gid, "member"); + break; case "admins": + // Admin -> speaker + Tools.add(uid, gid, "speaker"); case "followers": break; } @@ -324,12 +331,13 @@ export class Tools { /** * @memberof LDAP - * @summary Fonction intermédiaire de récursion. + * @summary Fonction intermédiaire de récursion à la suppression. * @desc Cette fonction gère les droits par récursion par une classique Depth First Search. * Cette fonction agit uniquement sur l'arbre User, de façon à différencier rôles stricts de rôles hérités. - * @arg {string} uid - uid de l'utilisateur à ajouter - * @arg {string} gid - gid du groupe concerné - * @arg {boolean} direction - direction de la recursion + * Elle est sans effet sur les groupes où l'utilisateur dispose de rôles stricts. + * @arg {string} uid - uid de l'utilisateur à supprimer + * @arg {string} gid - gid du groupe à l'origine de la récursion + * @arg {boolean} direction - direction de la recursion (true pour ascendant) * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, `false` sinon * @async * @static @@ -351,7 +359,7 @@ export class Tools { var to_visit = [gid]; while (to_visit.length > 0) { let cur_gid = to_visit.pop(); - // Si le statut de uid dans cur_gid est sun statut strict on arrête de boucler + // Si le statut de uid dans cur_gid est un statut strict on arrête de boucler for (let cat of checks) if ((await Tools.get(gid, "group", cat)).includes(uid)) continue; // Sinon on le tue et on boucle Tools.remIfPresent(uid, "user", cur_gid, "group", rol); @@ -364,40 +372,26 @@ export class Tools { * @memberof LDAP * @summary Fonction qui permet de supprimer un membre d'une catégorie existant d'un groupe. * @desc Cette fonction fait essentiellement appel à d'autres fonctions de {@link Tools} passées en argument et {@link LDAP.change}. - * Elle essaie d'assurer les propriétés d'inclusion et de récursion du LDAP. Elle est sans effet pour un admin hérité. + * Elle essaie d'assurer les propriétés d'inclusion et de récursion du LDAP (voir {@link remDFS} pour la récursion). Elle est sans effet pour un admin hérité. * Le comportement est étrange pour la suppression d'un membre hérité ; le membre est supprimé du groupe et des groupes parents, mais pas du groupe à l'origine de l'héritage. * @arg {string} uid - Identifiant de l'ex-membre * @arg {string} gid - Identifiant du groupe - * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné (admin, speaker, member ou follower) + * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné au type non contraint mais en pratique limité * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, `false` sinon * @async * @static */ static async remove(uid: string, gid: string, category : string): Promise<boolean> { - // Invulnérabilité pour les admins hérités + // Invulnérabilité pour les admins hérités (par définition, un admin hérité est dans User pas dans Group) if ((await Tools.get(gid, "group", "admins")).includes(uid) || !(await Tools.get(uid, "user", "admins")).includes(gid)) { Tools.remIfPresent(uid, "user", gid, "group", category); Tools.remIfPresent(gid, "group", uid, "user", category); - // Gestion des droits par inclusion + // Gestion des droits par inclusion (et éventuelle rétrogadation) Tools.remIncluded(uid, gid, category); - // Rétrogradation - switch (category) { - case "admins": - // Gestion des droits récursive - Tools.remDFS(uid, gid, true); - // Admin -> speaker - Tools.add(uid, gid, "speaker"); - break; - case "speakers": - // Speaker -> member - Tools.add(uid, gid, "members"); - break; - case "members": - // Gestion des droits récursive - Tools.remDFS(uid, gid, false); - case "followers": - break; - } + // Gestion des droits récursive + if (category == "admins") Tools.remDFS(uid, gid, true); + // Uniquement pour des membres ; sinon modification localisée au groupe + if (category == "members") Tools.remDFS(uid, gid, false); } return true; } @@ -461,7 +455,7 @@ export class Tools { 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... + else if (n>2) id+=(n-1).toString(); // Ensuite on continue .123, .1234, etc... return id; }); }