Subversion Repositories Applications.annuaire

Compare Revisions

No changes between revisions

Ignore whitespace Rev 579 → Rev 580

/trunk/jrest/bibliotheque/JRestService.php
526,5 → 526,41
$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu);
return $contenu;
}
 
/**
* Crée un nom Wiki (de la forme "JeanTalus") à partir des données de l'utilisateur;
* gère l'utilisation du pseudo mais pas la collision de noms Wiki @TODO s'en occuper
*
* @param array $infos des infos de profil utilisateur - on admet qu'elles contiennent "intitule"
* @return string un nom wiki correspondant à l' "intitulé" de l'utilisateur (prénom-nom ou pseudo)
* ou la valeur par défaut de $defaut si celui-ci est fourni et si le nom Wiki n'a pu être construit
*/
public function formaterNomWiki($intitule, $defaut="ProblemeNomWiki") {
$nw = $this->convertirEnCamelCase($intitule);
// on sait jamais
if ($nw == "") {
$nw = $defaut;
}
 
return $nw;
}
protected function convertirEnCamelCase($str) {
// Suppression des accents
$str = $this->supprimerAccents($str);
// Suppression des caractères non alphanumériques
$str = preg_replace('/[^\da-z]/i', '', ucwords(strtolower($str)));
return $str;
}
 
protected function supprimerAccents($str, $charset='utf-8') {
$str = htmlentities($str, ENT_NOQUOTES, $charset);
 
$str = preg_replace('#&([A-za-z])(?:acute|cedil|caron|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str);
$str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str); // pour les ligatures e.g. 'œ'
$str = preg_replace('#&[^;]+;#', '', $str); // supprime les autres caractères
 
return $str;
}
}
?>
/trunk/jrest/services/Auth.php
28,6 → 28,9
/** Nom du cookie */
protected $nomCookie = "this_is_not_a_good_cookie_name";
 
/** Bibliothèque de gestion des utilisateurs */
protected $utilisateur;
 
public function __construct($config, $demarrer_session = true) {
parent::__construct($config, $demarrer_session);
$this->clef = file_get_contents("clef-auth.ini");
38,9 → 41,20
$this->dureeJeton = $this->config['auth']['duree_jeton'];
$this->dureeCookie = $this->config['auth']['duree_cookie'];
$this->nomCookie = $this->config['auth']['nom_cookie'];
// gestion des utilisateurs @WARNING on utilise un service comme une lib, c'est
// mal !! @TODO séparer service et lib (ou réécrire tout ce foutoir)
$this->utilisateur = new Utilisateur($config);
}
 
/**
* Retourne la bobliothèque de gestion des utilisateurs (pour utilisation
* par les classes partenaires)
*/
public function getUtilisateur() {
return $this->utilisateur;
}
 
