Problém s ACL – přidělení práv pro roly Guest

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
plasmo
Člen | 66
+
0
-

Tak a mám tu další problém, nevím jestli chybu dělám je, nebo si ze mě nette utahuje :-)

V aplikaci využívám ACL pro autorizaci a následnou autentizaci uživatelů, k některým částem webu potřebuji aby měl přístup tzv. host, např. k HomepagePresenter, ale bohužel i přes nadefinování práv pro hosta nemám šanci k danému presenteru přistoupit, zasílám úryvek kódu, kde definuji práva.

<?php
class Proj_Security_Acl2 extends Permission
{
    const GUEST_ROLE = "guest";
    const USER_ROLE = "user";
    const EDITOR_ROLE = "editor";
    const ADMIN_ROLE = "admin";

    public function __construct()

    {
        // role
        $this->addRole(self::GUEST_ROLE);
        $this->addRole(self::USER_ROLE, self::GUEST_ROLE);
        $this->addRole(self::EDITOR_ROLE, self::USER_ROLE);
        $this->addRole(self::ADMIN_ROLE);

        // zdroje
        $this->addResource('HomepagePresenter');
        $this->addResource('TestPresenter');

        // privilegia
        $this->allow(self::GUEST_ROLE,'HomepagePresenter', array('view'));
        $this->allow(self::EDITOR_ROLE, 'TestPresenter', Permission::ALL);
        $this->allow(self::ADMIN_ROLE, Permission::ALL, Permission::ALL);
    }
}

?>

Co dělám špatně, nebo proč se nemůžu k homepage dostat bez přihlášení? Děkuji

EDIT: fixnuté zvýrazňovanie

Editoval kravčo (16. 9. 2010 12:26)

srigi
Nette Blogger | 558
+
0
-

Rolu guest nepridavaj, tu pridava Nette samo. Vyskusaj, mozno to je problem.

plasmo
Člen | 66
+
0
-

Roli Guest nepřiřazuju, jen se ji snažím nastavit provilegia, protože nepřihlašený může stránku zobrazit, ale všichni ostatní již mají práv více.

toka
Člen | 253
+
0
-

srigi napsal(a):

Rolu guest nepridavaj, tu pridava Nette samo. Vyskusaj, mozno to je problem.

Já tedy v dynamickém ACL roli guest vždy přidávám sám. Jenže já si myslím, že aby ti to fungovalo, tak se uživatel musí úspěšně přihlásit a zároveň být v roli guest. Takže pokud platí !isLoggedIn(), resp. !isAuthenticated(), tak zobrazíš to, co chceš ty pro „svého guesta“.

kravčo
Člen | 721
+
0
-

plasmo napsal(a):

Roli Guest nepřiřazuju, jen se ji snažím nastavit provilegia, protože nepřihlašený může stránku zobrazit, ale všichni ostatní již mají práv více.

srigi asi myslel niečo takéto:

<?php

class Proj_Security_Acl2 extends Permission
{
    // ...

    public function __construct()
    {
        // onedlho cez ServiceLocator, či ako sa bude volať...
	$guest_role = Environment::getUser()->guestRole;

        // role
        $this->addRole($guest_role);
        $this->addRole(self::USER_ROLE, $guest_role);
        $this->addRole(self::EDITOR_ROLE, self::USER_ROLE);
        $this->addRole(self::ADMIN_ROLE);

        // ...
    }
}

V tomto kóde chybu nevidím. Dôležité je aj to, ako testuješ, či má užívateľ právo na to-ono, tento kód skrátka (mne) nestačí…

// toto by malo fungovať aj bez prihlásenia užívateľa
$acl->isAllowed('guest', 'HomepagePresenter', 'view'); // TRUE
plasmo
Člen | 66
+
0
-

V tomto kóde chybu nevidím. Dôležité je aj to, ako testuješ, či má užívateľ právo na to-ono, tento kód skrátka (mne) nestačí…

// toto by malo fungovať aj bez prihlásenia užívateľa
$acl->isAllowed('guest', 'HomepagePresenter', 'view'); // TRUE

Aha, no už tomu možná začínám přicházet na kobylku, jak píše asi Toka, k tomu aby mě to vzalo to asi vyžaduje přihlášení a zároveň aby přihlášený uživatel měl roly hosta. Testuju to takto:

<?php
abstract class SecuredPresenter extends BasePresenter
{
    public function startup()
    {
        parent::startup();
        $user = $this->getUser();
        if (!$user->isLoggedIn()) {
            if ($user->getSignOutReason() === User::INACTIVITY) {
                $this->flashMessage('Uplynula doba neaktivity! Systém vás z bezpečnostních důvodů odhlásil.', 'warning');
            }
            $this->flashMessage('Pro vstup do této sekce se musíte přihlásit!', 'warning');
            $backlink = $this->getApplication()->storeRequest();
            $this->redirect(':Login:', array('backlink' => $backlink));
        }else{
            if (!$user->isAllowed($this->reflection->name, $this->getAction())) {
                $this->flashMessage('Pro vstup do této části nemáte dostatečná opravánění!', 'warning');
                $this->redirect(':HomePage:');
            }
        }
    }
}
?>

Editoval plasmo (17. 9. 2010 21:07)

plasmo
Člen | 66
+
0
-

