Rev 1765 | Go to most recent revision | 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;
}
}
?>