<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.acl.introduction">
    <title>Wprowadzenie</title>

    <para>
        <classname>Zend_Acl</classname> zapewnia lekką i elastyczną obsługę
        implementacji list kontroli dostępu (<acronym>ACL</acronym>) do zarządzania
        uprawnieniami. Ogólnie rzecz biorąc, aplikacja może używać list
        <acronym>ACL</acronym> do kontrolowania dostępu do określonych chronionych
        obiektów przez inne obiekty.
    </para>

    <para>
        Dla celów tej dokumentacji:
    </para>

    <itemizedlist>
        <listitem>
            <para>
                <emphasis>zasób</emphasis> jest obiektem do
                którego dostęp jest kontrolowany.
            </para>
        </listitem>
        <listitem>
            <para>
                <emphasis>rola</emphasis> jest obiektem, który
                może zażądać dostępu do zasobu.
            </para>
        </listitem>
    </itemizedlist>

    <para>
        Przystępnie mówiąc, <emphasis>role żądają dostępu do zasobów</emphasis>.
        Na przykład, jeśli obsługujący parking samochodow zażąda dostępu do
        samochodu, to ta osoba jest rolą, a samochód jest zasobem, więc dostęp
        do samochodu nie musi zostać przyznany każdemu.
    </para>

    <para>
        Dzięki określeniu i użyciu list kontroli dostępu (<acronym>ACL</acronym>),
        aplikacja może kontrolować to, w jaki sposób żądające obiekty (role) mają
        przydzielany dostęp do chronionych obiektów (zasobów).
    </para>

    <sect2 id="zend.acl.introduction.resources">
        <title>O zasobach</title>
        <para>
            Tworzenie zasobu w Zend_Acl jest bardzo proste. <classname>Zend_Acl</classname> zapewnia
            interfejs <classname>Zend_Acl_Resource_Interface</classname> aby ułatwić
            programistom tworzenie zasobów w aplikacji. Klasa jedynie implementuje ten
            interfejs, który składa się z jednej metody, <methodname>getResourceId()</methodname>,
            dzięki ktorej <classname>Zend_Acl</classname> wie, że obiekt jest zasobem. Dodatkowo w
            <classname>Zend_Acl</classname> dołączona jest klasa <classname>Zend_Acl_Resource</classname>,
            która jest podstawową implementacją zasobu do użycia przez
            programistów gdy jest to potrzebne.
        </para>
        <para>
            <classname>Zend_Acl</classname> zapewnia drzewiastą strukturę, w której
            mogą być dodawane zasoby (lub inaczej "obszary będące pod kontrolą").
            Dzięki temu, że zasoby są przechowywane w strukturze drzewiastej, mogą
            być one organizowane od ogólnych (od korzeni) do szczegółowych (do gałęzi).
            Zapytanie do konkretnego zasobu automatycznie przeszuka całą
            hierarchię zasobów, dla reguł przypisanych do przodka zasobów,
            pozwalając na proste dziedziczenie reguł. Na przykład, jeśli
            domyślna reguła ma być zastosowana do każdego budynku w mieście,
            wystarczy przypisać regułę do miasta, zamiast przypisywać regułę to
            każdego z budynków z osobna. Niektóre z budynków mogą wymagać
            wyjątków od tej reguły i może być to osiągnięte w łatwy sposób w
            <classname>Zend_Acl</classname> poprzez przypisanie takiej wyjątkowej reguły dla każdego z
            budynków wymagających wyjątku. Zasób może dziedziczyć tylko od
            jednego zasobu rodzica, a ten rodzic może także dziedziczyć tylko od
            jednego zasobu itd.
        </para>
        <para>
            <classname>Zend_Acl</classname> także obsługuje przywileje dla zasobów
            (np., "create", "read", "update", "delete") i programista może przypisać
            reguły, które mają zastosowanie do wszystkich przywilejów, lub dla
            konkretnych przywilejów dla jednego lub więcej zasobów.
        </para>
    </sect2>

    <sect2 id="zend.acl.introduction.roles">
        <title>O rolach</title>
        <para>
            Tak jak tworzenie zasobów, tworzenie ról także jest bardzo proste.
            Wszystkie role muszą implementować interfejs <classname>Zend_Acl_Role_Interface</classname>
            Ten interfejs składa się z jednej metody, <methodname>getRoleId()</methodname>,
            dzięki ktorej Zend_Acl wie, że obiekt jest rolą. Dodatkowo w
            Zend_Acl dołączona jest klasa <classname>Zend_Acl_Role</classname>,
            która jest podstawową implementacją roli do użycia przez
            programistów gdy jest to potrzebne.
        </para>
        <para>
            W <classname>Zend_Acl</classname> rola może dziedziczyć z jednej lub więcej ról. Jest to po
            to, aby możliwe było dziedziczenie zasad dla ról. Na przykład rola,
            użytkownik "sally", może dziedziczyć z jednej lub więcej ról
            rodziców, takich jak na przykład "editor" oraz "administrator".
            Programista może przypisać reguły dla ról "editor" oraz
            "administrator" osobno, a "sally" będzie dziedziczyć te reguły od
            obu ról, bez konieczności przypisania reguł bezpośrednio dla
            "sally".
        </para>
        <para>
            Chociaż możliwość dziedziczenia po wielu rolach jest bardzo
            użyteczna, to takie dziedziczenie wprowadza pewien stopień
            złożoności. Poniższy przykład ilustruje niejasny przypadek
            dziedziczenia i pokazuje w jaki sposób <classname>Zend_Acl</classname> go rozwiązuje.
        </para>
        <example id="zend.acl.introduction.roles.example.multiple_inheritance">
            <title>Dziedziczenie po wielu rolach</title>
            <para>
                Poniższy kod definiuje trzy podstawowe role, po których inne role
                mogą dziedziczyć - "guest", "member",
                oraz "admin". Następnie definiowana jest rola o
                nazwie "someUser", ktora dziedziczy po zdefiniowanych
                wcześniej trzech rolach. Ważna jest kolejność zdefiniowania tych
                trzech ról w tablicy <varname>$parents</varname>. Gdy sprawdzamy
                reguły dostępu, <classname>Zend_Acl</classname> szuka reguł zdefiniowanych nie tylko dla
                danej roli (w tym przypadku someUser"), ale także
                dla ról, po których ta rola dziedziczy (w tym przypadku
                "guest", "member" oraz "admin"):
            </para>
            <programlisting language="php"><![CDATA[
$acl = new Zend_Acl();

$acl->addRole(new Zend_Acl_Role('guest'))
    ->addRole(new Zend_Acl_Role('member'))
    ->addRole(new Zend_Acl_Role('admin'));

$parents = array('guest', 'member', 'admin');
$acl->addRole(new Zend_Acl_Role('someUser'), $parents);

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

$acl->deny('guest', 'someResource');
$acl->allow('member', 'someResource');

echo $acl->isAllowed('someUser', 'someResource') ? 'allowed' : 'denied';
]]></programlisting>
            <para>
                Z tego względu, że nie ma zdefiniowanych reguł konkretnie dla
                roli "someUser" oraz dla zasobu "someResource",
                <classname>Zend_Acl</classname> musi szukać zasad, ktore mogą być zdefiniowane dla ról,
                po których dziedziczy rola "someUser>". Wpierw
                sprawdzana jest rola "admin", a dla niej nie ma
                zdefiniowanej żadnej reguły dostępu. Następnie sprawdzana jest
                rola "member" i <classname>Zend_Acl</classname> znajduje zdefiniowaną
                regułę zezwalająca roli "member" na dostęp do zasobu
                "someResource".
            </para>
            <para>
                Jeśli <classname>Zend_Acl</classname> kontynuowałby sprawdzanie reguł zdefiniowanych dla
                innych ról rodziców, znalazłby regułę zabraniającą roli
                "guest" dostępu do zasobu "someResource".
                Ten fakt wprowadza niejaność, ponieważ teraz rola
                "someUser" ma zarówno dozwolony jak i zabroniony
                dostęp do zasobu "someResource", z tego powodu, że
                posiada odziedziczone po dwóch rolach reguły, które są ze sobą
                sprzeczne.
            </para>
            <para>
                <classname>Zend_Acl</classname> rozwiązuje tę niejaśność kończąc
                zapytanie wtedy, gdy znajdzie pierwszą regułę, wprost pasującą do
                zapytania. W tym przypadku, z tego względu, że rola "member" jest
                sprawdzana przed rolą "guest", przykładowy kod
                wyświetliłby "allowed".
            </para>
        </example>
        <note>
            <para>
                Gdy określasz wielu rodziców dla roli, pamiętaj, że ostatni
                rodzic na liście jest pierwszym przeszukiwanym rodzicem w
                celu znalezienia ról pasujących do zapytania autoryzacyjnego.
            </para>
        </note>
    </sect2>

    <sect2 id="zend.acl.introduction.creating">
        <title>Tworzenie list kontroli dostępu</title>

        <para>
            <acronym>ACL</acronym> może reprezentować dowolny zestaw fizycznych lub wirtualnych
            obiektów których potrzebujesz. Dla celów prezentacji utworzymy <acronym>ACL</acronym>
            dla prostego Systemu Zarządzania Treścią (Content Management System
            - <acronym>CMS</acronym>), w którym różnymi obszarami zarządza kilka poziomów grup.
            Aby utworzyć nowy obiekt <acronym>ACL</acronym>, utwórzmy instancję <acronym>ACL</acronym> bez parametrów:
        </para>

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

        <note>
            <para>
                Dopóki programista nie określi reguły "allow", <classname>Zend_Acl</classname> zabroni
                dostępu wszystkim rolom do wszystkich przywilejów dla wszystkich
                zasobów.
            </para>
        </note>
    </sect2>

    <sect2 id="zend.acl.introduction.role_registry">
        <title>Rejestrowanie ról</title>

        <para>
            System Zarządzania Treścią prawie zawsze potrzebuje hierarchii
            uprawnień aby określić możliwości jego użytkowników.
            Może być tu grupa 'Guest' aby pozwolić na limitowany dostęp
            dla celów demonstracyjnych, grupa 'Staff' dla większości
            użytkowników aplikacji <acronym>CMS</acronym>, którzy przeprowadzają najczęstsze
            codzienne operacje, grupa 'Editor' dla tych odpowiedzialnych za
            publikowanie, przeglądanie, archiwizowanie i usuwanie zawartości i
            ostatecznie grupa 'Administrator', której zadania obejmują zarówno
            zadania wszystkich innych grup, jak i zarządzanie ważnymi
            informacjami, zarządzanie użytkownikami, konfigurację baz danych
            oraz przeprowadzanie kopii zapasowych/eksportu danych.
            Ten zestaw pozwoleń może być reprezentowany w rejestrze ról,
            pozwalając każdej grupie dziedziczyć uprawnienia z grup rodziców,
            a także umożliwiając każdej z grup posiadanie własnych unikalnych
            uprawnień. Uprawnienia mogą być wyrażone w taki sposób:
        </para>

        <table id="zend.acl.introduction.role_registry.table.example_cms_access_controls">
          <title>Kontrola dostępu dla przykładowego CMS</title>
          <tgroup cols="3">
            <thead>
              <row>
                <entry>Nazwa</entry>
                <entry>Unikalne uprawnienia</entry>
                <entry>Dzidziczy uprawnienia od</entry>
              </row>
            </thead>
            <tbody>
              <row>
                <entry>Guest</entry>
                <entry>View</entry>
                <entry>N/A</entry>
              </row>
              <row>
                <entry>Staff</entry>
                <entry>Edit, Submit, Revise</entry>
                <entry>Guest</entry>
              </row>
              <row>
                <entry>Editor</entry>
                <entry>Publish, Archive, Delete</entry>
                <entry>Staff</entry>
              </row>
              <row>
                <entry>Administrator</entry>
                <entry>(posiada cały dostęp)</entry>
                <entry>N/A</entry>
              </row>
            </tbody>
          </tgroup>
        </table>

        <para>
            W tym przykładzie użyty jest obiekt <classname>Zend_Acl_Role</classname>, ale
            dozwolony jest dowolny obiekt, który implementuje interfejs
            <classname>Zend_Acl_Role_Interface</classname>. Te grupy mogą być dodane
            do rejestru ról w taki sposób:
        </para>

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

// Dodajemy grupy do rejestru ról używając obiektu Zend_Acl_Role
// Grupa guest nie dziedziczy kontroli dostępu
$roleGuest = new Zend_Acl_Role('guest');
$acl->addRole($roleGuest);

// Grupa staff dzidziczy od grupy guest
$acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);