Tak jsem to přepracoval následovně:
btw: vycházím z tohoto "tutoriálu ":https://doc.nette.org/…thentication

SecuredPresenter

<?php
abstract class SecuredPresenter extends BasePresenter
{
    public function startup()
    {
        parent::startup();
        $user = $this->getUser();
        if (!$user->isLoggedIn()) {
            if ($user->getSignOutReason() === User::INACTIVITY) {
                $this->flashMessage('Uplynula doba neaktivity! Systém vás z bezpečnostních důvodů odhlásil.', 'warning');
            }
            if (!$user->isAllowed($this->reflection->name, $this->getAction())){
                $this->flashMessage('Pro vstup do této části nemáte dostatečná opravánění!', 'warning');
                $this->redirect(':HomePage:');
            }
        }else{
            if (!$user->isAllowed($this->reflection->name, $this->getAction())) {
                $this->flashMessage('Pro vstup do této části nemáte dostatečná opravánění!', 'warning');
                $this->redirect(':HomePage:');
            }
        }
    }
}
?>

HomepagePresnter

<?php
class HomepagePresenter extends SecuredPresenter
{

	public function renderDefault()
	{
		$this->template->anyVariable = 'any value';
	}

    public function startup()
    {
        parent::startup();
        $user = $this->getUser();

        if (!$user->isLoggedIn()) {
            if ($user->getSignOutReason() === User::INACTIVITY) {
                $this->flashMessage('Uplynula doba neaktivity! Systém vás z bezpečnostních důvodů odhlásil.', 'warning');
            }
            if (!$user->isAllowed($this->reflection->name, $this->getAction())) {
                $this->flashMessage('Pro vstup do této části nemáte dostatečná opravánění!', 'warning');
                $this->redirect('Login:');
            }
        }
        else {
            if (!$user->isAllowed($this->reflection->name, $this->getAction())) {
                $this->flashMessage('Pro vstup do této části nemáte dostatečná opravánění!', 'warning');
                $this->redirect('Login:');
            }
        }
    }

    public function actionLogout()
    {
        $this->getUser()->signOut();
        $this->flashMessage('Právě jste byl odhlášen.','success');
        $this->redirect('Homepage:');
    }
}

?>

Jediný co se mi nelíbí je zdvojení podmínky

<?php
if (!$user->isAllowed($this->reflection->name, $this->getAction())) {
                $this->flashMessage('Pro vstup do této části nemáte dostatečná opravánění!', 'warning');
                $this->redirect('Login:');
            }
?>

Je to takhle tedy použitelné co se správnosti týče? Funguje to, takže to já jsem spokojen, jen nechci aby to byla prasárna :)

A prosím ještě jsem nějak nepochopil, proč musí mít ty dva presentery stejnou metodu? Když vlastne Homepage dědí od Secure, proč se startup přetěžuje? Z tut, jsem to nepobral. Děkuji

Editoval plasmo (17. 9. 2010 21:06)

kravčo
Člen | 721
+
0
-

Najprv si prosím fixni zdrojáky v predošlých príspevkoch podľa návodu.

Rozhodovanie o prístupe by nemalo závisieť na tom, či je používateľ prihlásený alebo nie. Malo by sa riadiť výhradne tým, či má používateľ prístup k danému zdroju. Teda podmienka $user->isLoggedIn() by sa mala v tvojom prípade využívať nanajvýš na zistenie odhlásenia po dlhej nečinnosti. Duplikovanie podmienky nechápem, v jednom prípade sa testuje a inak sa testuje tiež… žiadny rozdiel :)

<?php

abstract class SecuredPresenter extends BasePresenter
{
    public function startup()
    {
        parent::startup();
        $user = $this->getUser();
        if (!$user->isLoggedIn() && $user->getSignOutReason() === User::INACTIVITY) {
            $this->flashMessage('Uplynula doba neaktivity! Systém vás z bezpečnostních důvodů odhlásil.', 'warning');
        }
        if (!$user->isAllowed($this->reflection->name, $this->getAction())) {
            $this->flashMessage('Pro vstup do této části nemáte dostatečná oprávnění!', 'warning');
            $this->redirect(':HomePage:');
        }
    }
}

HomepagePresenter startup() definovať opäť nemusí, v tomu tutoriáli ho definuje opäť, pretože sa v niečom líšia…

<?php

class HomepagePresenter extends SecuredPresenter
{

    public function renderDefault()
    {
        $this->template->anyVariable = 'any value';
    }

    public function actionLogout()
    {
        $this->getUser()->signOut();
        $this->flashMessage('Právě jste byl odhlášen.', 'success');
        $this->redirect('Homepage:');
    }
}

Ďalší problém je, že prístup k tzv. fallback stránke by nemal byť nijako podmienený. Ak existuje používateľ, ktorý nemá prístup k HomepagePresenteru, pri jeho zobrazení sa mu stránka zacyklí. Preto mi príde správnejšie dediť HomepagePresenter od BasePresenteru a odstatné od SecuredPresenteru. Takisto nemôžeš riadiť prístup k stránke s prihlasovacím formulárom, vznikne rovnako nepríjemné zacyklenie :)

<?php

class HomepagePresenter extends BasePresenter { /* ... */ }
class AnotherPresenter extends SecuredPresenter { /* ... */ }
class YetAnotherPresenter extends SecuredPresenter { /* ... */ }