Subversion Repositories eFlore/Applications.coel

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1497 jpm 1
<?php
2
/**
3
 * Service d'itentification d'un utilisateur.
4
 * Encodage en entrée : utf8
5
 * Encodage en sortie : utf8
6
 * Cas d'utilisation :
7
 * 1: Aucun login ni mot de passe transmis
8
 * 	1: L'application retourne l'identifiant de session en cours
9
 * 	2: Une identification est toujours active, cette identification est retournée
10
 *
11
 * 2: Ce service recoit un login et un mot de passe
12
 * 	1 : On tente d'identifier l'utilisateur
13
 * 	2 : Si réussi, l'état passe à : connecté
14
 * 	3 : sinon, l'état passe à : pas connecté
15
 *
16
 * 3: Ce service reçoit un identifiant (différent du login) et aucun mot de passe :
17
 * 	1 : Déconnexion
18
 *
19
 *  En résumé, utilisation des URLs :
20
 *  /CoelUtilisateur/					: retour identifiant de session si jamais connecté, sinon retour de l'id (+ login et mot de passe)
21
 *  /CoelUtilisateur/ * / * /			: idem ci-dessus
22
 *  /CoelUtilisateur/id					: déconexion
23
 *  /CoelUtilisateur/login/mot_de_passe	: connexion
24
 *
25
 * @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
26
 * @author David DELON <david.delon@clapas.net>abstract
27
 * @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
28
 * @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
29
 * @version $Id$
30
 * @copyright 2009
31
 */
