<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 15101 -->
<!-- Reviewed: no -->
<sect1 id="zend.acl.introduction">
    <title>Introduction</title>

    <para>
        <classname>Zend_Acl</classname> fournit une implémentation légère et flexible de
        listes de contrôle d'accès (ACL : Access Control List) pour la gestion de privilèges. En
        général, une application peut utiliser une telle fonctionnalité pour contrôler l'accès à
        certains objets par d'autres objets demandeurs.
    </para>

    <para>
        Dans le cadre de cette documentation,
        <itemizedlist>
            <listitem>
                <para>
                    une <emphasis role="strong">ressource</emphasis> est un objet dont l'accès
                    est contrôlé,
                </para>
            </listitem>
            <listitem>
                <para>
                    un <emphasis role="strong">rôle</emphasis> est un objet qui peut demander
                    l'accès à une ressource.
                </para>
            </listitem>
        </itemizedlist>Dit simplement, <emphasis role="strong"> les rôles demandent l'accès à des
        ressources</emphasis>. Par exemple, si une personne demande l'accès à une voiture, alors la
        personne est le rôle demandeur et la voiture est la ressource, puisque l'accès à la voiture
        est soumis à un contrôle.
    </para>

    <para>
        Grâce à la définition et à la mise en oeuvre d'une liste de contrôle d'accès (ACL),
        une application peut contrôler comment les objets demandeurs (rôles) reçoivent l'accès (ou
        non) à des objets protégés (ressources).
    </para>

    <sect2 id="zend.acl.introduction.resources">
        <title>A propos des ressources</title>

        <para>
            Avec <classname>Zend_Acl</classname>, créer une ressource est très simple.
            <classname>Zend_Acl</classname> fournit
            <classname>Zend_Acl_Resource_Interface</classname> pour faciliter la tâche aux
            développeurs. Une classe a simplement besoin d'implémenter cette interface, qui
            consiste en une seule méthode, <code>getResourceId()</code>, pour que
            <classname>Zend_Acl</classname> reconnaît l'objet comme étant une ressource. Par
            ailleurs, <classname>Zend_Acl_Resource</classname> est fourni par
            <classname>Zend_Acl</classname> comme une implémentation basique de ressource que les
            développeurs peuvent étendre si besoin.
        </para>

        <para>
            <classname>Zend_Acl</classname> fournit une structure en arbre à laquelle
            plusieurs ressources (ou "zone sous contrôle d'accès") peuvent être ajoutées. Puisque
            les ressources sont sauvées dans cet arbre, elles peuvent être organisées du général
            (via la racine de l'arbre) jusqu'au particulier (via les feuilles de l'arbre). Les
            requêtes envers une ressource spécifique vont automatiquement entraîner la recherche de
            règles sur ses parents au sein de la structure hiérarchique des ressources, ce qui
            permet un héritage simple des règles. Par exemple, si une règle par défaut doit être
            appliquée à tous les bâtiments d'une ville, on pourra simplement assigner la règle à la
            ville elle-même, au lieu de la répéter à tous les bâtiments. Mais certains bâtiments
            peuvent nécessiter des règles spécifiques, et ceci peut se faire aisément avec
            <classname>Zend_Acl</classname> en assignant les règles nécessaires à chaque bâtiment
            de la ville qui nécessite une exception. Une ressource peut hériter d'un seul parent
            ressource, qui hérite lui même de son propre parent, et ainsi de suite.
        </para>

        <para>
            <classname>Zend_Acl</classname> supporte aussi des privilèges pour chaque
            ressource (par exemple : "créer", "lire", "modifier", "supprimer"), et le développeur
            peut assigner des règles qui affectent tous les privilèges ou seuls certains privilèges
            d'une ressource.
        </para>
    </sect2>

    <sect2 id="zend.acl.introduction.roles">
        <title>A propos des rôles</title>

        <para>
            Comme pour les ressources, créer un rôle est très simple.
            <classname>Zend_Acl</classname> propose <classname>Zend_Acl_Role_Interface</classname>
            pour faciliter le travail des développeurs. Une classe doit uniquement implémenter
            cette interface qui consiste en une seule méthode <code>getRoleId()</code>, pour que
            <classname>Zend_Acl</classname> considère l'objet comme un rôle. De plus,
            <classname>Zend_Acl_Role</classname> est inclus dans <classname>Zend_Acl</classname>
            comme une implémentation basique de rôle que les développeurs peuvent étendre si
            besoin.
        </para>

        <para>
            Dans <classname>Zend_Acl</classname>, un rôle peut hériter de un ou plusieurs
            rôles. Ceci permet de supporter l'héritage de règles à travers plusieurs rôles. Par
            exemple, un rôle utilisateur, comme "Éric", peut appartenir à un ou plusieurs rôles
            d'action, tels que "éditeur" ou "administrateur". Le développeur peut créer des règles
            pour "éditeur" et "administrateur" séparément, et "Éric" va hériter des règles des deux
            sans avoir à définir des règles directement pour "Éric".
        </para>

        <para>
            Bien que la possibilité d'hériter de plusieurs rôles soit très utile, l'héritage
            multiple introduit aussi un certain degré de complexité. L'exemple ci-dessous illustre
            l'ambiguïté et la manière de la résoudre.
        </para>

        <example id="zend.acl.introduction.roles.example.multiple_inheritance">
            <title>Héritages multiples entre rôles</title>

            <para>
                Le code ci-dessous définit trois rôles de base - "invite", "membre", et
                "admin" - desquels d'autres rôles peuvent hériter. Ensuite, un rôle identifié par
                "unUser" est créé et hérite des trois autres rôles. L'ordre selon lequel ces rôles
                apparaissent dans le tableau
                <code>$parents</code> est important. Lorsque cela est nécessaire
                <classname>Zend_Acl</classname> recherche les règles d'accès définies non seulement
                pour le rôle demandé (ici "unUser"), mais aussi pour les autres rôles desquels le
                rôle recherché hérite (ici "invite", "membre", et "admin")&#160;:
            </para>

            <programlisting role="php"><![CDATA[
$acl = new Zend_Acl();

$acl->addRole(new Zend_Acl_Role('invite'))
    ->addRole(new Zend_Acl_Role('membre'))
    ->addRole(new Zend_Acl_Role('admin'));

$parents = array('invite', 'membre', 'admin');
$acl->addRole(new Zend_Acl_Role('unUtilisateur'), $parents);

$acl->add(new Zend_Acl_Resource('uneResource'));

$acl->deny('invite', 'uneResource');
$acl->allow('membre', 'uneResource');

echo $acl->isAllowed('unUtilisateur', 'uneResource') ? 'autorisé' : 'refusé';
]]></programlisting>

            <para>
                Puisqu'il n'y a pas de règle spécifiquement définie pour le rôle
                "unUtilisateur" et "uneRessource", <classname>Zend_Acl</classname> doit rechercher
                des règles qui pourraient être définies pour des rôles dont "unUtilisateur" hérite.
                Premièrement, le rôle "admin" est contrôlé, et il n'y a pas de règle d'accès
                définie pour lui. Ensuite, le rôle "membre" est visité, et
                <classname>Zend_Acl</classname> trouve qu'il y a une règle qui spécifie que
                "membre" a un accès autorisé à "uneRessource".
            </para>

            <para>
                Si <classname>Zend_Acl</classname> continuait à examiner toutes les règles de
                tous les rôles parents, il trouverait que "invite" est interdit d'accès à
                "uneRessource". Ceci introduit une ambiguïté puisque maintenant "unUtilisateur" est
                à la fois autorisé et interdit d'accès à "uneRessource", puisqu'il hérite de règles
                opposées de ses différents parents.
            </para>

            <para>
                <classname>Zend_Acl</classname> résout cette ambiguïté en arrêtant la
                recherche de règles d'accès dès qu'une première règle est découverte. Dans notre
                exemple, puisque le rôle "membre" est examiné avant le rôle "invite", le résultat
                devrait afficher "autorisé".
            </para>
        </example>

        <note>
            <para>
                Lorsque vous spécifiez plusieurs parents pour un rôle, conservez à l'esprit
                que le dernier parent listé est le premier dans lequel une règle utilisable sera
                recherchée.
            </para>
        </note>
    </sect2>

    <sect2 id="zend.acl.introduction.creating">
        <title>Créer la Liste de Contrôle d'Accès</title>

        <para>
            Une ACL peut représenter n'importe quel ensemble d'objets physiques ou virtuels
            que vous souhaitez. Pour les besoins de la démonstration, nous allons créer un système
            basique d'ACL pour une Gestion de Contenus (CMS) qui comporte plusieurs niveaux de
            groupes au sein d'une grande variété de zones. Pour créer un nouvel objet ACL, nous
            créons une nouvelle instance d'ACL sans paramètres&#160;:
        </para>

        <programlisting role="php"><![CDATA[
$acl = new Zend_Acl();
]]></programlisting>

        <note>
            <para>
                Jusqu'à ce que le développeur spécifie une règle "allow",
                <classname>Zend_Acl</classname> refuse l'accès pour tous les privilèges sur chaque
                ressource pour chaque rôle.
            </para>
        </note>
    </sect2>

    <sect2 id="zend.acl.introduction.role_registry">
        <title>Registre des rôles</title>

        <para>
            Les systèmes de gestion de contenu vont pratiquement toujours nécessiter une
            hiérarchie de permissions afin de déterminer les droits de rédaction de ses
            utilisateurs. Il pourrait y avoir un groupe "Invités" qui donne accès aux
            démonstrations, un groupe "Staff" pour la majorité des utilisateurs du CMS qui
            réalisent la plupart du travail quotidien, un groupe "Éditeur" pour ceux qui sont
            responsables de la publication, l'archivage, la relecture et la suppression, et enfin
            un groupe "Administrateur" dont les tâches incluent toutes les tâches des autres
            groupes plus des tâches de maintenance, de gestion des utilisateurs, configuration et
            backup/export. Cet ensemble de permissions peut être représenté dans un registre de
            rôles, permettant à chaque groupe d'hériter des privilèges des groupes "parents". Les
            permissions peuvent être rendues de la manière suivante&#160;:
        </para>

        <table id="zend.acl.introduction.role_registry.table.example_cms_access_controls">
            <title>Contrôles d'Accès pour un exemple de CMS</title>

            <tgroup cols="3">
                <thead>
                    <row>
                        <entry>Nom</entry>
                        <entry>Permissions</entry>
                        <entry>Permissions héritées de</entry>
                    </row>
                </thead>
                <tbody>
                    <row>
                        <entry>Invité</entry>
                        <entry>Voir</entry>
                        <entry>N/A</entry>
                    </row>
                    <row>
                        <entry>Staff</entry>
                        <entry>Modifier, Soumettre, Relire</entry>
                        <entry>Invité</entry>
                    </row>
                    <row>
                        <entry>Éditeur</entry>
                        <entry>Publier, Archiver, Supprimer</entry>
                        <entry>Staff</entry>
                    </row>
                    <row>
                        <entry>Administrateur</entry>
                        <entry>(Reçoit tous les accès)</entry>
                        <entry>N/A</entry>
                    </row>
                </tbody>
            </tgroup>
        </table>

        <para>
            Pour cet exemple, <classname>Zend_Acl_Role</classname> est utilisé, mais
            n'importe quel objet qui implémente <classname>Zend_Acl_Role_Interface</classname> est
            acceptable. Ces groupes peuvent être ajoutés au registre des rôles comme suit&#160;:
        </para>

        <programlisting role="php"><![CDATA[
$acl = new Zend_Acl();

// Ajoute des groupes au registre des rôles en utilisant Zend_Acl_Role

// Invité n'hérite d'aucun accès
$roleinvite = new Zend_Acl_Role('invite');
$acl->addRole($roleinvite);

// Staff hérite de Invité
$acl->addRole(new Zend_Acl_Role('staff'), $roleinvite);

// Ce que précède pourrait aussi être écrit:
// $acl->addRole(new Zend_Acl_Role('staff'), 'invite');

// Editeur hérite de staff
$acl->addRole(new Zend_Acl_Role('editeur'), 'staff');

// Administrateur n'hérite pas d'accès
$acl->addRole(new Zend_Acl_Role('administrateur'));
]]></programlisting>
    </sect2>

    <sect2 id="zend.acl.introduction.defining">
        <title>Définir les Contrôles d'Accès</title>

        <para>
            Maintenant que l'ACL contient les rôles nécessaires, on peut établir des règles
            qui définissent comment les ressources accèdent aux rôles. Vous avez sans doute noté
            que nous n'avons défini aucune ressource particulière pour cet exemple, ce qui est plus
            simple pour illustrer comment les règles s'appliquent à toutes les ressources.
            <classname>Zend_Acl</classname> fournit une implémentation dans laquelle les règles
            doivent simplement être assignées du général au particulier, ce qui réduit le nombre de
            règles spécifiques à ajouter. Ceci grâce à l'héritage.
        </para>

        <note>
            <para>
                Généralement <classname>Zend_Acl</classname> se conforme à une règle donnée
                si et seulement si une règle plus spécifique ne s'applique pas.
            </para>
        </note>

        <para>
            En conséquence, on peut définir un nombre assez complexe de règles avec un nombre
            minimal de code. Pour définir les permissions comme définies ci-dessus&#160;:
        </para>

        <programlisting role="php"><![CDATA[
$acl = new Zend_Acl();

$roleinvite = new Zend_Acl_Role('invité');
$acl->addRole($roleinvite);
$acl->addRole(new Zend_Acl_Role('staff'), $roleinvite);
$acl->addRole(new Zend_Acl_Role('editeur'), 'staff');
$acl->addRole(new Zend_Acl_Role('administrateur'));

// Invité peut uniquement voir le contenu
$acl->allow($roleinvite, null, 'voir');

/*
ce qui précède peut aussi être écrit :
$acl->allow('invité', null, 'voir');
*/

// Staff hérite des privilèges de Invité, mais a aussi ses propres
// privilèges
$acl->allow('staff', null, array('edit', 'submit', 'relire'));

// Editeur hérite les privilèges voir, modifier, soumettre,
// et relire de Staff, mais a aussi besoin de certains privilèges
$acl->allow('editeur', null, array('publier', 'archiver', 'supprimer'));

// Administrateur hérite de rien, mais reçoit tous les privilèges
$acl->allow('administrateur');
]]></programlisting>

        <para>
            Les valeurs <code>null</code> dans les appels <code>allow()</code> ci-dessus sont
            utilisées pour indiquer que les règles s'appliquent à toutes les ressources.
        </para>
    </sect2>

    <sect2 id="zend.acl.introduction.querying">
        <title>Interroger les ACL</title>

        <para>
            Nous avons maintenant une ACL flexible, qui peut être utilisée pour déterminer si
            l'objet appelant a les permissions pour réaliser les fonctions au sein de l'application
            web. Interroger l'ACL est assez simple en utilisant la méthode
            <code>isAllowed()</code>&#160;:
        </para>

        <programlisting role="php"><![CDATA[
echo $acl->isAllowed('invité', null, 'voir') ?
     "autorisé" : "refusé";
// autorisé

echo $acl->isAllowed('staff', null, 'publier') ?
     "autorisé" : "refusé";
// refusé

echo $acl->isAllowed('staff', null, 'relire') ?
     "autorisé" : "refusé";
// autorisé

echo $acl->isAllowed('editeur', null, 'voir') ?
     "autorisé" : "refusé";
// autorisé parce que hérité de Invité

echo $acl->isAllowed('editeur', null, 'modifier') ?
     "autorisé" : "refusé";
// refusé parce qu'il n'y a pas de règle pour 'modifier'

echo $acl->isAllowed('administrateur', null, 'voir') ?
     "autorisé" : "refusé";
// autorisé car administrateur est autorisé pour tout

echo $acl->isAllowed('administrateur') ?
     "autorisé" : "refusé";
// autorisé car administrateur est autorisé pour tout

echo $acl->isAllowed('administrateur', null, 'modifier') ?
     "autorisé" : "refusé";
// autorisé car administrateur est autorisé pour tout
]]></programlisting>
    </sect2>
</sect1>
