Permission

Třída Permission obstarává práci s uživatelskými rolemi a jejich právy a přístupy. Díky této třídě budou Vaše aplikace bezpečné a programování uživatelského zabezpečení bude hračka.

Než si vysvětlíme co a jak, bylo by vhodné vysvětlit a připomenout pojmy, se kterými budeme operovat.

  • Role – je role uživatele, pomocí role sdružujeme oprávnění, které budeme na dané uživatele aplikovat. (př.: guest, member, admin)
  • Resource – je oblast, nad kterou budeme definovat jednotlivá přístupová práva. (př.: clanky, administrace, nastenka)
  • Actions – jsou akce, které uživatel v roli role provádět nad resource (př.: edit, delete, show)

Základní práce se třídou bude tedy spočívat na nadefinování rolí a resource a následnému propojení, co kdy daný uživatel může na dané oblasti dělat. Jednotlivé uživatelské role se můžou navzájem dědit. Rodiče dané role definujeme pomocí druhému parametru. Jako rodiče předáme jeho jméno, nebo pole se jmény požadovaných rodičů.

Role guest je definována automaticky po vytvoření třídy Permission.

$acl = new Permission();
$acl->addRole('member', 'guest');
$acl->addRole('admin', 'member');

$acl->addResource('clanky');
$acl->addResource('komentare');

Dále musím definovat jednotlivé propojení mezi zdroji a rolemi. Pokud nejsou u dané role definovány jednotlivé zdroje nebo akce, pak vrací metoda isAllowed false. Z toho vyplývá, že přístupnějším systéme definice jednotlivých vazeb je odspodu, od guest, a následné povolování přístupu jednotlivým rolím.

Vazby vytváříme pomocí metody allow(), respektive pomocí deny(), jako první parametr zadáváme role, jako druhý zdroje a jako třetí akce.

$acl->allow('member', 'posts', 'comment');

Jednotlivé parametry předáváme jako řetězec, případně jako pole řetězců. Velmi užitečným nástrojem nám může být kvantifikátor *. Díky hvězdičce nemusíme vyjmenovávat všechny zdroje / akce, ale jednoduše můžeme nastavit práva pro celou danou oblast.

Hvězdička se smí použít pouze po nadefinování zdrojů a akcí. Na později přidané zdroje a akce nebude mít vliv!

$acl = new Permission();

# roles
$acl->addRole('member', 'guest');
$acl->addRole('admin', 'member');
$acl->addRole('superadmin', 'admin');

# resource
$acl->addResource('comments');
$acl->addResource('posts');

# privilegies
$acl->allow('guest', array('posts', 'comments'), 'view');
$acl->allow('member', 'comments', 'add');
$acl->allow('admin', 'posts', array('add', 'edit', 'delete'));
$acl->allow('superadmin', '*', '*');



# returns true
$acl->isAllowed('guest', 'posts', 'view');
$acl->isAllowed('guest', 'comments', 'view');
$acl->isAllowed('member', 'comments', 'view');
$acl->isAllowed('admin', 'comments', 'add');
$acl->isAllowed('admin', 'posts', 'view');
$acl->isAllowed('superadmin', 'posts', 'delete');
$acl->isAllowed('superadmin', 'comments', 'delete');

# returns false
$acl->isAllowed('guest', 'comments', 'add');
$acl->isAllowed('guest', 'posts', 'add');
$acl->isAllowed('member', 'comments', 'delete');
$acl->isAllowed('admin', 'comments', 'delete');

Dynamický správa přístupu

Dynamickou správu přísupu využijete tehdy, když budete potřebovat se rozhodnout na základě jiných faktorů, než je pouze jméno zdroje a akce.

class TimeAssertion extends PermissionAssertion
{
    public function assert(Permission $acl, $resource, $action)
    {
        return date('H') > 12;
    }
}

Třída, jenž bude provádět validaci musí být potomkem od třídy PermissionAssertion a musí definovat metodu assert, jak je uvedeno v ukázce (včetně stejných parametrů). Metodě assert je předán objekt Permission, dále název zdroje a název action. V této ukázce povolíme hostovi přístup ke všemu, ale až po poledni.

$acl = new Permission;
$acl->allow('guest', '*', '*', new TimeAssertion);

Dynamický správa zdrojů

Často nastane situace, kdy je třeba povolit uživateli přístup pouze k části zdrojů, například k té, které je vlastníkem. I tento složitý mechanismus třída Permission zvládne. Využijeme k tomu dynamickou správu přístupu a přidáme ještě objektové zastoupení zdroje.

class MediaResource extends Resource
{
    public $author_id;
    protected $name = 'media';
}

class MediaAssertion extends PermissionAssertion
{
    public function assert(Permission $acl, $resource, $action)
    {
        return $this->resource->author_id == 1234;
    }
}

Třída dynamického zdroje musí být potomkem třídy Resource a musí mít nadefinovanou členskou proměnnou $name. Proměnná $name by měla obsahovat jméno zdroje.

$acl = new Permission;
$acl->addRole('author');
$acl->addResource('media');
$acl->allow('author', 'media', '*', new MediaAssertion);

$media = new MediaResource;
$media->author_id = 1234;


# returns true
$acl->isAllowed('author', $media);
$acl->isAllowed('author', $media, 'view');