Chapitre 4. Hoa_Acl

Quand on souhaite construire une application multi-utilisateurs, il est très courant d'avoir différents groupes d'utilisateurs et que chaque groupe ait des droits ou des permissions différentes.

Trivialement, on peut dire que les ACL sont un système qui supprime toutes notions d'arborescence dans la distribution des droits pour des personnes ou des ressources.

On va essayer de donner un exemple à travers ce chapitre. Chaque section est donc liée à la précédente et elles indiquent les étapes à suivre.

ACL, présentation des protagonistes

Un rapide rappel sur les ACL

Les ACL se basent sur le système de droit classique que l'on retrouve dans les systèmes Unix. Les ACL ne remplacent pas le système existant mais se fixe par-dessus pour rester compatible avec la norme POSIX.

Les ACL permettent une gestion plus fine des droits utilisateurs.

Les acteurs dans un jeu d'ACL

Pour définir des droits, on rencontre différents acteurs.

Le premier de tous et le plus concerné est l'utilisateur (représenté par la classe Hoa_Acl_User).

Un utilisateur fait partie d'un groupe d'utilisateur (représenté par la classe Hoa_Acl_Group). Un groupe comporte des droits qu'il peut hériter d'un ou plusieurs autres groupes ; on a alors un héritage multiple.

Les droits — ou permissions — (représentés par la classe Hoa_Acl_Permission) représentent une action qu'un groupe peut effectuer. Du fait d'un utilisateur peut être dans plusieurs groupes à la fois, il aura par conséquent la permission d'effectuer toutes les actions dont ses groupes bénéficient.