32
class CoelUtilisateur extends Coel {
33
 
1508 jpm 34
	private $licence_acceptee = false;
35
 
1497 jpm 36
	// TODO : controle systematique... dans tous les services si connected : name cookie = name service
37
	public function getRessource(){
38
		$this->getElement(array('*','*'));
39
	}
40
 
41
	public function getElement($param){
42
		$identification = false;
43
		$info = array();
44
 
45
		// Si la licence n'a pas été accepté nous réinitialisons tout
1508 jpm 46
		if (!isset($param[2]) && (!isset($_COOKIE['coel_licence']) || (isset($_COOKIE['coel_licence']) && $_COOKIE['coel_licence'] != 1))) {
1497 jpm 47
			$this->deconnecterUtilisateur();
48
		}
49
 
50
		// S'il y a 3 paramètres, c'est qu'on cherche à mettre à jour la licence
51
		if (isset($param[2])) {
1508 jpm 52
			$this->debug[] = "Licence acceptee";
53
			$this->licence_acceptee = true;
1497 jpm 54
			// Mise à jour de la licence
55
			if (!$this->accepterLicence($param[0]))	{
56
				$this->debug[] = "Erreur de mise à jour licence utilisateur";
57
			}
58
		} else if (isset($param[1])) { // Non connecté : vérification
59
			if (!$this->getUtilisateur()) { // Si non identifié
60
				$id = null;
61
				if ($param[0] == '*' && $param[1] == '*') {	// Tentative d'identification depuis les cookies permanents
62
					if (isset($_COOKIE['coel_login']) && ($this->souvenirUtilisateur($_COOKIE['coel_login'], $_COOKIE['coel_mot_de_passe'])))  {
63
						$id = $this->getUtilisateurId();
64
						$identification = true;
65
						$info = array($id, $identification, $this->getUtilisateurNomComplet(), $this->getUtilisateurPrenom(), $this->getUtilisateurNom(), $this->getParametre());
66
					}
67
				} else if ($this->connecterUtilisateur($param[0], $param[1], 1)) { // Tentative d'identification depuis les paramêtres passés dans l'url du service
68
					$id = $this->getUtilisateurId();
69
					$identification = true;
70
					$info = array($id, $identification, $this->getUtilisateurNomComplet(), $this->getUtilisateurPrenom(), $this->getUtilisateurNom(), $this->getParametre());
71
				}
72
 
73
				// L'identification a échouée, nous retournons un session_id comme identifiant
74
				if (is_null($id)) {
75
					$id = session_id();
76
					$identification = false;
77
					$info = array($id, $identification);
78
				}
79
			} else { // Déjà identifié
80
				$id = $this->getUtilisateurId();
81
				$identification = true;
82
				$info = array($id, $identification, $this->getUtilisateurNomComplet(), $this->getUtilisateurPrenom(), $this->getUtilisateurNom(), $this->getParametre());
83
			}
84
		} else { // Déconnexion
85
			$this->deconnecterUtilisateur();
86
			$id = session_id();
87
			$identification = false;
88
			$info = array($id, $identification);
89
		}
90
 
91
		array_unshift($info, $this->getLicence());
92
 
93
		// Envoie sur la sortie standard
94
		$this->envoyer($info);
95
	}
96
 
97
	private function getUtilisateurId() {
98
		if ($utilisateur = $this->getUtilisateur()) {
99
			return $utilisateur['id'];
100
		} else {
101
			return '';
102
		}
103
	}
104
 
105
	private function getUtilisateurLogin() {
106
		if ($utilisateur = $this->getUtilisateur()) {
107
			return $utilisateur['login'];
108
		} else {
109
			return '';
110
		}
111
	}
112
 
113
	private function getUtilisateurNomComplet() {
114
		if ($utilisateur = $this->getUtilisateur()) {
115
			return $utilisateur['nom_complet'];
116
		} else {
117
			return '';
118
		}
119
	}
120
 
121
	private function getUtilisateurPrenom() {
122
		if ($utilisateur = $this->getUtilisateur()) {
123
			return $utilisateur['prenom'];
124
		} else {
125
			return '';
126
		}
127
	}
128
 
129
	private function getUtilisateurNom() {
130
		if ($utilisateur = $this->getUtilisateur()) {
131
			return $utilisateur['nom'];
132
		} else {
133
			return '';
134
		}
135
	}
136
 
137
	private function getParametre() {
138
		if ($utilisateur = $this->getUtilisateur()) {
139
			return $utilisateur['parametre'];
140
		} else {
141
			return '';
142
		}
143
	}
144
 
145
	private function getLicence()	{
146
		if (!empty($_SESSION['coel_utilisateur']))	{
147
			return (string) $_SESSION['coel_utilisateur']['licence'];
148
		} else {
149
			return '';
150
		}
151
	}
152
 
153
	private function getInfosAnnuaire()	{
154
		if (!empty($_SESSION['coel_infosAnnuaire']))	{
155
			return $_SESSION['coel_infosAnnuaire'];
156
		} else	{
157
			return '';
158
		}
159
	}
160
 
161
	private function deconnecterUtilisateur() {
162
		$_SESSION['coel_utilisateur'] = '';
163
		$_SESSION['coel_infosAnnuaire'] = '';
164
		$this->supprimerCookie('coel_login');
165
		$this->supprimerCookie('coel_mot_de_passe');
166
		$this->supprimerCookie('coel_licence');
167
		$this->supprimerCookie('coel_permanence');
168
	}
169
 
170
	private function connecterUtilisateur($login, $mot_de_passe, $permanence = 1) {
171
		// Dans tous les cas, on récupère les informations de l'utilisateur présentes dans l'annuaire de Tela Botanica
172
		$infosAnnuaire = $this->obtenirInfosAnnuaire($login);
173
		$this->setInfosAnnuaire($infosAnnuaire);
174
 
175
		if ($mot_de_passe == 'debug' && $utilisateur_existant = $this->chargerUtilisateur($login)) {
176
			$this->setUtilisateur($utilisateur_existant, $permanence);
177
			return true;
178
		} else {
179
			$mot_de_passe_sha1 = sha1($mot_de_passe);
180
			$mot_de_passe_md5 = md5($mot_de_passe);
181
			if ($utilisateur_existant = $this->chargerUtilisateur($login, $mot_de_passe_sha1)) {
182
				// OK, nous poursuivons
183
			} else if ($utilisateur_existant = $this->chargerUtilisateur($login, $mot_de_passe_md5)) {
184
				// Mise à jour du mot de passe md5 en sha1
185
				$this->mettreAJourMotDePasse($login, $mot_de_passe_md5, $mot_de_passe_sha1);
186
				$utilisateur_existant['mot_de_passe'] = $mot_de_passe_sha1;
187
			}
188
 
189
			// Vérification de la nécessité de mettre à jour l'utilisateur du COEL vis à vis de l'annuaire de Tela Botanica
190
			if (!is_null($infosAnnuaire) &&  $this->avoirBesoinMiseAJour($utilisateur_existant)) {
1508 jpm 191
				$this->debug[] = "Besoin d'une mise à jour";
1497 jpm 192
				// Vérifions que la personne s'est bien identifiée
193
				if ($infosAnnuaire['mot_de_passe'] == $mot_de_passe_md5) {
1508 jpm 194
					$this->debug[] = "Identification correcte avec md5";
1497 jpm 195
					$utilisateur_existant = $this->getInfoAnnuaireCoelDepuisInfoAnnuaireDistant($mot_de_passe_sha1, $infosAnnuaire);
196
 
197
					$presence_dans_coel = $this->verifierPresenceUtilisateur($infosAnnuaire['id']);
1508 jpm 198
					$this->debug[] = "Presence:$presence_dans_coel";
1497 jpm 199
					if ($presence_dans_coel) {
200
						// Nécessite de faire une mise à jour
1508 jpm 201
						$this->debug[] = "Mise à jour de l'utilisateur {$infosAnnuaire['id']}";
1587 aurelien 202
						$this->mettreAJourUtilisateur($login, $mot_de_passe_sha1, $infosAnnuaire);
1497 jpm 203
						$utilisateur_existant['licence'] = (int) $this->recupererLicenceUtilisateur($infosAnnuaire['id']);
204
					} else {
205
						// Nécessite d'ajouter le nouvel utilisateur
1508 jpm 206
						$this->debug[] = "Ajout d'une nouvel utilisateur";
1497 jpm 207
						$this->ajouterUtilisateurACoel($infosAnnuaire, $mot_de_passe_sha1);
208
					}
209
 
210
					$this->setUtilisateur($utilisateur_existant, $permanence);
211
				} else {
1508 jpm 212
					$this->debug[] = "Identification INCORRECTE avec md5";
1497 jpm 213
					return false;
214
				}
215
			} else if ($utilisateur_existant != false) {
216
				// L'utilisateur est toutefois présent dans l'annuaire de COEL, est correctement identifié  et n'a pas besoin de mise à jour
217
				$this->setUtilisateur($utilisateur_existant, $permanence);
218
			} else {
219
				// L'utilisateur n'existe ni dans l'annuaire de Tela Botanica ni dans celui de COEL
220
				return false;
221
			}
222
 
223
			// L'utilisateur a t il accepté la licence? Nécessaire pour être connecté!
224
			if ($utilisateur_existant['licence'] == 1)	{
225
				return true;
226
			} else {
227
				return false;
228
			}
229
		}
230
	}
231
 
232
	private function avoirBesoinMiseAJour($info_annuaire_coel) {
233
		$necessite_maj = false;
234
		if ($info_annuaire_coel == false) {
235
			// Le login et/ou le mot de passe a pu changer
236
			$necessite_maj = true;
237
		} else {
238
			$info_annuaire_distant = $this->getInfosAnnuaire();
239
			if ($this->comparerInfosAnnuairesDistantEtCoel($info_annuaire_distant, $info_annuaire_coel) == false) {
240
				$necessite_maj = true;
241
			}
242
		}
243
		return $necessite_maj;
244
	}
245
 
246
	private function comparerInfosAnnuairesDistantEtCoel($annuaire_distant, $annuaire_coel) {
247
		$identique = true;
248
		$tableau_annuaire_distant = array('nom' => $annuaire_distant['nom'],
249
			'prenom' => $annuaire_distant['prenom'],
250
			'ville' => $annuaire_distant['ville'],
251
			'code_postal' => $annuaire_distant['code_postal']);
252
		$tableau_annuaire_coel = array('nom' => $annuaire_coel['nom'],
253
			'prenom' => $annuaire_coel['prenom'],
254
			'ville' => $annuaire_coel['ville'],
255
			'code_postal' => $annuaire_coel['code_postal']);
256
		foreach ($tableau_annuaire_distant as $cle => $valeur) {
257
			if ($tableau_annuaire_coel[$cle] != $valeur) {
258
				$identique = false;
259
				break;
260
			}
261
		}
262
		return $identique;
263
	}
264
 
265
	private function getInfoAnnuaireCoelDepuisInfoAnnuaireDistant($mot_de_passe_sha1, $infos) {
266
		$cp_fmt_nom_complet = $infos['prenom'].' '.$infos['nom'];
267
		$utilisateur_existant = array('id' => $infos['id'], 'login' =>	$infos['courriel'],
268
					   		'mot_de_passe' => $mot_de_passe_sha1,
269
							'nom_complet' => $cp_fmt_nom_complet, 'nom' => $infos['nom'], 'prenom' => $infos['prenom'],
270
							'parametre' => '', 'licence' => '0');
271
		return $utilisateur_existant;
272
	}
273
 
274
	private function verifierPresenceUtilisateur($id) {
275
		$present = false;
276
		$requete =	'SELECT COUNT(cp_id_personne) AS nbre '.
277
					'FROM coel_personne '.
1508 jpm 278
					"WHERE cp_ce_annuaire = {$this->bdd->quote($id)} ".
1635 aurelien 279
					"	AND cp_ce_annuaire = cp_id_personne ";
1497 jpm 280
		try {
281
			$nbre = $this->bdd->query($requete)->fetchColumn();
1508 jpm 282
			if (0 == $nbre) {
283
				$this->debug[] = "Utilisateur NON présent dans l'annuaire de COEL.";
284
			} else if (1 == $nbre) {
285
				$this->debug[] = "Utilisateur présent dans l'annuaire de COEL.";
1497 jpm 286
				$present = true;
1508 jpm 287
			} else if (false === $nbre) {
288
				$this->debug[] = "Erreur dans la requête de vérification de présence dans l'annuaire de COEL.";
1497 jpm 289
			}
290
		} catch (PDOException $e) {
291
			$this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage());
292
		}
293
 
294
		return $present;
295
	}
