Subversion Repositories eFlore/Applications.coel

Rev

Rev 1852 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
/**
 * Service d'itentification d'un utilisateur.
 * Encodage en entrée : utf8
 * Encodage en sortie : utf8
 * Cas d'utilisation :
 * 1: Aucun login ni mot de passe transmis
 *      1: L'application retourne l'identifiant de session en cours
 *      2: Une identification est toujours active, cette identification est retournée
 * 
 * 2: Ce service recoit un login et un mot de passe
 *      1 : On tente d'identifier l'utilisateur
 *      2 : Si réussi, l'état passe à : connecté
 *      3 : sinon, l'état passe à : pas connecté
 * 
 * 3: Ce service reçoit un identifiant (différent du login) et aucun mot de passe :
 *      1 : Déconnexion
 * 
 *  En résumé, utilisation des URLs :
 *  /CoelUtilisateur/                                   : retour identifiant de session si jamais connecté, sinon retour de l'id (+ login et mot de passe)
 *  /CoelUtilisateur/ * / * /                   : idem ci-dessus
 *  /CoelUtilisateur/id                                 : déconexion
 *  /CoelUtilisateur/login/mot_de_passe : connexion
 *
 * @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
 * @author David DELON <david.delon@clapas.net>abstract 
 * @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
 * @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
 * @version $Id$
 * @copyright 2009
 */
class CoelUtilisateur extends Coel { 
        
        private $licence_acceptee = false;
        
        // TODO : controle systematique... dans tous les services si connected : name cookie = name service
        public function getRessource(){
                $this->getElement(array('*','*'));
        }       

        public function getElement($param){
                $identification = false;
                $info = array();
                
                // Si la licence n'a pas été accepté nous réinitialisons tout
                if (!isset($param[2]) && (!isset($_COOKIE['coel_licence']) || (isset($_COOKIE['coel_licence']) && $_COOKIE['coel_licence'] != 1))) {
                        $this->deconnecterUtilisateur();
                }
                
                // S'il y a 3 paramètres, c'est qu'on cherche à mettre à jour la licence
                if (isset($param[2])) {
                        $this->debug[] = "Licence acceptee";
                        $this->licence_acceptee = true; 
                        // Mise à jour de la licence
                        if (!$this->accepterLicence($param[0])) {
                                $this->debug[] = "Erreur de mise à jour licence utilisateur";
                        }
                } else if (isset($param[1])) { // Non connecté : vérification
                        if (!$this->getUtilisateur()) { // Si non identifié
                                $id = null;
                                if ($param[0] == '*' && $param[1] == '*') {     // Tentative d'identification depuis les cookies permanents
                                        if (isset($_COOKIE['coel_login']) && ($this->souvenirUtilisateur($_COOKIE['coel_login'], $_COOKIE['coel_mot_de_passe'])))  {
                                                $id = $this->getUtilisateurId();
                                                $identification = true;
                                                $info = array($id, $identification, $this->getUtilisateurNomComplet(), $this->getUtilisateurPrenom(), $this->getUtilisateurNom(), $this->getParametre());
                                        }
                                } else if ($this->connecterUtilisateur($param[0], $param[1], 1)) { // Tentative d'identification depuis les paramêtres passés dans l'url du service
                                        $id = $this->getUtilisateurId();
                                        $identification = true;
                                        $info = array($id, $identification, $this->getUtilisateurNomComplet(), $this->getUtilisateurPrenom(), $this->getUtilisateurNom(), $this->getParametre());
                                } 
                                
                                // L'identification a échouée, nous retournons un session_id comme identifiant
                                if (is_null($id)) {                                     
                                        $id = session_id();
                                        $identification = false;
                                        $info = array($id, $identification);
                                }
                        } else { // Déjà identifié
                                $id = $this->getUtilisateurId();
                                $identification = true;
                                $info = array($id, $identification, $this->getUtilisateurNomComplet(), $this->getUtilisateurPrenom(), $this->getUtilisateurNom(), $this->getParametre());
                        }
                } else { // Déconnexion
                        $this->deconnecterUtilisateur();
                        $id = session_id();
                        $identification = false;
                        $info = array($id, $identification);
                }

                array_unshift($info, $this->getLicence());
                
                // Envoie sur la sortie standard
                $this->envoyer($info);
        }
        