Et enfin, on trouve les ressources (représentées par la classe Hoa_Acl_Resource). Les ressources peuvent être un document, une image, une donnée ou n'importe quoi d'autre. Une ressource appartient à un ou plusieurs utilisateurs (dans le cas d'une ressource partagée).

Obtenir une instance de Hoa_Acl

Tout se passe autour de la classe Hoa_Acl. On enregistre successivement les groupes, les permissions, les utilisateurs etc. auprès de notre objet Hoa_Acl.

Pour obtenir une instance de cette classe, on est obligé de passer à travers la méthode statique getInstance qui met en place un Singleton. Ce qui fait que les registres de groupe et consorts persistent lors de l'exécution du script.

On aurait alors :

<?php
 
set_include_path( ... );
 
require_once 'Framework.php';
import('Acl.~');
 
/**
 * On récupère l'instance de notre ACL.
 */
$acl = Hoa_Acl::getInstance();

On notera pour la suite que le paquetage règle ses dépendances seul, c'est à dire que l'on n'aura pas à importer les classes Hoa_Acl_Group, Hoa_Acl_Permission etc., sauf cas particulier que l'on précisera.

Groupe et héritage multiple

Dans la méthodologie de construction d'ACL selon Hoa, on commence par décrire les groupes d'utilisateurs.

Un groupe est représenté par deux entités : un identifiant, qui doit être unique, et un label. Le label peut être n'importe quoi : aussi bien une chaîne de caractère pour donner un descriptif du groupe ou un objet qui contiendrait différentes informations provenant d'une base de données. Le label n'est pas typé, on peut donc y placer ce que l'on veut.

Déclaration d'un groupe

On va déclarer cinq groupes : le groupe administrateur, staff, publicitaire, éditeur et éditeur spécial. Chacun d'eux aura en label son nom écrit clairement mais on pourrait très bien y mettre un objet qui contiendrait plus d'informations, et qui décrirait le profil du groupe.

On aurait alors :

/**
 * On récupère notre instance principale.
 */
$acl        = Hoa_Acl::getInstance();
 
/**
 * On déclare nos groupes.
 * En premier : l'identifiant, et en
 * second : le label.
 */
$admin      = new Hoa_Acl_Group('admin', 'Administrateur');
$staff      = new Hoa_Acl_Group('staff', 'Staff');
$adman      = new Hoa_Acl_Group('adman', 'Publicitaire');
$editor     = new Hoa_Acl_Group('editor', 'Éditeur');
$editorSpec = new Hoa_Acl_Group('editorSpec', 'Éditeur spécial');

Pour vérifier les valeurs, on a accès à deux méthodes : getId qui nous retourne l'identifiant de notre groupe, et getLabel qui nous retourne le label de notre groupe. Voyons plutôt :

/**
 * On souhaite retrouver l'identifiant.
 */
var_dump($editor->getId());
 
/**
 * Affichera :
 *     string(6) "editor"
 */
 
/**
 * On souhaite retrouver le label.
 */
var_dump($editor->getLabel());
 
/**
 * Affichera :
 *     string(7) "Éditeur"
 */

Mise en place de l'héritage des groupes

Maintenant que nos groupes sont prêts, il faut les déclarer dans le registre des ACL. Pour cela, on passe à travers la méthode addGroup qui prend en premier argument notre objet de groupe, et le second argument décrit les parents desquels il va hériter des droits. On peut très bien donner l'identifiant du groupe ou l'instance elle-même. On peut également donner un tableau si on a plusieurs parents.

Dans notre cas, on va dire que l'administrateur est seul, il n'a ni parent, ni enfant. Le staff a trois enfants : éditeur spécial, publicitaire et éditeur. Et enfin, chose particulière, publicitaire a pour enfant éditeur spécial. Éditeur spécial a donc deux parents : staff et publicitaire.

On veut :

On déclarerait alors :

/**
 * On rappelle que la variable $acl
 * contient notre instance principale.
 * Nos groupes sont également déclarés.
 */
 
/**
 * On ajoute le groupe administrateur.
 */
$acl->addGroup($admin);
 
/**
 * On ajoute le groupe staff.
 */
$acl->addGroup($staff);
 
/**
 * On ajoute le groupe éditeur, qui hérite
 * de staff.
 */
$acl->addGroup($editor, $staff);
 
/**
 * On ajoute le groupe publicitaire, qui hérite
 * également de staff. Ici on donne l'identifiant
 * du groupe, ce qui est équivalent à donner
 * son instance.
 */
$acl->addGroup($adman, 'staff');
 
/**
 * On ajoute le groupe éditeur spécial, qui
 * hérite de staff et publicitaire.
 */
$acl->addGroup($editorSpec, array('staff', 'adman'));

Le système est optimisé et se base sur Hoa_Graph (voir Chapitre 19, Hoa_Graph). On précise que l'on ne peut construire de graphe comportant de boucle avec les ACL — et c'est normal.

Récupérer un groupe

La classe Hoa_Acl nous permet de retrouver un groupe à partir de son identifiant, et ainsi, on pourra le questionner (par exemple, retrouver son label).

Pour cela, on s'aide de la méthode getGroup qui prend en seul argument l'identifiant du groupe et retourne un objet Hoa_Acl_Group, une exception Hoa_Acl_Exception est levée sinon :

/**
 * On affiche le label du groupe éditeur.
 */
var_dump(
    $acl->getGroup('editor')->getLabel()
);
 
/**
 * Affichera :
 *     string(7) "Éditeur"
 */

On ne peut pas récupérer l'ensemble des groupes, cette action est interdite si on est extérieur à la famille de classe Hoa_Acl. En effet, son accès est protégé.

Vérifier l'existence d'un groupe

On peut vérifier qu'un groupe ait déjà été enregistré auprès de l'ACL.

Pour cela, on s'aide de la méthode groupExists, qui prend un seul paramètre : l'identifiant ou l'instance d'un groupe.

On aurait alors :

/**
 * On vérifie qu'un groupe existe.
 */
var_dump(
    $acl->groupExists('staff')
);
 
/**
 * Affichera :
 *     bool(true)
 */

Supprimer un groupe

On peut également supprimer un groupe.

Propagation de la suppression

On a vu que les groupes étaient liés entre eux à travers des liens d'héritage. Un groupe peut alors avoir des enfants.

Quand on veut supprimer un groupe, deux cas s'offrent à nous. Soit le groupe n'a pas d'enfant (i.e. aucun groupe n'hérite de ce premier) et cela ne pose aucun problème, soit le groupe a des enfants et on a encore un choix : soit on a une exception, soit on propage la suppression. Propager la suppression signifie que chaque enfant va être supprimé, ainsi que chacun des enfants des enfants etc.