296
 
297
	private function recupererLicenceUtilisateur($id) {
298
		$requete =	'SELECT cp_mark_licence '.
299
					'FROM coel_personne '.
1508 jpm 300
					"WHERE cp_ce_annuaire = {$this->bdd->quote($id)} ".
1635 aurelien 301
					"	AND cp_ce_annuaire = cp_id_personne ";
1497 jpm 302
		try {
303
			$licence = $this->bdd->query($requete)->fetchColumn();
304
			if ($licence === false) {
305
				$this->debug[] = "La licence n'a pas pu être récupérée.";
306
				return 0;
307
			} else {
308
				return $licence;
309
			}
310
		} catch (PDOException $e) {
311
			$this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage());
312
		}
313
	}
314
 
315
	private function mettreAJourMotDePasse($login, $mot_de_passe_md5, $mot_de_passe_sha1) {
316
		try {
1508 jpm 317
			$requete = 	'UPDATE coel_personne '.
1497 jpm 318
		   				"SET cp_mot_de_passe = '$mot_de_passe_sha1' ".
319
		   				"WHERE cp_login = '$login' ".
1508 jpm 320
		   				"	AND cp_mot_de_passe = '$mot_de_passe_md5' ";
1497 jpm 321
			// Ajout des données
322
			$resultat = $this->bdd->exec($requete);
323
			if ($resultat === false) {
324
				$this->messages[] = "Le mot de passe de l'utilisateur n'a pas été mis à jour car la requête a échouée.";
325
			}
326
		} catch (PDOException $e) {
327
			$messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
328
		}
329
	}
