/** * @file Ce fichier contient la classe de l'API du LDAP qui gère les opérations sur les groupes. Elle est destinée à être exportée pour être utilisée par les resolvers. * @author hawkspar * @memberof LDAP */ import { ldapConfig, categories } from '../internal/config'; import {Basics} from '../internal/basics'; import {Tools} from '../internal/tools'; //------------------------------------------------------------------------------------------------------------------------ // Type à exporter //------------------------------------------------------------------------------------------------------------------------ /** * @memberof LDAP * @class groupData * @var {string} gid - Identifiant du groupe * @var {string} name - Nom du groupe (souvent son nom mais pas nécessairement) * @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; 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 } //------------------------------------------------------------------------------------------------------------------------ // Classes à exporter TBT //------------------------------------------------------------------------------------------------------------------------ export class Group { /** * @memberof LDAP * @class Group * @classdesc Cette classe est une des deux classes exportables permettant de faire des opérations sur les groupes. * @summary Constructeur vide. */ constructor() {} /** * @memberof LDAP * @summary Fonction qui renvoit toutes les infos relatives à un groupe particulier. * @desc Cette fonction utilise {@link Tools.peek} avec l'interface {@link groupData}. Elle ne fait que consulter le groupe sans le changer, et en extrayant les uid des membres. * @arg {string} gid - Identifiant du groupe * @return {Promise(groupData)} Informations recueillies ; renvoie une liste de dictionnaire avec le profil complet du groupe au format {@link groupData}. * @static * @async */ static async peek(gid: string) : Promise<groupData> { try { let data = await Tools.peek<groupData>("group", gid, groupData); // Extraction des uid de parents data["parents"] = data["parents"].map(dn => dn.split(',')[0].split('=')[1]); return data; } catch(err) { throw "Erreur lors d'une recherche d'informations sur un groupe."; } } /** * @memberof LDAP * @summary Fonction qui retrouve le groupe qui ressemblent à l'input et qui correspond au type fourni. Etape 0 vers un vrai TOL (Trombino On Line) pour les groupes. * @desc Cette fonction utilise {@link Tools.search}. * @arg {groupData} input - String entré par l'utilisateur qui ressemble au nom du groupe. * @return {Promise(string[])} Liste des gid dont le nom ressemble à l'input. * @static * @async */ static async search(data: groupData) : Promise<string[]> { try { return Tools.search("group", data); } catch(err) { throw "Erreur lors de la recherche approximative d'un groupe."; } } /** * @memberof LDAP * @summary Fonction qui permet de rajouter un administrateur à un groupe. * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. Le nouvel administrateur ne devient pas membre ou porte-parole du groupe pour autant ! * @arg {string} uid - Identifiant du membre futur admin * @arg {string} gid - Identifiant du groupe * @return {boolean} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async addAdmin(uid: string, gid: string): Promise<boolean> { return Tools.add(uid, gid, "admins"); } /** * @memberof LDAP * @summary Fonction qui permet de supprimer un administrateur. * @desc Cette fonction fait essentiellement appel à {@link Tools.remove}. * Elle ne remonte pas les échelons, car cela permettrait à un admin d'un petit groupe de supprimer un admin d'un grand. * @arg {string} uid - Identifiant de l'admin à dégrader, supposé membre * @arg {string} gid - Identifiant du groupe * @return {boolean} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async remAdmin(uid: string, gid: string): Promise<boolean> { return Tools.remove(uid, gid, "admins"); } /** * @memberof LDAP * @summary Fonction qui permet de rajouter un porte-parole à un groupe. * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. Elle ne rajoute pas l'utilisateur au groupe. * @arg {string} uid - Identifiant du membre futur porte-parole * @arg {string} gid - Identifiant du groupe * @return {boolean} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async addSpeaker(uid: string, gid: string): Promise<boolean> { return Tools.add(uid, gid, "speakers"); } /** * @memberof LDAP * @summary Fonction qui permet de rétrograder un membre du stade de porte-parole d'un groupe au stade d'utilisateur. * @desc Cette fonction fait essentiellement appel à {@link Tools.remove}. Elle dégrade aussi d'un éventuel statut d'administrateur. * @arg {string} uid - Identifiant de l'admin à dégrader (pas supposé valide) * @arg {string} gid - Identifiant du groupe * @return {boolean} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async remSpeaker(uid: string, gid: string): Promise<boolean> { return Tools.remove(uid, gid, "speakers"); } /** * @memberof LDAP * @summary Fonction qui permet d'ajouter un utilisateur à un groupe. * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. * @arg {string} uid - Identifiant de l'utilisateur à ajouter * @arg {string} gid - Identifiant du groupe * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async addMember(uid: string, gid: string) : Promise<boolean> { return Tools.add(uid, gid, "members"); } /** * @memberof LDAP * @summary Fonction qui permet de supprimer un membre existant d'un groupe. * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. * Cette fonction supprime tous les droits de l'utilisateur sur le groupe, mais aussi sur les groupes sources si son statut de membre était hérité. * @arg {string} uid - Identifiant de l'ex-membre (pas supposé valide) * @arg {string} gid - Identifiant du groupe * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async remMember(uid: string, gid: string): Promise<boolean> { return Tools.remove(uid, gid, "members"); } /** * @memberof LDAP * @summary Fonction qui permet d'ajouter un sympathisant à un groupe. * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. * @arg {string} uid - Identifiant de l'utilisateur à ajouter * @arg {string} gid - Identifiant du groupe * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async addFollower(uid: string, gid: string) : Promise<boolean> { return Tools.add(uid, gid, "followers"); } /** * @memberof LDAP * @summary Fonction qui permet de supprimer un sympathisant d'un groupe. * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. * @arg {string} uid - Identifiant de l'ex-sympathisant (pas supposé valide) * @arg {string} gid - Identifiant du groupe * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async remFollower(uid: string, gid: string): Promise<boolean> { return Tools.remove(uid, gid, "followers"); } /** * @memberof LDAP * @summary Fonction intermédiaire qui reformatte un fichier User en LDAP-friendly pour tous les champs éditables * @desc Cette fonction n'est pas asynchrone ! * @arg {userData} data - Dictionnaire de données utilisateurs * @arg {dic} vals - Dictionnaire passé par référence pour être enrichi des données utilisateurs reformattées */ static reformat(data: groupData, vals : any) : void { // Ecriture de toutes les valeurs directement inscrites dans le LDAP 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, ""); } /** * @memberof LDAP * @summary Fonction qui créé un nouveau groupe dans le LDAP. * @desc Cette fonction fait une utilisation massive d'eval pour anonymiser son code ; c'est mal et cela suppose que beaucoup de soins ont été pris lors de * l'escape de ses paramètres. Appelle {@link LDAP.add} et {@link LDAP.change}, mais aussi {@link Tools.add} * pour gérer les groupes du nouvel utilisateur. Cettte application permet de rajouter des utilisateurs à toutes les catégories du groupe. * @arg {groupData} data - Dictionnaire des informations utilisateurs (voir détail des champs dans ldapConfig.json) * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async create(data: groupData) : Promise<boolean> { // Calcul d'un dictionnaire d'ajout let vals = {}; // gid de base généré à partir du nom standardisé, pas à partir de l'entrée 'gid' ! try { Tools.generateGid(data['name']).then(id => { vals[ldapConfig.group.gid] = id; vals[ldapConfig.group['name']] = id; }); } catch(err) { throw "Erreur lors de la génération d'un hruid pour créer un nouveau groupe."; } let gid: string = vals[ldapConfig.group.gid]; // Réécriture données groupes en mode LDAP-friendly Group.reformat(data, vals); // 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']]: 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 }; Basics.change("group", gid, "add", vals3).then(res => { if (!res) throw "Erreur lors de l'ajout des valeurs constantes du nouveau groupe."; }); }); // Ajout groupes parents et fils data["parents"].forEach(gid => { Basics.change("group", gid, "add", { [ldapConfig.group["parents"]]: gid }).then(res => { if (!res) throw "Erreur de l'ajout d'un groupe associé au nouveau groupe."; }); }); // Utilisation des fonctions adaptées pour assurer la cohérence de l'ensemble for (let cat of categories) { for (let uid of data[cat]) { if (!await Tools.add(uid, gid, cat)) throw "Erreur de l'ajout d'un membre au nouveau groupe."; } } return true; } /** * @memberof LDAP * @summary Fonction qui supprime un groupe du LDAP. * @desc Cette fonction commence par gérer les groupes du membre puis le supprime entièrement. A modifier une fois que le LDAP incluerait les groupes administres par une utilisateur. * Appelle {@link LDAP.clear} bien sûr, mais aussi {@link Tools.remove} pour gérer les groupes de l'utilisateur sortant. * @arg {string} gid - gid de la victime * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async delete(gid: string): Promise<boolean> { try { // Gestion des catégories en bloc d'abord let profile = await Group.peek(gid); for (let cat of categories) profile[ldapConfig.group[cat]].forEach(uid => Tools.remove(uid, gid, cat)); // Elimination if (!await Basics.clear("group",gid)) throw "Erreur lors de la suppression de la feuille dans l'arbre des groupes."; return true; } catch(err) { throw "Erreur lors de l'obtention du profil d'un groupe pour le supprimer."; } } /** * @memberof LDAP * @summary Fonction qui édite un groupe existant dans le LDAP. Sans influence sur ses membres ou admins. * @desc Appelle {@link Group.delete} suivi de {@link Group.create} pour mener son oeuvre de destruction créatrice. * Cette méthode ne permet pas de rejoindre aucun groupe, mais elle permet de changer son mot de passe, image, ou même son nom. * @arg {groupData} data - Dictionnaire des informations du groupe. * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ static async edit(data: groupData) : Promise<boolean> { try { let vals = {}; Group.reformat(data, vals); // Modification par effet de bord return Basics.change("user", data["gid"], "replace", vals); } catch(err) { throw "Erreur lors de la modification d'un groupe."; } } }