On distingue donc deux modes de suppression :

  • DELETE_CASCADE : on supprime chacun des enfants et leurs enfants etc. ;
  • DELETE_RESTRICT : on ne supprime le groupe si et seulement si il n'a aucun enfant, sinon une exception Hoa_Acl_Exception sera levée. C'est la valeur par défaut.

Attention, utiliser la suppression en cascade peut supprimer une très grande partie du graphe des groupes (dépendant de sa construction bien évidemment). Dans notre exemple, si on supprime le groupe staff, tous les groupes seront supprimés à part admin, car tous héritent de staff.

La méthode deleteGroup a deux paramètres : le premier est l'identifiant ou l'instance du groupe, et le second est le mode de suppression.

On aurait alors :

/**
 * On supprime un groupe s'il n'a
 * pas d'enfant, sinon, on affiche l'erreur.
 */
try {
 
    $acl->deleteGroup('staff', Hoa_Acl::DELETE_RESTRICT);
}
catch ( Hoa_Acl_Exception $e ) {
 
    $e->raiseError();
}

Si on supprime un groupe et qu'un utilisateur en faisait partie, il en sera expulsé. Ainsi, les utilisateurs ne feront pas partie de groupe inexistant.

Permissions

On a déclaré les groupes et mis en place leur héritage. On doit maintenant déclarer les permissions.

À l'instar des groupes, les permissions ont un identifiant et un label qui peut être un objet ou autre. On trouve également les mêmes méthodes getId et getLabel.

Création des permissions

On va prendre l'exemple de trois permissions : lecture, écriture et exécution. On peut créer autant de droit que l'on veut, on n'est pas limité.

On aurait alors :

/**
 * On crée les permissions.
 * Le label de chaque permission est simplement
 * une courte description (le nom complet si on veut).
 */
$read    = new Hoa_Acl_Permission('read', 'Lecture');
$write   = new Hoa_Acl_Permission('write', 'Écriture');
$execute = new Hoa_Acl_Permission('execute', 'Exécution');

Assignation des droits aux groupes

Les droits sont maintenant déclarés. Il ne nous reste qu'à les assigner aux différents groupes précédemment enregistrés.

On a deux méthodes à notre disposition : allow et deny qui prennent en premier argument l'identifiant du groupe. Le second argument diffère selon la méthode. Pour la méthode allow, le second argument est une instance ou un tableau d'instance, qui va être le (ou les) droit(s) à ajouter au groupe (par défaut, il n'a aucun droit). Pour la méthode deny, on peut aussi bien avoir des instances de permissions, que leurs identifiants (ce qui n'est pas possible pour la méthode allow).

On veut que l'aministrateur ait tous les droits, tout comme le staff. Donc tous les enfants de staff auront tous les droits (par héritage). Alors, on enlève le droit d'exécution au publicitaire. Enfin, pour voir le fonctionnement de l'héritage dans une autre situation, on supprime le droit de lecture au staff, tous ses enfants ne devraient donc plus l'avoir.

On aurait alors :

/**
 * On assigne les droits.
 */
 
/**
 * L'administrateur a tous les droits.
 */
$acl->allow('admin', array($read, $write, $execute));
 
/**
 * Pareil pour le staff.
 */
$acl->allow('staff', array($read, $write, $execute));
 
/**
 * Le publicitaire n'a pas le droit d'exécution.
 * On lui enlève donc via l'instance.
 */
$acl->deny('adman', $execute);
 
/**
 * Maintenant, on enlève le droit de lecture au staff,
 * et donc à tous ses enfants.
 * On enlève via l'identifiant, est équivalent à
 * utiliser une instance.
 */
$acl->deny('staff', 'read');

Avant de tester les droits, il faut déclarer des utilisateurs.

Utilisateurs

Maintenant que les groupes sont déclarés, et que chacun a reçu des droits, il faut déclarer un utilisateur.

Un utilisateur peut appartenir à un ou plusieurs groupes.

Créer un utilisateur

On va créer deux utilisateurs : Hywan[8] et Mini-Hywan. Hywan fera parti du groupe staff, et Mini-Hywan fera parti du groupe publicitaire et éditeur.