        private function getUtilisateurId() {
                if ($utilisateur = $this->getUtilisateur()) {
                        return $utilisateur['id'];
                } else {
                        return '';
                }
        }
        
        private function getUtilisateurLogin() {
                if ($utilisateur = $this->getUtilisateur()) {
                        return $utilisateur['login'];
                } else {
                        return '';
                }
        }
        
        private function getUtilisateurNomComplet() {
                if ($utilisateur = $this->getUtilisateur()) {
                        return $utilisateur['nom_complet'];
                } else {
                        return '';
                }
        }
        
        private function getUtilisateurPrenom() {
                if ($utilisateur = $this->getUtilisateur()) {
                        return $utilisateur['prenom'];
                } else {
                        return '';
                }
        }
        
        private function getUtilisateurNom() {
                if ($utilisateur = $this->getUtilisateur()) {
                        return $utilisateur['nom'];
                } else {
                        return '';
                }
        }
        
        private function getParametre() {
                if ($utilisateur = $this->getUtilisateur()) {
                        return $utilisateur['parametre'];
                } else {
                        return '';
                }
        }
        
        private function getLicence()   {
                if (!empty($_SESSION['coel_utilisateur']))      {
                        return (string) $_SESSION['coel_utilisateur']['licence'];
                } else {
                        return '';
                }
        }
                
        private function getInfosAnnuaire()     {
                if (!empty($_SESSION['coel_infosAnnuaire']))    {
                        return $_SESSION['coel_infosAnnuaire'];
                } else  {
                        return '';
                }
        }

        private function deconnecterUtilisateur() {
                $_SESSION['coel_utilisateur'] = '';
                $_SESSION['coel_infosAnnuaire'] = '';
                $this->supprimerCookie('coel_login');
                $this->supprimerCookie('coel_mot_de_passe');
                $this->supprimerCookie('coel_licence');
                $this->supprimerCookie('coel_permanence');              
        }
        