/*
alternatywnie, powyższe mogłoby wyglądać tak:
$acl->addRole(new Zend_Acl_Role('staff'), 'guest');
*/

// Grupa editor dziedziczy od grupy staff
$acl->addRole(new Zend_Acl_Role('editor'), 'staff');

// Administrator nie dziedziczy kontroli dostępu
$acl->addRole(new Zend_Acl_Role('administrator'));
]]></programlisting>

    </sect2>

    <sect2 id="zend.acl.introduction.defining">
        <title>Definiowanie kontroli dostępu</title>

        <para>
            Teraz gdy <acronym>ACL</acronym> zawiera stosowne role, możemy ustalić reguły, które
            definiują w jaki sposób role mają uzyskiwać dostęp do zasobów.
            Mogłeś zauważyć, że nie zdefiniowaliśmy w tym przykładzie żadnych
            konkretnych zasobów, co jest uproszczone w celu zilustrowania, że
            reguły mają zastosowanie do wszystkich zasobów. <classname>Zend_Acl</classname> zapewnia
            implementację dzięki której reguły mogą być przypisane od ogólnych
            do szczegółowych, minimalizując ilość potrzebnych reguł, ponieważ
            zasoby oraz role dziedziczą reguły, które są definiowane dla ich
            przodków.
        </para>

        <note>
            <para>
                W zasadzie <classname>Zend_Acl</classname> przestrzega danej reguły tylko wtedy, gdy
                nie ma zastosowania bardziej szczegółowa reguła.
            </para>
        </note>

        <para>
            Możemy więc zdefiniować rozsądny kompleksowy zestaw reguł przy
            minimalnej ilości kodu. Aby zastosować podstawowe uprawnienia
            zdefiniowane wyżej zrób tak:
        </para>

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