La création d'un utilisateur se fait via la classe Hoa_Acl_User et prend deux arguments : l'identifiant et le label ; on retrouve donc les deux méthodes getId et getLabel.

On trouve également la méthode addGroup qui permet d'enregistrer l'utilisateur auprès de un ou plusieurs groupes. Pour cela, on passe en seul paramètre une instance, un identifiant, ou un tableau d'instance ou d'identifiant de groupe.

On aurait alors :

/**
 * On crée les utilisateurs.
 */
 
/**
 * On crée l'utilisateur Hywan.
 */
$hywan     = new Hoa_Acl_User('hywan', 'Hywan');
 
/**
 * Hywan fait partie du groupe staff.
 */
$hywan->addGroup($staff);
 
/**
 * On crée l'utilisateur Mini-Hywan.
 */
$minihywan = new Hoa_Acl_User('minihywan', 'Mini-Hywan');
 
/**
 * Mini-Hywan fait partie du groupe publicitaire et éditeur.
 */
$minihywan->addGroup(array('adman', 'editor'));

Maintenant que les utilisateurs sont déclarés, il faut les enregistrer auprès de l'ACL :

/**
 * On rappelle que la variable $acl
 * contient notre instance principale.
 */
 
/**
 * On ajoute l'utilisateur Hywan.
 */
$acl->addUser($hywan);
 
/**
 * On ajoute l'utilisateur Mini-Hywan.
 */
$acl->addUser($minihywan);

Profiler un utilisateur

On admet que le label a tout de même plus de sens dans le cas d'un utilisateur. On propose un exemple.

Chaque membre a des données qui proviennent d'une base de données. Elle comprend plusieurs informations que l'on peut rassembler dans un objet de données par exemple :

/**
 * On donne un exemple d'objet de données
 * pratique pour être un label d'un utilisateur.
 * Pour bien faire, il faudrait mettre des setters,
 * et getters partout. On simplifie pour la clarté
 * du code.
 */
class Utilisateur {
 
    /**
     * Prénom de l'utilisateur.
     */
    public $firstname  = 'Ivan';
 
    /**
     * Nom de l'utilisateur.
     */
    public $surname    = 'Enderlin';
 
    /**
     * Moyen de locomotion préféré.
     */
    public $locomotion = 'Sandales';
 
    /**
     * Est un geek ou pas.
     */
    public $isGeek     = 'Il semblerait';
}
 
/**
 * On crée maintenant l'utilisateur.
 */
$hywan = new Hoa_Acl_User('hywan', new Utilisateur());
 
/**
 * On l'affecte à un groupe.
 */
$hywan->addGroup($staff);
 
/**
 * On ajoute l'utilisateur.
 */
$acl->addUser($hywan);

Maintenant, on peut retrouver les informations sur l'utilisateur via son label et la méthode getUser de Hoa_Acl qui permet de retrouver un utilsateur enregistré à l'aide de son identifiant.

On aurait alors :

/**
 * On affiche le moyen de locomotion préféré
 * de l'utilisateur Hywan.
 */
var_dump(
    $acl->getUser('hywan')->getLabel()->locomotion
);
 
/**
 * Affichera :
 *     string(8) "Sandales"
 */

Les ACL peuvent donc servir de profil pour un utilisateur.

Vérifier l'existence d'un utilisateur

On peut vérifier qu'un utilisateur ait déjà été enregistré auprès de l'ACL.

Pour cela, on utilise la méthode userExists sur la classe Hoa_Acl. Elle prend un seul argument : l'identifiant ou l'instance de l'utilisateur.

On aurait alors :

/**
 * On teste l'existence d'un utilisateur.
 */
var_dump(
    $acl->userExits('rasmus')
);
 
/**
 * Affichera :
 *     bool(false)
 */

Supprimer un utilisateur

Pour « bannir » un utilisateur, on utilise une méthode complémentaire à addUser, c'est à dire deleteUser.

Cette méthode prend un seul paramètre qui peut être l'identifiant ou l'instance de l'utilisateur. Elle ne retourne rien.

On aurait alors :

/**
 * On supprime un utilisateur.
 * On teste avant et après son existence,
 * pour voir la différence.
 */
var_dump($acl->userExists('hywan'));
 
$acl->deleteUser('hywan');
 