        private function connecterUtilisateur($login, $mot_de_passe, $permanence = 1) {
                // Dans tous les cas, on récupère les informations de l'utilisateur présentes dans l'annuaire de Tela Botanica
                $infosAnnuaire = $this->obtenirInfosAnnuaire($login);
                $this->setInfosAnnuaire($infosAnnuaire);

                if ($mot_de_passe == 'debug' && $utilisateur_existant = $this->chargerUtilisateur($login)) {
                        $this->setUtilisateur($utilisateur_existant, $permanence);
                        return true;
                } else {
                        $mot_de_passe_sha1 = sha1($mot_de_passe);
                        $mot_de_passe_md5 = md5($mot_de_passe);                 
                        if ($utilisateur_existant = $this->chargerUtilisateur($login, $mot_de_passe_sha1)) {
                                // OK, nous poursuivons
                        } else if ($utilisateur_existant = $this->chargerUtilisateur($login, $mot_de_passe_md5)) {
                                // Mise à jour du mot de passe md5 en sha1
                                $this->mettreAJourMotDePasse($login, $mot_de_passe_md5, $mot_de_passe_sha1);
                                $utilisateur_existant['mot_de_passe'] = $mot_de_passe_sha1;
                        }
                        
                        // Vérification de la nécessité de mettre à jour l'utilisateur du COEL vis à vis de l'annuaire de Tela Botanica
                        if (!is_null($infosAnnuaire) &&  $this->avoirBesoinMiseAJour($utilisateur_existant)) {
                                $this->debug[] = "Besoin d'une mise à jour";
                                // Vérifions que la personne s'est bien identifiée
                                if ($infosAnnuaire['mot_de_passe'] == $mot_de_passe_md5) {
                                        $this->debug[] = "Identification correcte avec md5";
                                        $utilisateur_existant = $this->getInfoAnnuaireCoelDepuisInfoAnnuaireDistant($mot_de_passe_sha1, $infosAnnuaire);
                                        
                                        $presence_dans_coel = $this->verifierPresenceUtilisateur($infosAnnuaire['id']);
                                        $this->debug[] = "Presence:$presence_dans_coel";
                                        if ($presence_dans_coel) {
                                                // Nécessite de faire une mise à jour
                                                $this->debug[] = "Mise à jour de l'utilisateur {$infosAnnuaire['id']}";
                                                $this->mettreAJourUtilisateur($login, $mot_de_passe_sha1, $infosAnnuaire);
                                                $utilisateur_existant['licence'] = (int) $this->recupererLicenceUtilisateur($infosAnnuaire['id']);
                                        } else {
                                                // Nécessite d'ajouter le nouvel utilisateur
                                                $this->debug[] = "Ajout d'une nouvel utilisateur";
                                                $this->ajouterUtilisateurACoel($infosAnnuaire, $mot_de_passe_sha1);
                                        }
                                        
                                        $this->setUtilisateur($utilisateur_existant, $permanence);
                                } else {
                                        $this->debug[] = "Identification INCORRECTE avec md5";
                                        return false;
                                }
                        } else if ($utilisateur_existant != false) {
                                // L'utilisateur est toutefois présent dans l'annuaire de COEL, est correctement identifié  et n'a pas besoin de mise à jour
                                $this->setUtilisateur($utilisateur_existant, $permanence);
                        } else {
                                // L'utilisateur n'existe ni dans l'annuaire de Tela Botanica ni dans celui de COEL
                                return false;
                        }
                        
                        // L'utilisateur a t il accepté la licence? Nécessaire pour être connecté!
                        if ($utilisateur_existant['licence'] == 1)      {
                                return true;
                        } else {
                                return false;
                        }
                }
        }
        
        private function avoirBesoinMiseAJour($info_annuaire_coel) {
                $necessite_maj = false;
                if ($info_annuaire_coel == false) {
                        // Le login et/ou le mot de passe a pu changer
                        $necessite_maj = true;
                } else {
                        $info_annuaire_distant = $this->getInfosAnnuaire();
                        if ($this->comparerInfosAnnuairesDistantEtCoel($info_annuaire_distant, $info_annuaire_coel) == false) {
                                $necessite_maj = true;
                        }
                }
                return $necessite_maj;
        }
        
        private function comparerInfosAnnuairesDistantEtCoel($annuaire_distant, $annuaire_coel) {
                $identique = true;
                $tableau_annuaire_distant = array('nom' => $annuaire_distant['nom'], 
                        'prenom' => $annuaire_distant['prenom'], 
                        'ville' => $annuaire_distant['ville'], 
                        'code_postal' => $annuaire_distant['code_postal']);
                $tableau_annuaire_coel = array('nom' => $annuaire_coel['nom'], 
                        'prenom' => $annuaire_coel['prenom'], 
                        'ville' => $annuaire_coel['ville'], 
                        'code_postal' => $annuaire_coel['code_postal']);
                foreach ($tableau_annuaire_distant as $cle => $valeur) {
                        if ($tableau_annuaire_coel[$cle] != $valeur) {
                                $identique = false;
                                break;
                        }
                }
                return $identique;
        }
        
        private function getInfoAnnuaireCoelDepuisInfoAnnuaireDistant($mot_de_passe_sha1, $infos) {
                $cp_fmt_nom_complet = $infos['prenom'].' '.$infos['nom']; 
                $utilisateur_existant = array('id' => $infos['id'], 'login' =>  $infos['courriel'], 
                                                        'mot_de_passe' => $mot_de_passe_sha1,
                                                        'nom_complet' => $cp_fmt_nom_complet, 'nom' => $infos['nom'], 'prenom' => $infos['prenom'], 
                                                        'parametre' => '', 'licence' => '0');
                return $utilisateur_existant;
        }
        