330
 
1587 aurelien 331
	private function mettreAJourUtilisateur($login, $mot_de_passe_sha1, $infos) {
1497 jpm 332
		try {
333
		   	$cp_fmt_nom_complet = $infos['prenom'].' '.$infos['nom'];
334
			$requete = 	'UPDATE coel_personne '.
1508 jpm 335
		   				"SET cp_id_personne = '{$infos['id']}', ".
1497 jpm 336
						"	cp_fmt_nom_complet = '$cp_fmt_nom_complet', cp_prenom = '{$infos['prenom']}', cp_nom = '{$infos['nom']}', ".
337
						"	cp_code_postal = '{$infos['code_postal']}', cp_ville = '{$infos['ville']}', cp_truk_courriel = '{$infos['courriel']}', ".
338
						"	cp_login = '{$infos['courriel']}', cp_mot_de_passe = '$mot_de_passe_sha1', cp_ce_annuaire = '{$infos['id']}' ".
339
		   				"WHERE cp_login = '$login' ".
1587 aurelien 340
		   				"	AND cp_mot_de_passe = '{$infos['mot_de_passe']}' ";
1508 jpm 341
 
1497 jpm 342
			// Ajout des données
343
			$resultat = $this->bdd->exec($requete);
344
			if ($resultat === false) {
345
				$this->messages[] = "L'utilisateur n'a pas été mis à jour car la requête a échouée.";
346
			}
347
		} catch (PDOException $e) {
348
			$messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
349
		}
350
	}
351
 