var_dump($acl->userExists('hywan'));
 
/**
 * Affichera :
 *     bool(true)
 *     bool(false)
 */

Liste des groupes d'un utilisateur

La classe Hoa_Acl nous permet de récupérer un utilisateur via sa méthode getUser. On peut donc connaître son label, mais également la liste des groupes auxquels il est adhérent. Pour cela, on utilise la méthode getGroups :

/**
 * On affiche la liste des identifiants
 * des groupes de l'utilisateur Mini-Hywan.
 */
var_dump(
    $acl->getUser('minihywan')->getGroups())
);
 
/**
 * Affichera :
 *     array(2) {
 *       [0]=>
 *       string(9) "adman"
 *       [1]=>
 *       string(6) "editor"
 *     }
 */

Ajouter un groupe à un utilisateur après enregistrement

Un utilisateur se manipule assez bien. Même après enregistrement, on est toujours capable de lui ajouter des groupes (ou supprimer, on l'aborde juste après).

Pour cela, on s'aide tout d'abord de la méthode getUser de la classe Hoa_Acl qui prend en seul argument l'identifiant de l'utilisateur. Ensuite — une fois l'utilisateur récupéré — on peut utiliser la méthode addGroup (de la classe Hoa_Acl_User donc), qui prend en seul argument un identifiant, une tableau d'identifiant, une instance ou un tableau d'instance du ou des groupes à ajouter. On s'y prendrait de cette façon :

/**
 * On retrouve un utilisateur pour le modifier.
 * On lui ajoute un groupe, i.e. il appartient
 * à un nouveau groupe.
 */
$acl->getUser('hywan')->addGroup('editorSpec');

La méthode addGroup retourne la liste des groupes auxquels l'utilisateur appartient, soit un tableau.

Supprimer un groupe à un utilisateur après enregistrement

De la même manière que pour ajouter, on peut supprimer. Cette fois, on s'appuie sur la méthode deleteGroup qui a le même paramètre.

On aurait :

/**
 * On retrouve un utilisateur pour le modifier.
 * On lui supprime un groupe, i.e. il n'appartient
 * plus à un groupe.
 */
$acl->getUser('hywan')->deleteGroup('editorSpec');

La méthode deleteGroup retourne également la liste des groupes auxquels l'utilisateur appartient.

Vérifier l'appartenance d'un utilisateur à un groupe

On propose une façon de vérifier si un utilisateur appartient à un groupe. Attention, on ne vérifie pas ses droits mais seulement son appartenance à un groupe en particulier.

Pour cela, on utilise la méthode groupExists qui prend en seul argument l'identifiant ou l'instance du groupe à tester.

On aurait :

/**
 * On teste si un utilisateur appartient à
 * un groupe en particulier.
 */
var_dump(
    $hywan->groupExists('staff')
);
 
/**
 * Ou après l'enregistrement auprès de
 * l'ACL.
 */
var_dump(
    $acl->getUser('hywan')->groupExists('staff')
);
 
/**
 * Affichera :
 *     bool(true)
 */

Vérifier les droits

On passe maintenant à la partie la plus intéressante. On a déjà déclaré tous nos groupes, permissions et utilisateurs. On peut donc commencer nos tests.

Pour savoir si un utilisateur a le droit d'effectuer une tâche, on s'aide de la méthode isAllowed de la classe Hoa_Acl. Cette méthode prend en premier argument, l'identifiant ou l'instance d'un utilisateur. En second argument, l'identifiant ou l'instance d'une permission. Il reste encore deux autres arguments que l'on détaillera plus tard ; ils concernent les ressources et les assertions.

On aurait alors :

/**
 * L'utilisateur Hywan fait partie du groupe staff.
 * Ce groupe a les droits d'écriture et d'exécution,
 * et n'a pas le droit de lecture (voir le dernier
 * appel de la méthode deny).
 */
 
/**
 * On regarde s'il a les droits d'exécution.
 */
var_dump(
    $acl->isAllowed($hywan, 'execute')
);
 
/**
 * Affichera :
 *     bool(true)
 */
 
/**
 * On regarde s'il a les droits de lecture.
 */
var_dump(
    $acl->isAllowed('hywan', 'read')
);
 
/**
 * Affichera :
 *     bool(false)
 */
 
/**
 * L'utilisateur Mini-Hywan fait partie des groupes
 * publicitaire et éditeur. Il a donc les droits
 * d'écriture et d'exécution de par son appartenance
 * au groupe éditeur qui hérite de staff. Même si son
 * appartenance au groupe publicitaire l'empêche
 * d'avoir les droits d'exécution, éditeur lui donne
 * ces droits.
 */
 
/**
 * On regarde s'il a les droits d'exécution.
 */
var_dump(
    $acl->isAllowed('minihywan', 'execute')
);
 
/**
 * Affichera :
 *     bool(true)
 */
 
/**
 * On regarde s'il a les droits d'écriture.
 */
var_dump(
    $acl->isAllowed('minihywan', $write)
);
 
/**
 * Affichera :
 *     bool(true)
 */

Notion de ressource

Une ressource désigne tout type d'entité de données. Cela peut être un document, une image, ou n'importe quoi d'autre.

Une ressource appartient à un ou plusieurs utilisateurs, ce qui permet d'avoir des ressources partagées.

Créer une ressource

On va prendre l'exemple d'une ressource qui représente un tutorial, de titre « Tutorial sur les ACL ». Cette ressource appartient à l'utilisateur Hywan.

On va donc créer une ressource à l'aide de la classe Hoa_Acl_Resource. Comme ses sœurs, elle prend deux paramètres : l'identifiant et le label. On retrouve donc les méthodes getId et getLabel.

On a également la méthode addUser qui permet d'ajouter un utilisateur auprès d'une ressource. Le seul argument prend l'identifiant ou l'instance d'un utilisateur, on peut également avoir un tableau d'identifiant ou d'instance si on veut ajouter plusieurs utilisateurs.

Enfin, on enregistre la ressource auprès de l'ACL à l'aide de la méthode addResource qui prend en seul argument l'instance d'une ressource.

On aurait alors :

/**
 * On crée une ressource.
 */
$resource = new Hoa_Acl_Resource('tuto', 'Tutorial sur les ACL.');
 
/**
 * On ajoute l'utilisateur Hywan.
 */
$resource->addUser('hywan');
 
/**
 * On enregistre la ressource.
 */
$acl->addResource($resource);

Vérifier les droits avec une ressource

Pour mémoire, on rappelle que le troisième argument de la méthode isAllowed de la classe Hoa_Acl permet de tester les droits par rapport à une ressource. Si on ne veut pas tester de ressource, il suffit de passer null.

En fait, isAllowed commence par vérifier que l'utilisateur appartient bien à la ressource. S'il y appartient, alors on effectue le reste des vérifications, sinon on retourne false directement.

On aurait alors :

/**
 * On regarde si l'utilisateur Hywan a les droits
 * d'exécution auprès de la ressource tuto.
 */
var_dump(
    $acl->isAllowed('hywan', 'execute', 'tuto')
);
 
/**
 * Affichera :
 *     bool(true)
 */
 
/**
 * On regarde si l'utilisateur Mini-Hywan a les droits
 * d'exécution auprès de la ressource tuto.
 */
var_dump(
    $acl->isAllowed('minihywan', 'execute', 'tuto')
);
 
/**
 * Affichera :
 *     bool(false)
 */

Vérifier l'existence d'une ressource

On peut vérifier qu'une ressource a bien été enregistrée auprès de l'ACL.

La méthode resourceExists se propose de répondre à ce besoin. Elle prend un seul et unique paramètre : l'identifiant ou l'instance de la ressource.

On aurait alors :

/**
 * On vérifie l'existence d'une ressource.
 */
var_dump(
    $acl->resourceExists('tuto')
);
 
/**
 * Affichera :
 *     bool(true)
 */

Supprimer une ressource

La méthode deleteResource est utile pour supprimer une ressource.

Cette méthode ne prend qu'un seul paramètre qui est l'identifiant ou l'instance de la ressource.

Voyons plutôt :

/**
 * On supprime une ressource.
 */
$acl->deleteResource('tuto');

Récupérer une ressource enregistrée

On peut récupérer une ressource enregistrée auprès de l'ACL à travers la méthode getResource de la classe Hoa_Acl. Elle prend en seul paramètre l'identifiant de la ressource à récupérer.

On aurait :

/**
 * On affiche le label d'une ressource
 * déjà enregistrée.
 */
var_dump(
    $acl->getResource('tuto')->getLabel()
);
 
/**
 * Affichera :
 *     string(22) "Tutorial sur les ACL."
 */

Supprimer un utilisateur d'une ressource

On peut aussi supprimer un ou plusieurs utilisateurs en utilisant la méthode deleteUser de la classe Hoa_Acl_Resource qui prend un paramètre. Ce paramètre peut être l'identifiant ou l'instance d'un utilisateur, ou un tableau d'identifiant ou d'instance.

On aurait alors :

/**
 * On supprime l'utilisateur Hywan,
 * de la ressource tuto.
 */
$resource->deleteUser('hywan');
 
/**
 * Ou à partir d'une ressource déjà
 * enregistrée auprès de l'ACL.
 */
$acl->getResource('tuto')->deleteUser('hywan');

Vérifier l'appartenance d'un utilisateur auprès d'une ressource

On peut vérifier qu'un utilisateur est bien enregistré auprès d'une ressource avec la méthode userExists de la classe Hoa_Acl_Resource. Cette méthode prend un seul argument : l'identifiant ou l'instance d'un utilisateur.

On aurait alors :

/**
 * On vérifie que l'utilisateur Hywan
 * est enregistré auprès de la ressource tuto.
 */
var_dump(
    $acl->getResource('tuto')->userExists('hywan')
);
 
/**
 * Affichera :
 *     bool(true)
 */

Obtenir la liste des utilisateurs d'une ressource

On peut aussi obtenir la liste de tous les utilisateurs enregistrés auprès d'une ressource.

Pour cela, on s'aide de la méthode getUsers de la classe Hoa_Acl_Resource. Elle ne prend aucun argument.

On aurait :

/**
 * On récupère la liste des utilisateurs
 * déclarés auprès de la ressource tuto.
 */
var_dump(
    $acl->getResource('tuto')->getUsers()
);
 
/**
 * Affichera :
 *     array(1) {
 *       [0]=>
 *       string(5) "hywan"
 *     }
 */

Affiner les droits avec les assertions

Les assertions permettent une gestion plus fine des droits, en ce sens où elles ajoutent une condition supplémentaire à valider. Cela peut être une vérification d'IP ou une vérification d'heure (telle partie est accessible de telle à telle heure) etc.

Les assertions sont donc des objets qui doivent implémenter l'interface Hoa_Acl_Assert_Interface qui force l'implémentation de la méthode assert sans aucun argument. Cette méthode doit retourner un booléen. Une comparaison stricte sera faite, i.e. une comparaison de valeur et de type.

Un exemple très trivial :

/**
 * On importe notre interface.
 */
import('Acl.Assert.Interface');
 
/**
 * Une assertion vraiment simple, qui est
 * un peu caractérielle.
 */
class MonAssertion implements Hoa_Acl_Assert_Interface {
 
    public function assert ( ) {
 
        return false;
    }
}

On peut ajouter les assertions dans la méthode isAllowed en quatrième et dernier argument. On doit passer l'instance de l'assertion qui est typée selon l'interface.

On aurait alors :

/**
 * On regarde si l'utilisateur Hywan a les droits
 * d'exécution auprès de la ressource tuto,
 * en prenant compte de l'assertion.
 */
var_dump(
    $acl->isAllowed('hywan', 'execute', 'tuto', new MonAssertion())
);
 
/**
 * Affichera :
 *     bool(false)
 */

Persistance des ACL

Si on veut stocker les ACL quelque part et les ressortir plus tard, on peut les rendre persistantes à l'aide de la sérialisation.

Pour cela, on utilise tout simplement la fonction serialize de PHP. Pour désérialiser, on utilise sa fonction réciproque : unserialize.

On aurait alors :

/**
 * On sérialise l'ACL.
 */
$serialize = serialize($acl);
 
/**
 * On désérialise.
 */
$acl = unserialize($serialize);


[8] Hywan est le pseudo de Ivan Enderlin, c'est original.