/**
* Notice d'utilisation succincte
* @TODO essayer de choisir entre anglais et français
*/
192,19 → 206,26
$this->erreur("parameters <login> and <password> required");
}
$acces = false;
$objAuth = null;
// connexion à un partenaire ?
$infosPartenaire = array();
if ($partenaire != '') {
$classeAuth = "AuthPartner" . ucfirst(strtolower($partenaire));
try {
$fichierClasse = "auth/$classeAuth.php";
/*if (! file_exists($fichierClasse)) {
$this->erreur('unknown partner "' . $partenaire . '"');
}*/
$fichierClasse = getcwd() . "/services/auth/$classeAuth.php"; // @TODO vérifier si getcwd() est fiable dans ce cas
if (! file_exists($fichierClasse)) {
$this->erreur("unknown partner '$partenaire'");
}
require $fichierClasse;
$objAuth = new $classeAuth($this);
$authPartenaire = new $classeAuth($this);
// authentification par le partenaire
$acces = $objAuth->verifierAcces($login, $password);
$acces = $authPartenaire->verifierAcces($login, $password);
if ($acces === true) {
// copie des infos dans l'annuaire si besoin
$authPartenaire->synchroniser();
}
// détails à ajouter au jeton local
$infosPartenaire['partenaire'] = $partenaire;
$infosPartenaire['jetonPartenaire'] = $authPartenaire->getJetonPartenaire();
} catch(Exception $e) {
$this->erreur($e->getMessage(), 500);
}
211,8 → 232,6
} else {
// authentification locale
$acces = $this->verifierAcces($login, $password);
// faux polylmorphisme pour éviter des "if" partout
$objAuth = new Utilisateur($this->config);
}
if ($acces === false) {
$this->detruireCookie();
222,7 → 241,8
$this->erreur("authentication failed", 401);
}
// infos utilisateur
$infos = $objAuth->getIdentiteParCourriel($login);
$infos = $this->utilisateur->getIdentiteParCourriel($login);
//var_dump($infos); exit;
// getIdentiteParCourriel retourne toujours le courriel comme clef de tableau en lowercase
$login = strtolower($login);
if (count($infos) == 0 || empty($infos[$login])) {
231,13 → 251,14
// si la redirection n'a pas eu lieu
$this->erreur("could not get user info");
}
// nom Wiki
$infos[$login]['nomWiki'] = $objAuth->formaterNomWiki($infos[$login], "UnknownWikiName");
$infos = $infos[$login];
// date de dernière modification du profil
$dateDerniereModif = $objAuth->getDateDerniereModifProfil($infos[$login]['id'], true);
$infos[$login]['dateDerniereModif'] = $dateDerniereModif;
$dateDerniereModif = $this->utilisateur->getDateDerniereModifProfil($infos['id'], true);
$infos['dateDerniereModif'] = $dateDerniereModif;
// infos partenaire
$infos = array_merge($infos, $infosPartenaire);
// création du jeton
$jwt = $this->creerJeton($login, $infos[$login]);
$jwt = $this->creerJeton($login, $infos);
// création du cookie
$this->creerCookie($jwt);
// redirection si demandée - se charge de sortir du script en cas de succès
248,7 → 269,7
"token" => $jwt,
"duration" => intval($this->dureeJeton),
"token_id" => $this->nomCookie,
"last_modif" => $infos[$login]['dateDerniereModif']
"last_modif" => $infos['dateDerniereModif']
));
}
 
/trunk/jrest/services/Utilisateur.php
84,42 → 84,6
}
 
/**
* Crée un nom Wiki (de la forme "JeanTalus") à partir des données de l'utilisateur;
* gère l'utilisation du pseudo mais pas la collision de noms Wiki @TODO s'en occuper
*
* @param array $infos des infos de profil utilisateur - on admet qu'elles contiennent "intitule"
* @return string un nom wiki correspondant à l' "intitulé" de l'utilisateur (prénom-nom ou pseudo)
* ou la valeur par défaut de $defaut si celui-ci est fourni et si le nom Wiki n'a pu être construit
*/
public function formaterNomWiki($infos, $defaut="ProblemeNomWiki") {
$nw = $this->convertirEnCamelCase($infos['intitule']);
// on sait jamais
if ($nw == "") {
$nw = $defaut;
}
 
return $nw;
}
protected function convertirEnCamelCase($str) {
// Suppression des accents
$str = $this->supprimerAccents($str);
// Suppression des caractères non alphanumériques
$str = preg_replace('/[^\da-z]/i', '', ucwords(strtolower($str)));
return $str;
}
 
protected function supprimerAccents($str, $charset='utf-8') {
$str = htmlentities($str, ENT_NOQUOTES, $charset);
 
$str = preg_replace('#&([A-za-z])(?:acute|cedil|caron|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str);
$str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str); // pour les ligatures e.g. '&oelig;'
$str = preg_replace('#&[^;]+;#', '', $str); // supprime les autres caractères
 
return $str;
}
 
