Skip to content
Snippets Groups Projects
Forked from an inaccessible project.
user.ts 8.26 KiB
/**
 * @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, userData, categories } from '../internal/config';
import {Basics} from '../internal/basics';
import {Tools} from '../internal/tools';

//------------------------------------------------------------------------------------------------------------------------
// Classes à exporter TBT
//------------------------------------------------------------------------------------------------------------------------

export {userData};

export class User {
    /**
     * @memberof LDAP
     * @class User
     * @classdesc Cette classe est une des deux classes exportables permettant de faire des opérations sur les utilisateurs.
     * @summary Constructeur vide.
     */
    constructor() {}
     
    /**
     * @memberof LDAP
     * @summary Fonction qui renvoit les infos de base 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}.
     * @static
     * @async
     */
    static async peek(uid: string) : Promise<userData> {
        try { 
            let data = await Tools.peek<userData>("user", uid, userData);
            for (let cat of categories) data[cat] = data[cat].map(dn => dn.split(',')[0].split('=')[1]);
            return data;
        }
        catch(err) {
            throw "Error while peeking a user.";
        }
    }
    
    /**
     * @memberof LDAP
     * @summary Fonction qui retrouve les uid des paxs validant les critères de recherche. Utiliser {@link User.peek} au cas par cas après pour obtenir les vraies infos.
     * @desc Cette fonction utilise {@link Tools.search}.
     * @arg {userData} data - Dictionnaire contenant les données nécessaires à la recherche. Les valeurs sont celles entrées par l'utilisateur et sont par hypothèse
     * comme des sous-parties compactes des valeurs renvoyées. Tous les champs ci-dessous peuvent être indifféremment des listes (par exemple pour chercher un membre
     * de plusieurs groupes) ou des éléments isolés. Si un champ n'est pas pertinent, le mettre à '' ou undefined.
     * @return {Promise(string[])} gids des profils qui "match" les critères proposés.
     * @static
     * @async
     */
    static async search(data: userData) : Promise<string[]> {
        try {
            return Tools.search("user", data);
        }
        catch(err) {
            throw "Erreur lors de la recherche approximative d'un utilisateur.";
        }
    }
    
    /**
     * @memberof LDAP
     * @summary Fonction qui créé un nouvel utilisateur dans le LDAP.
     * @desc Appelle {@link LDAP.add} bien sûr, mais aussi {@link Tools.add} pour gérer les groupes du nouvel utilisateur.
     * @arg {userData} data - Dictionnaire des informations utilisateurs. Des erreurs peuvent apparaître si tous les champs ne sont pas remplis.
     * Cette application permet de rejoindre des groupes en masse pour toute catégorie, à la fois façon Sigma et CAS.
     * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
     * @async
     * @static
     */
    static async create(data: userData): Promise<boolean> {
        // Calcul d'un dictionnaire d'ajout
        let vals = {};

        // 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("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 : string = vals[ldapConfig.user.uid];

        // 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"]) {
            // Ecriture de toutes les valeurs uniques
            if (data[key_att] != undefined) vals[ldapConfig.user[key_att]]=data[key_att];
        }

        // 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
        let vals3={};

        // ldapConfiguration du mot de passe utilisateur
        // Le préfixe {CRYPT} signifie que le mdp est hashé dans OpenLDAP voir : https://www.openldap.org/doc/admin24/security.html 
        vals3[ldapConfig.user['password']] = "{CRYPT}"+data['password'];
        
        // Ecriture d'un surnom s'il y a lieu
        if ((data['nickname']!=undefined) && (data['nickname']!='')) vals3[ldapConfig.user['nickname']]=data['nickname'];
        try {
            // Génération id aléatoire unique
            vals3[ldapConfig.user['id']]= await Tools.generateId(ldapConfig.user['id'], "user");
        }
        catch(err) {
            throw "Erreur lors de la génération d'un id numérique pour un nouvel utilisateur.";
        }

        // Code root
        vals3[ldapConfig.user['cleanFullName']]=data['fullName'].replace(':', ';').toLowerCase().normalize('UFD');

        // Inscription des valeurs calculées
        if (!await Basics.change("user", uid, "add", vals3)) throw "Erreur lors de l'ajout des valeurs calculées à la feuille du nouvel utilisateur.";

        ["posixAccount", "shadowAccount", "brUser"].forEach(cst => {
            let val3={};
            vals3[ldapConfig.user['class']]=cst;
            Basics.change("user", uid, "add", vals3).then(res => {
                if (!res) throw "Erreur lors de l'ajout d'une valeur constante à la feuille du nouvel utilisateur.";
            });
        });

        // Ajout dans les groupes à la catégorie voulue
        for (let cat of categories) {
            for (let gid of data[cat]) Tools.add(uid, gid, cat).then(res => {
                if (!res) throw "Erreur de l'ajout d'un membre au nouveau groupe.";
            });
        }
        return true;
    }

    //------------------------------------------------------------------------------------------------------------------------
    // Fonctions de suppression TBT
    //------------------------------------------------------------------------------------------------------------------------
    
    /**
     * @memberof LDAP
     * @summary Fonction qui supprime un utilisateur du LDAP.
     * @desc Cette fonction commence par gérer les groupes du membre puis le supprime entièrement.
     * Appelle {@link LDAP.clear} bien sûr, mais aussi {@link Tools.remove} pour gérer les groupes de l'utilisateur sortant.
     * @arg {string} uid - uid de la victime
     * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
     * @async
     * @static
     */
    static async delete(uid: string): Promise<boolean> {
        try {
            // Gestion des groupes de l'utilisateur d'abord
            let profil = await User.peek(uid);
            for (let cat of categories) profil[ldapConfig.user[cat]].forEach(gid => Tools.remove(uid, gid, cat));
        }
        catch(err) {
            throw "Erreur lors de l'obtention des informations de l'utilisateur à supprimer.";
        }
        // Elimination pure et simple
        if (!Basics.clear("user", uid)) throw "Erreur lors de la suppression de l'utilisateur.";
        return true;
    }

    /**
     * @memberof LDAP
     * @summary Fonction qui édite un utilisateur existant dans le LDAP.
     * @desc Appelle simplement {@link Tools.edit}. Sans effet sur les groupes de l'utilisateur concerné.
     * @arg {userData} data - Dictionnaire des informations utilisateurs
     * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon
     * @async
     * @static
     */
    static async edit(data : userData) : Promise<boolean> {
        try {
            return Tools.edit("user",data);
        }
        catch(err) {
            throw "Erreur lors de la modification d'un utilisateur.";
        }
    }
}