        private function verifierPresenceUtilisateur($id) {
                $present = false;
                $requete =      'SELECT COUNT(cp_id_personne) AS nbre '.
                                        'FROM coel_personne '.
                                        "WHERE cp_ce_annuaire = {$this->bdd->quote($id)} ".
                                        "       AND cp_ce_annuaire = cp_id_personne ";
                try {
                        $nbre = $this->bdd->query($requete)->fetchColumn();
                        if (0 == $nbre) {
                                $this->debug[] = "Utilisateur NON présent dans l'annuaire de COEL.";
                        } else if (1 == $nbre) {
                                $this->debug[] = "Utilisateur présent dans l'annuaire de COEL.";
                                $present = true;
                        } else if (false === $nbre) {
                                $this->debug[] = "Erreur dans la requête de vérification de présence dans l'annuaire de COEL.";
                        }
                } catch (PDOException $e) {
                        $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage());
                }
                
                return $present;
        }
        
        private function recupererLicenceUtilisateur($id) {
                $requete =      'SELECT cp_mark_licence '.
                                        'FROM coel_personne '.
                                        "WHERE cp_ce_annuaire = {$this->bdd->quote($id)} ".
                                        "       AND cp_ce_annuaire = cp_id_personne ";
                try {
                        $licence = $this->bdd->query($requete)->fetchColumn();
                        if ($licence === false) {
                                $this->debug[] = "La licence n'a pas pu être récupérée.";
                                return 0;
                        } else {
                                return $licence;
                        }
                } catch (PDOException $e) {
                        $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage());
                }
        }
        
        private function mettreAJourMotDePasse($login, $mot_de_passe_md5, $mot_de_passe_sha1) {
                try {
                        $requete =      'UPDATE coel_personne '.
                                                "SET cp_mot_de_passe = '$mot_de_passe_sha1' ". 
                                                "WHERE cp_login = '$login' ".
                                                "       AND cp_mot_de_passe = '$mot_de_passe_md5' ";
                        // Ajout des données
                        $resultat = $this->bdd->exec($requete);
                        if ($resultat === false) {
                                $this->messages[] = "Le mot de passe de l'utilisateur n'a pas été mis à jour car la requête a échouée.";
                        }
                } catch (PDOException $e) {
                        $messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
                }
        }
        
        private function mettreAJourUtilisateur($login, $mot_de_passe_sha1, $infos) {
                try {
                        $cp_fmt_nom_complet = $infos['prenom'].' '.$infos['nom'];
                        $requete =      'UPDATE coel_personne '.
                                                "SET cp_id_personne = '{$infos['id']}', ".
                                                "       cp_fmt_nom_complet = '$cp_fmt_nom_complet', cp_prenom = '{$infos['prenom']}', cp_nom = '{$infos['nom']}', ".
                                                "       cp_code_postal = '{$infos['code_postal']}', cp_ville = '{$infos['ville']}', cp_truk_courriel = '{$infos['courriel']}', ".
                                                "       cp_login = '{$infos['courriel']}', cp_mot_de_passe = '$mot_de_passe_sha1', cp_ce_annuaire = '{$infos['id']}' ".
                                                "WHERE cp_login = '$login' ".
                                                "       AND cp_mot_de_passe = '{$infos['mot_de_passe']}' ";
                        
                        // Ajout des données
                        $resultat = $this->bdd->exec($requete);
                        if ($resultat === false) {
                                $this->messages[] = "L'utilisateur n'a pas été mis à jour car la requête a échouée.";
                        }
                } catch (PDOException $e) {
                        $messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
                }
        }
        
        private function ajouterUtilisateurACoel($infos, $mot_de_passe_sha1) {
                try {
                        // Construction de la requête d'ajout
                        // Notes : pour rester compatibles avec l'annuaire de Tela, les utilisateurs sont ajoutés directement avec l'id
                        // de l'annuaire Tela. Dans CoelPersonne, les personnes qui ne sont pas utilisateur sont ajoutés avec un id supérieur à 100 000
                        $cp_fmt_nom_complet = $infos['prenom'].' '.$infos['nom'];
                        $cp_mark_licence = '0'; 
                        $requete =      'INSERT INTO coel_personne '.
                                                '       (cp_id_personne, cp_fmt_nom_complet, cp_prenom, cp_nom, cp_code_postal, '. 
                                                '       cp_ville, cp_truk_courriel, cp_login, cp_mot_de_passe, cp_ce_annuaire, cp_mark_licence) '.
                                                "VALUES ('{$infos['id']}', '$cp_fmt_nom_complet', '{$infos['prenom']}', '{$infos['nom']}', ". 
                                                "'{$infos['code_postal']}', '{$infos['ville']}', '{$infos['courriel']}', '{$infos['courriel']}', '".$mot_de_passe_sha1."', ". 
                                                "'{$infos['id']}', $cp_mark_licence) ";
                        //$this->debug[] = $requete;
                        // Ajout des données
                        $resultat = $this->bdd->exec($requete);
                        if ($resultat === false) {
                                $this->debug[] = "Utilisateur NON ajouté dans coel_personne car la requête a échouée.";
                        } else {
                                $this->debug[] = "Utilisateur ajouté à coel_personne.";
                        }
                } catch (PDOException $e) {
                        $messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
                }
        }
        
        private function souvenirUtilisateur($login, $mot_de_passe_sha1) {
                if ($login == '' && $mot_de_passe_sha1 == '') {
                        return false;
                } else if ($utilisateur_existant = $this->chargerUtilisateur($login, $mot_de_passe_sha1)) {
                        if ($utilisateur_existant['mot_de_passe'] == $mot_de_passe_sha1) {
                                $this->setUtilisateur($utilisateur_existant, $_COOKIE['coel_permanence']);
                                return true;
                        } else {
                                return false; 
                        }
                }
        }

        private function obtenirInfosAnnuaire($login)   {
                $url_annuaire = $this->config['coel']['urlAnnuaire'];
                $login_annuaire = $this->config['coel']['loginAnnuaire'];
                $mdp_annuaire = $this->config['coel']['mdpAnnuaire'];

                $posds = strpos($url_annuaire, "//");
                $protocole = substr($url_annuaire, 0, $posds+2);
                $reste_adresse = substr($url_annuaire, $posds+2);
                // auth HTTP basic cracra
                $url_annuaire = $protocole . $login_annuaire . ':' . $mdp_annuaire . "@" . $reste_adresse;
                $url_annuaire .= '/' . $login;
                $url_annuaire .= '/xml'; // @TODO un jour, faire en sorte que ça lise du JSON

                $resultat_annuaire = file_get_contents($url_annuaire);
                $tableau_annuaire = null;
                if ($xml_utilisateur = simplexml_load_string($resultat_annuaire))       {
                        // La fonction a retourné un objet
                        foreach ($xml_utilisateur->children() as $key => $val) {
                                if ((string) $val != '') {
                                        $tableau_annuaire[$key] = (String) $val;
                                }
                        } 
                }
                return $tableau_annuaire;
        }

        private function setInfosAnnuaire($infosAnnuaire)       {
                $_SESSION['coel_infosAnnuaire'] = $infosAnnuaire;
        }

        private function accepterLicence($login)        {
                $sortie = false;
                try {
                        $requete =      'UPDATE coel_personne '.
                                                'SET cp_mark_licence = 1 '.
                                                "WHERE cp_login = {$this->bdd->quote($login)} ";
                        $resultat = $this->bdd->exec($requete);
                        if ($resultat === false) {
                                $this->debug[] = "La table Personne n'a pas été mise à jour car la requête a échouée.";
                        } else {
                                $this->debug[] = "Création du cookie licence.";
                                $_SESSION['coel_utilisateur']['licence'] = '1';
                                $this->setCookiePersistant('coel_licence', '1');
                                $sortie = true;
                        }
                } catch (PDOException $e) {
                        $messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
                }
                return $sortie;
        }
}
?>