182

Gérer une communauté d'utilisateurs

Créez site15 en copiant site14.

  1. /cms
    1. ...
    2. site14
    3. site15

Dans ce chapitre, nous allons gérer une communauté d'utilisateurs dans une BD et leur attribuer des rôles.

Pour tester le résultat en ligne, entrez http://www.frasq.org/cms/site15 dans la barre d'adresse de votre navigateur. Identifiez-vous en tant que foobar avec le mot de passe f00bar. Un bouton vert avec une coche apparaît dans le bandeau de la page d'accueil. Si vous cliquez dessus, le contenu de la page est transmis au validateur du W3C. Déconnectez-vous et identifiez-vous de nouveau mais en tant que barfoo avec le mot de passe barf00. Le lien sur le W3C n'est pas affiché.

Démarrez le processeur de commandes de MySQL et entrez dans la BD du site :

$ mysql -u root -p
mysql> use frasqdb2;

NOTE : Utilisez phpMyAdmin pour plus de confort.

Ajoutez la table user à la BD du site :

CREATE TABLE USER (
  user_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(40) NOT NULL,
  `password` VARCHAR(32) NOT NULL,
  mail VARCHAR(100) DEFAULT NULL,
  created datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `access` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  locale enum('fr','en') NOT NULL DEFAULT 'fr',
  active tinyint(1) NOT NULL DEFAULT '1',
  banned tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (user_id),
  UNIQUE KEY name (name),
  UNIQUE KEY mail (mail)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

Le numéro de l'utilisateur user_id est aussi la clé primaire . name et mail sont des clés uniques qui permettent d'identifier un utilisateur. password garde le mot de passe de l'utilisateur chiffré en MD5. created contient la date et l'heure de création du compte. access note la date et l'heure de la dernière connexion au compte. locale donne la langue préférée de l'utilisateur parmi celles gérées par le site. active indique si le compte est accessible. banned signale un utilisateur indésirable.

Créez un utilisateur foobar avec le mot de passe f00bar et un utilisateur barfoo avec le mot de passe barf00 :

INSERT INTO USER (name, password, mail, created)
VALUES ('foobar', MD5('f00bar'), 'foobar@localhost', NOW());
INSERT INTO USER (name, password, mail, created)
VALUES ('barfoo', MD5('barf00'), 'barfoo@localhost', NOW());

Remarquez que les mots de passe sont encodés en MD5. IMPORTANT : Ne conservez jamais les mots de passe en clair.

Ajoutez les tables role et user_role à la BD du site :

CREATE TABLE `role` (
  role_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(40) NOT NULL,
  PRIMARY KEY (role_id),
  UNIQUE KEY name (name)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

role n'est rien de plus qu'une liste de noms.

CREATE TABLE user_role (
  user_id INT(10) UNSIGNED NOT NULL DEFAULT '0',
  role_id INT(10) UNSIGNED NOT NULL DEFAULT '0',
  PRIMARY KEY (user_id,role_id),
  KEY `role` (role_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

user_role associe un numéro d'utilisateur avec un rôle. Un utilisateur peut avoir plusieurs rôles.

Définissez les rôles administrator, writer, reader et moderator :

INSERT INTO `role` (name) VALUES ('administrator');
INSERT INTO `role` (name) VALUES ('writer');
INSERT INTO `role` (name) VALUES ('reader');
INSERT INTO `role` (name) VALUES ('moderator');

Associez l'utilisateur foobar aux rôles administrator et writer :

INSERT INTO user_role (user_id, role_id) VALUES (1, 1);
INSERT INTO user_role (user_id, role_id) VALUES (1, 2);

Vérifiez que vous pouvez lister les noms des rôles d'un utilisateur :

mysql> SELECT u.name AS user_name, r.name AS role_name FROM user u
JOIN user_role ur ON ur.user_id=u.user_id
JOIN role r ON r.role_id=ur.role_id
WHERE ur.user_id=1;
+-----------+---------------+
| user_name | role_name     |
+-----------+---------------+
| foobar    | administrator |
| foobar    | writer        |
+-----------+---------------+
2 rows in set (0.00 sec)
mysql> quit

Éditez le fichier user.inc dans le dossier models et ajoutez les fonctions suivantes :

  1. function user_get($user_id) {
  2.     if (!is_numeric($user_id)) {
  3.         return false;
  4.     }
  5.  
  6.     $tabuser=db_prefix_table('user');
  7.  
  8.     $sql="SELECT name AS user_name, password AS user_password, mail AS user_mail, UNIX_TIMESTAMP(created) AS user_created, UNIX_TIMESTAMP(access) AS user_access, locale AS user_locale, active AS user_active, banned AS user_banned FROM $tabuser WHERE user_id=$user_id LIMIT 1";
  9.  
  10.     $r = db_query($sql);
  11.  
  12.     return $r ? $r[0] : false;
  13. }

user_get retourne un tableau avec les champs user_name, user_password, user_mail, user_created, user_access, user_locale, user_active et user_banned de l'utilisateur dont le numéro est $user_id ou false si $user_id n'est pas un numéro d'utilisateur valide.

  1. function user_get_role($user_id) {
  2.     if (!is_numeric($user_id)) {
  3.         return false;
  4.     }
  5.  
  6.     $tabrole=db_prefix_table('role');
  7.     $tabuserrole=db_prefix_table('user_role');
  8.  
  9.     $sql="SELECT r.name AS role_name FROM $tabuserrole ur JOIN $tabrole r ON r.role_id=ur.role_id WHERE ur.user_id=$user_id";
  10.  
  11.     $r = db_query($sql);
  12.  
  13.     if (!$r) {
  14.         return false;
  15.     }
  16.  
  17.     $role=array();
  18.  
  19.     foreach ($r as $v) {
  20.         $role[] = $v['role_name'];
  21.     }
  22.  
  23.     return $role;
  24. }

user_get_role retourne la liste des rôles de l'utilisateur $user_id ou false si $user_id n'est pas un numéro d'utilisateur valide.

  1. function user_find($login) {
  2.     $sqllogin=db_sql_arg($login, true);
  3.  
  4.     $tabuser=db_prefix_table('user');
  5.  
  6.     $sql="SELECT user_id FROM $tabuser WHERE name=$sqllogin OR mail=$sqllogin LIMIT 1";
  7.  
  8.     $r = db_query($sql);
  9.  
  10.     return $r ? $r[0]['user_id'] : false;
  11. }

user_find vérifie si un utilisateur dont le nom ou l'adresse d'email est $login est défini dans la BD. user_find retourne le numéro unique de l'utilisateur ou false en cas d'échec.

  1. function user_login($login, $password) {
  2.     $user_id = user_find($login);
  3.  
  4.     if (!$user_id) {
  5.         return false;
  6.     }
  7.  
  8.     $r = user_get($user_id);
  9.  
  10.     if (!$r) {
  11.         return false;
  12.     }
  13.  
  14.     extract($r);    /* user_name user_password user_mail user_created user_access user_locale user_active user_banned */
  15.  
  16.     if (!$user_active or $user_banned) {
  17.         return false;
  18.     }
  19.  
  20.     $password=md5($password);
  21.  
  22.     if ($password != $user_password) {
  23.         return false;
  24.     }
  25.  
  26.     $now=time();
  27.  
  28.     $user = array();
  29.     $user['id'] = $user_id;
  30.     $user['name'] = $user_name;
  31.     $user['mail'] = $user_mail;
  32.     $user['locale'] = $user_locale;
  33.     $user['created'] = (int)$user_created;
  34.     $user['access'] = $now;
  35.  
  36.     $r = user_get_role($user_id);
  37.  
  38.     $user['role'] = $r;
  39.  
  40.     $tabuser=db_prefix_table('user');
  41.  
  42.     $sql="UPDATE $tabuser SET access=FROM_UNIXTIME($now) WHERE user_id=$user_id LIMIT 1";
  43.  
  44.     db_update($sql);
  45.  
  46.     return $user;
  47. }

user_login obtient avec user_find le numéro de l'utilisateur dont le nom ou l'adresse d'email est $login puis les propriétés du compte avec user_get. Si $login n'est pas le nom ou l'adresse d'email d'un utilisateur ou si $password ne correspond pas au mot de passe ou si le compte est inactif ou bloqué, user_login retourne false. Si la connexion est acceptée, $login note la date et l'heure dans la BD avant de retourner un tableau avec les champs id, name, mail, locale, created et access extraits du tableau des propriétés renvoyé par user_get et le champ role contenant la liste des rôles renvoyée par user_get_role.

Remarquez que l'interface de la fonction user_login n'a pas changé. Vous n'avez donc pas besoin de modifier le formulaire de la page d'identification. Entrez http://localhost/cms/site15/fr/utilisateur dans la barre d'adresse de votre navigateur et vérifiez que tout fonctionne comme auparavant.

Ajoutez le fichier userhasrole.php dans le dossier library avec le contenu suivant  :

  1. /cms/site15
    1. library
      1. userhasrole.php
  1. function user_has_role($role) {
  2.     return isset($_SESSION['user']) and $_SESSION['user']['role'] and in_array($role, $_SESSION['user']['role']);
  3. }

user_has_role retourne true si l'utilisateur est connecté et si $role est un de ses rôles, ou false dans le cas contraire.

Modifiez la fonction banner qui fabrique le bloc du bandeau du site dans le fichier banner.php dans le dossier blocks :

  1. require_once 'userhasrole.php';

Charge la fonction user_has_role.

  1.     $menu=$contact=$login=$logout=$validate=false;
  2.     $languages=false;
  3.     $contact_page=$nobody_page=$validate_page=false;
  4.  
  5.     $is_identified = user_is_identified();
  6.     $is_writer = user_has_role('writer');

Initialise les variables $validate et $validate_page. Met $is_writer à true si l'utilisateur a le rôle writer, a false dans le cas contraire.

  1.                 case 'validate':
  2.                     if ($param) {
  3.                         if ($is_writer) {
  4.                             $validate_page=$param;
  5.                             $validate=true;
  6.                         }
  7.                     }
  8.                     break;

Si 'validate' est dans $components, si $param n'est pas false et si $is_writer est true, assigne la valeur associée au composant à $validate_page et met $validate à true.

  1.     if ($logout or $contact) {
  2.         $menu = view('bannermenu', $lang, compact('contact', 'contact_page', 'validate', 'validate_page', 'logout', 'nobody_page', 'login', 'user_page'));
  3.     }

Passe les paramètres $validate et $validate_page à la vue.

Modifiez l'action home dans le fichier home.php dans le dossier actions pour passer le lien sur la page d'accueil au bloc du bandeau :

  1.     $validate=url('home', $lang);
  2.  
  3.     $banner = build('banner', $lang, compact('languages', 'contact', 'account', 'validate'));

Assigne l'URL de la page d'accueil à $validate et passe le paramètre à banner.

Ajoutez le lien sur le validateur à la vue du menu du bandeau dans les fichiers views/fr/bannermenu.phtml pour la version française et views/en/bannermenu.phtml pour la version en anglais :

  1. <?php if (isset($validate) and $validate): ?>
  2. <li><a id="validate" href="http://validator.w3.org/check?uri=<?php echo $base_root . $validate_page; ?>" target="validator.w3.org" title="Valider"><span>Valider</span></a></li>
  3. <?php endif; ?>
  1. <?php if (isset($validate) and $validate): ?>
  2. <li><a id="validate" href="http://validator.w3.org/check?uri=<?php echo $base_root . $validate_page; ?>" target="validator.w3.org" title="Validate"><span>Valider</span></a></li>
  3. <?php endif; ?>

Modifiez la feuille de style pour afficher un bouton à la place du lien sur le W3C :

  1. #bannermenu #validate {width:24px;height:24px;float:left;margin-right:6px;background:transparent url(../buttons/check.png) no-repeat center center;}

Copiez l'icône dans le dossier buttons :

  1. /cms/site15
    1. buttons
      1. check.png

Entrez http://localhost/cms/site15 dans la barre d'adresse de votre navigateur. Identifiez-vous en tant que foobar avec le mot de passe f00bar. Vérifiez que le bouton de validation est bien affiché sur la page d'accueil. Désactivez le CSS pour juger de la qualité du document généré. Passez la souris sur le bouton pour contrôler l'URL. Si votre site est accessible sur le web, cliquez sur le bouton pour valider le contenu de la page. Identifiez-vous en tant que barfoo avec le mot de passe barf00. Vérifiez que le bouton de validation n'est pas affiché sur la page d'accueil.

Commentaires

Votre commentaire :
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip aide 2000

Entrez un maximum de 2000 caractères.
Améliorez la présentation de votre texte avec les balises de formatage suivantes :
[p]paragraphe[/p], [b]gras[/b], [i]italique[/i], [u]souligné[/u], [s]barré[/s], [quote]citation[/quote], [pre]tel quel[/pre], [br]à la ligne,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]commande[/code], [code=langage]code source en c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].