352
	private function ajouterUtilisateurACoel($infos, $mot_de_passe_sha1) {
353
		try {
354
			// Construction de la requête d'ajout
355
		   	// Notes : pour rester compatibles avec l'annuaire de Tela, les utilisateurs sont ajoutés directement avec l'id
356
		   	// de l'annuaire Tela. Dans CoelPersonne, les personnes qui ne sont pas utilisateur sont ajoutés avec un id supérieur à 100 000
357
		   	$cp_fmt_nom_complet = $infos['prenom'].' '.$infos['nom'];
358
		   	$cp_mark_licence = '0';
359
		   	$requete = 	'INSERT INTO coel_personne '.
1765 aurelien 360
		   				'	(cp_id_personne, cp_fmt_nom_complet, cp_prenom, cp_nom, cp_code_postal, '.
1508 jpm 361
						'	cp_ville, cp_truk_courriel, cp_login, cp_mot_de_passe, cp_ce_annuaire, cp_mark_licence) '.
1765 aurelien 362
		   				"VALUES ('{$infos['id']}', '$cp_fmt_nom_complet', '{$infos['prenom']}', '{$infos['nom']}', ".
1508 jpm 363
		   				"'{$infos['code_postal']}', '{$infos['ville']}', '{$infos['courriel']}', '{$infos['courriel']}', '".$mot_de_passe_sha1."', ".
1497 jpm 364
		   				"'{$infos['id']}', $cp_mark_licence) ";
1508 jpm 365
		   	//$this->debug[] = $requete;
1497 jpm 366
			// Ajout des données
367
			$resultat = $this->bdd->exec($requete);
368
			if ($resultat === false) {
1508 jpm 369
				$this->debug[] = "Utilisateur NON ajouté dans coel_personne car la requête a échouée.";
370
			} else {
371
				$this->debug[] = "Utilisateur ajouté à coel_personne.";
1497 jpm 372
			}
373
		} catch (PDOException $e) {
374
			$messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
375
		}
376
	}
377
 
378
	private function souvenirUtilisateur($login, $mot_de_passe_sha1) {
379
		if ($login == '' && $mot_de_passe_sha1 == '') {
380
			return false;
381
		} else if ($utilisateur_existant = $this->chargerUtilisateur($login, $mot_de_passe_sha1)) {
382
			if ($utilisateur_existant['mot_de_passe'] == $mot_de_passe_sha1) {
383
				$this->setUtilisateur($utilisateur_existant, $_COOKIE['coel_permanence']);
384
				return true;
385
			} else {
386
				return false;
387
			}
388
		}
389
	}
1852 mathias 390
 
1497 jpm 391
	private function obtenirInfosAnnuaire($login)	{
392
		$url_annuaire = $this->config['coel']['urlAnnuaire'];
393
		$login_annuaire = $this->config['coel']['loginAnnuaire'];
394
		$mdp_annuaire = $this->config['coel']['mdpAnnuaire'];
1852 mathias 395
 
396
		$posds = strpos($url_annuaire, "//");
397
		$protocole = substr($url_annuaire, 0, $posds+2);
398
		$reste_adresse = substr($url_annuaire, $posds+2);
399
		// auth HTTP basic cracra
400
		$url_annuaire = $protocole . $login_annuaire . ':' . $mdp_annuaire . "@" . $reste_adresse;
401
		$url_annuaire .= '/' . $login;
402
		$url_annuaire .= '/xml'; // @TODO un jour, faire en sorte que ça lise du JSON
403
 
1497 jpm 404
		$resultat_annuaire = file_get_contents($url_annuaire);
405
		$tableau_annuaire = null;
406
		if ($xml_utilisateur = simplexml_load_string($resultat_annuaire))	{
407
			// La fonction a retourné un objet
408
			foreach ($xml_utilisateur->children() as $key => $val) {
409
				if ((string) $val != '') {
410
			  		$tableau_annuaire[$key] = (String) $val;
411
				}
412
			}
413
		}
414
		return $tableau_annuaire;
415
	}
1852 mathias 416
 
1497 jpm 417
	private function setInfosAnnuaire($infosAnnuaire)	{
418
		$_SESSION['coel_infosAnnuaire'] = $infosAnnuaire;
419
	}
1852 mathias 420
 
1508 jpm 421
	private function accepterLicence($login)	{
1497 jpm 422
		$sortie = false;
423
		try {
424
			$requete = 	'UPDATE coel_personne '.
425
						'SET cp_mark_licence = 1 '.
1508 jpm 426
						"WHERE cp_login = {$this->bdd->quote($login)} ";
1497 jpm 427
			$resultat = $this->bdd->exec($requete);
428
			if ($resultat === false) {
1508 jpm 429
				$this->debug[] = "La table Personne n'a pas été mise à jour car la requête a échouée.";
1497 jpm 430
			} else {
1508 jpm 431
				$this->debug[] = "Création du cookie licence.";
1497 jpm 432
				$_SESSION['coel_utilisateur']['licence'] = '1';
1508 jpm 433
				$this->setCookiePersistant('coel_licence', '1');
1497 jpm 434
				$sortie = true;
435
			}
436
		} catch (PDOException $e) {
437
		 	$messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage(), $requete);
438
		}
439
		return $sortie;
440
	}
441
}
442
?>