/**
* Permet d'obtenir des infos pour un ou plusieurs ids utilisateurs indiqué(s) dans la ressource.
* RESSOURCE : /infos-par-ids/#id[,#id]*
* PARAMÈTRES : forceArrayOfArrays - si true, retourne un tableau associatif même s'il n'y a qu'un
155,6 → 119,18
return $infos;
}
 
// proxy pour AnnuaireModele::obtenirIdParMail() car le présent service
// est utilisé comme une lib => c'est MAL ! @TODO séparer lib et service !!
public function getIdParCourriel($courriel) {
return $this->getAnnuaire()->obtenirIdParMail($this->idAnnuaire, $courriel);
}
 
// proxy pour AnnuaireModele::inscrireUtilisateurCommeUnGrosPorc() car le présent service
// est utilisé comme une lib => c'est MAL ! @TODO séparer lib et service !!
public function inscrireUtilisateurCommeUnGrosPorc($donnees) {
return $this->getAnnuaire()->inscrireUtilisateurCommeUnGrosPorc($donnees);
}
 
/**
* Méthode rétrocompatible : appelle getInfosParIds et s'il n'y a qu'un résultat,
* ne retourne pas un tableau associatif mais un tableau simple
198,7 → 174,7
$utilisateur['pseudo'] = $this->obtenirPseudo($id);
$utilisateur['pseudoUtilise'] = $this->obtenirPseudoUtilise($id);
$utilisateur['intitule'] = $this->formaterIntitule($utilisateur);
$utilisateur['nomWiki'] = $this->formaterNomWiki($utilisateur);
$utilisateur['nomWiki'] = $this->formaterNomWiki($utilisateur['intitule']);
$courriel = strtolower($courriel);
$infos_utilisateurs[$courriel] = $utilisateur;
}
435,7 → 411,7
$this->messages[] = "Ce type de méthode '$methode_demande' n'est pas disponible pour la requete PUT.";
}
} else {
$this->messages[] = "Ce service n'est pas implémanté.";
$this->messages[] = "Ce service n'est pas implémenté.";
}
 
if (!is_null($infos)) {
/trunk/jrest/services/auth/AuthPartnerPlantnet.php
5,7 → 5,7
/**
* Permet de se connecter à l'annuaire de Tela Botanica à l'aide d'un compte Pl@ntNet / identify
*/
class AuthPartnerPlantnet extends AuthPartner {
class AuthPartnerPlantnet extends AuthPartner {
 
public function verifierAcces($login, $password) {
$url = "http://identify-test.plantnet-project.org/api/security/token/create?_username=$login&_password=$password";
13,38 → 13,51
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, array()); // nécessaire dans les versions modernes de libcurl sinon on se prend un 400 !
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($curl);
curl_close($curl);
 
//var_dump($res);
$res = json_decode($res, true);
//var_dump($res);
if (!empty($res['JWT'])) {
$jeton = $this->lib->decoderJetonManuellement($res['JWT']);
$this->jetonPartenaire = $res['JWT'];
$jetonDecode = $this->auth->decoderJetonManuellement($this->jetonPartenaire);
// stockage pour traitement dans les autres méthodes
$this->data = $jeton;
$this->data = $jetonDecode['details'];
//var_dump($jeton);
if (!empty($jeton['details']['email'])) {
//var_dump($jeton['details']['email']);
if ( !empty($this->data['email'])) {
//var_dump($this->data['email']);
return true;
}
}
 
return false;
}
 
public function getIdentiteParCourriel() {
protected function getNomPartenaire() {
return "plantnet";
}
 
echo "get identité par courriel<br/>";
protected function getCourriel() {
return $this->data['email'];
}
 
public function formaterNomWiki() {
protected function getId() {
// la clef primaire est le "username" dans Pl@ntNet, apparemment
return $this->data['username'];
}
 
echo "formater nom wiki<br/>";
protected function getValeursProfilPartenaire() {
return array(
'nom' => $this->data['lastname'],
'prenom' => $this->data['firstname'],
'email' => $this->data['email'],
'pseudo' => $this->data['username']
);
}
 
public function getDateDerniereModifProfil() {
 
echo "get date dernière modif profil<br/>";
}
/*public function getTimestampMajPartenaire() {
return 420000000000;
}*/
}
/trunk/jrest/services/auth/AuthPartner.php
3,17 → 3,117
abstract class AuthPartner {
 
/** Injection de dépendance du service Auth, pour utiliser les méthodes comme decoderJetonManuellement() */
protected $lib;
protected $auth;
 
/** Données retournées par le service d'authentification du partenaire */
/** Injection de dépendance de la lib Utilisateur depuis le service Auth */
protected $utilisateur;
 
/** Jeton brut retourné par le service d'authentification du partenaire */
protected $jetonPartenaire;
 
/** Données décodées depuis le jeton du partenaire */
protected $data;
 
/** Identifiant de l'utilisateur dans l'annuaire local, ou false s'il n'existe pas */
protected $idLocal;
 
public function __construct($authLib) {
$this->lib = $authLib;
$this->auth = $authLib;
$this->utilisateur = $authLib->getUtilisateur();
$this->idLocal = false;
}
 
/** Retourne true si l'utilisateur est authentifié par le partenaire */
public abstract function verifierAcces($login, $password);
public abstract function getIdentiteParCourriel();
public abstract function formaterNomWiki();
public abstract function getDateDerniereModifProfil();
 
/**
* Vérifie si l'annuaire contient déjà une entrée associée au
* courriel de l'utilisateur et l'ajoute ou la met à jour au besoin
*/
public function synchroniser() {
$courriel = $this->getCourriel();
// l'utilisateur existe-t-il déjà ?
$this->idLocal = $this->utilisateur->getIdParCourriel($courriel);
if ($this->idLocal !== false) {
if (! $this->profilEstAJour()) {
$this->mettreAJourProfil();
}
} else {
$this->inscrireUtilisateur();
}
}
 
/**
* Retourne true si le profil local est à jour par rapport à la date
* de dernière modification fournie par le partenaire; si une telle
* date n'existe pas, retourne $retourSiPasDeDate (true par défaut - on
* ne met pas à jour)
*/
protected function profilEstAJour($retourSiPasDeDate=true) {
$tsMajPartenaire = $this->getTimestampMajPartenaire();
//echo "Timestamp partenaire : "; var_dump($tsMajPartenaire); echo "<br/>";
if ($tsMajPartenaire != null) {
$dateMajLocale = $this->utilisateur->getDateDerniereModifProfil($this->idLocal);
$tsMajLocale = strtotime($dateMajLocale); // attention à ne pas changer le format de date !
//echo "Timestamp local : "; var_dump($tsMajLocale); echo "<br/>";
return ($tsMajLocale >= $tsMajPartenaire);
}
// Si le partenaire ne fournit pas de date, on retourne la valeur par défaut
return $retourSiPasDeDate;
}
 
/**
* Retourne le nom du partenaire en cours
*/
protected abstract function getNomPartenaire();
 
/**
* Retourne le courriel de l'utilisateur fourni par le partenaire
*/
protected abstract function getCourriel();
 
/**
* Retourne l'identifiant de l'utilisateur fourni par le partenaire
*/
protected abstract function getId();
 
/**
* Retourne le timestamp de dernière mise à jour du profil fournie par le
* partenaire; par défaut retourne null, ce qui laisse au mécanisme de
* synchronisation le soin de décider si on met à jour le profil ou non
*/
protected function getTimestampMajPartenaire() {
return null;
}
 
/**
* Retourne le jeton fourni par le partenaire
*/
public function getJetonPartenaire() {
return $this->jetonPartenaire;
}
 
/**
* Retourne un tableau de valeurs correpondant au profil de l'utilisateur,
* fourni par le partenaire, et contenant au minimum :
* - nom
* - prenom
* - pseudo
* - email
* Pour les autres champs possibles, voir AnnuaireModele::inscrireUtilisateurCommeUnGrosPorc()
*/
protected abstract function getValeursProfilPartenaire();
 
protected function inscrireUtilisateur() {
$valeursProfil = $this->getValeursProfilPartenaire();
$valeursProfil['partenaire'] = $this->getNomPartenaire();
$valeursProfil['id_partenaire'] = $this->getId();
// gruik gruik
$this->utilisateur->inscrireUtilisateurCommeUnGrosPorc($valeursProfil);
}
 
protected function mettreAJourProfil() {
throw new Exception("La mise à jour du profil n'est pas encore prise en charge");
$valeursProfil = $this->getValeursProfilPartenaire();
}
}
/trunk/modeles/AnnuaireModele.php
1277,4 → 1277,63
}
return false;
}
 
/**
* Puisqu'il n'y a pas la moindre méthode métier un peu propre pour inscrire un utilisateur, on
* va devoir tout faire à la main comme un verrat grassouilet.
* @WARNING c'est TRES TRES MAL de faire ça, ça casse la généricité, le multi-annuaire et tous les
* trucs mégachiants qui... euh... servent à rien en pratique :-/ mais bon c'est mal
*/
public function inscrireUtilisateurCommeUnGrosPorc($donnees) {
//echo "GRUIIIIK !!! ";
$donneesDefaut = array('nom' => '', 'prenom' => '', 'fonction' => '', 'titre' => '',
'password' => '', 'email' => '', 'url' => '', 'addr1' => '', 'addr2' => '', 'code_postal' => '',
'ville' => '', 'etat' => '', 'pays' => '', 'departement' => ''
);
$donnees = array_merge($donneesDefaut, $donnees);
// 1) table principale de l'annuaire
$req = "INSERT INTO annuaire_tela VALUES(DEFAULT, '"
. $donnees['nom'] . "', '"
. $donnees['prenom'] . "', '"
. $donnees['fonction'] . "', '"
. $donnees['titre'] . "', '"
. $donnees['password'] . "', '"
. $donnees['email'] . "', '"
. $donnees['url'] . "', '"
. $donnees['addr1'] . "', '"
. $donnees['addr2'] . "', '"
. $donnees['code_postal'] . "', '"
. $donnees['ville'] . "', '"
. $donnees['etat'] . "', '"
. $donnees['pays'] . "', '"
. $donnees['departement'] . "', '', NULL, '', '', 0, 1, CURRENT_TIMESTAMP, NULL, 0, 0);";
 
//echo $req; $res = true;
$res = $this->requete($req);
if ($res) {
// 2) récupération de l'ID à la wanagain
$id = $this->obtenirIdParMail(1, $donnees['email']);
//echo "ID: "; var_dump($id);
if ($id) {
// 3) métadonnées : pseudo et infos partenaire
// @WARNING les ids des colonnes peuvent différer d'une base à l'autre, méga cracra !
$req2 = "INSERT INTO annu_meta_valeurs VALUES"
. "(DEFAULT, 136, $id, 1)," // pseudo utilisé
. "(DEFAULT, 99, $id, '" . $donnees['pseudo'] . "')," // pseudo
. "(DEFAULT, 144, $id, '" . $donnees['partenaire'] . "')," // partenaire
. "(DEFAULT, 145, $id, '" . $donnees['id_partenaire'] . "')" // id_partenaire
;
//echo $req2;
$res2 = $this->requete($req2);
 
// 4) date de dernière modification
$req3 = "INSERT INTO annu_triples VALUES (DEFAULT, 1, $id, 'modification', CURRENT_TIMESTAMP)";
$res3 = $this->requete($req3);
 
// pas grave si la ddm a raté
return ($res2 != false);
}
}
return false;
}
}
/trunk/doc/bdd/.~lock.annuaire_vocabulaire.ods#
File deleted
\ No newline at end of file