$roleGuest = new Zend_Acl_Role('guest');
$acl->addRole($roleGuest);
$acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
$acl->addRole(new Zend_Acl_Role('editor'), 'staff');
$acl->addRole(new Zend_Acl_Role('administrator'));

// Grupa guest może tylko oglądać zawartość
$acl->allow($roleGuest, null, 'view');

/*
alternatywnie, powyższe mogłoby wyglądać tak:
$acl->allow('guest', null, 'view');
*/

// Grupa staff dzidziczy uprawnienia view od grupy guest,
// ale także potrzebuje dodatkowych uprawnień
$acl->allow('staff', null, array('edit', 'submit', 'revise'));

// Grupa editor dziedziczy uprawnienia view, edit, submit,
// oraz revise od grupy staff, ale także potrzebuje dodatkowych uprawnień
$acl->allow('editor', null, array('publish', 'archive', 'delete'));

// Administrator nie dziedziczy niczego, ale ma dostęp do wszystkich zasobów
$acl->allow('administrator');
]]></programlisting>

        <para>
            Wartości <constant>NULL</constant> w powyższych wywołaniach metod
            <methodname>allow()</methodname> oznaczają, że reguły dotyczą wszystkich zasobów.
        </para>

    </sect2>

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

        <para>
            Posiadamy teraz elastyczne <acronym>ACL</acronym>, ktore mogą być użyte do określenia,
            czy żądająca osoba posiada uprawnienia do przeprowadzenia określonej
            akcji w aplikacji web. Przeprowadzenie zapytań jest bardzo proste
            poprzez użycie metody <methodname>isAllowed()</methodname>:
        </para>

        <programlisting language="php"><![CDATA[
echo $acl->isAllowed('guest', null, 'view') ?
     "allowed" : "denied";
// dozwolone

echo $acl->isAllowed('staff', null, 'publish') ?
     "allowed" : "denied";
// zabronione

echo $acl->isAllowed('staff', null, 'revise') ?
     "allowed" : "denied";
// dozwolone

echo $acl->isAllowed('editor', null, 'view') ?
     "allowed" : "denied";
// dozwolone ponieważ jest dziedziczone od gościa

echo $acl->isAllowed('editor', null, 'update') ?
     "allowed" : "denied";
// zabronione ponieważ nie ma reguły dla 'update'

echo $acl->isAllowed('administrator', null, 'view') ?
     "allowed" : "denied";
// dozwolone ponieważ administrator ma wszystkie uprawnienia

echo $acl->isAllowed('administrator') ?
     "allowed" : "denied";
// dozwolone ponieważ administrator ma wszystkie uprawnienia

echo $acl->isAllowed('administrator', null, 'update') ?
     "allowed" : "denied";
// dozwolone ponieważ administrator ma wszystkie uprawnienia
]]></programlisting>

    </sect2>
</sect1>