Uživatelské ROLE a přímé zadání URL

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

Zajímalo by mě, jak mám zamezit(přesměrovat), nějakým hezkým způsobem, přímé zadání url do browseru na které uživatel nemá roly/právo, nechci se v každém presenteru ptát jestli není uživatel admin → přesměruj na default page atd:.

Tzn: user má přístup pouze do Dashboard + Rezervace
admin má přístup všude

ovšem pokud zná uživatel adresu (z historie prohlížeče a pod) a zadá ji do browseru dostane se například do administrace, dá se tohle nastavit v config.neon nebo base presenteru ?

Jak generovat menu jsem již vyřešil v Generovaní menu dle role

Editoval Joacim (1. 4. 2015 14:31)

Azathoth
Člen | 495
+
+4
-

Já mám pro všechny prezentery, kam má přístup pouze uživatel s určitou rolí, baseprezenter, ze kterého dědí a ve startup metodě si testuji roli a pokud je špatná, tak uživatele přesměruji pryč.

Joacim
Člen | 229
+
0
-

Šlo by poslat nějakou ukázku ? Princip chápu jen se v nette zatím moc neorientuji a hledat správné cesty přes vypsání objektů – var_dump (abych věděl co jaká proměná má uloženo), to se radši zeptám.

Mám si vypsat nette application request nebo existuje lepší cesta jak zjistit na co se uživatel odkazuje ?

thm
Člen | 147
+
0
-
// základní presenter
class BasePresenter extends Nette\Application\UI\Presenter{}

// Presenter který bude mít jenom startup - slouží ke kontrolování něčeho pro všechny presentery, které od něho budou dědit
class LoggedUserPresenter extends BasePresenter{

	public function startup() {
		parent::startup(); //V každém presenteru je NUTNÉ volat startup předka, pokud je startup v presenteru použitý.

		if(!$this->user->isLoggedIn()){ //Nebo $user->isAllowed(), $user->isInRole() atd...
                  $this->flashMessage('Pro přístup do této části aplikace musíte být přihlášeni.');
                  $this->redirect('Ass:'); //Pošleme do...
            }
	}
}

// Pak už jenom dědíš od LoggedUserPresenteru a můžeš si být jistý že do view takto zděděných presenterů se dostane pouze přihlášený uživatel (v mém příkladě).
class UserInformationPresenter extends LoggedUserPresenter{
	public function startup() {
		parent::startup(); //Právě tady (v tomto případě) je nutné volat startup předka, jinak by se provedl startup jenom UserInformationPresenteru... Ale ty potřebuješ aby se provedla kontrola, jestli je uživatel přihlášený, nebo jestli má nějaké oprávnění apod.
		...
		...
		...
		//... další kód startupu.. Pokud bys zde (v tomto startupu neměl žádný kód), můžeš ho zcela vynechat.
	}
}

Editoval thm (2. 4. 2015 11:02)

greeny
Člen | 405
+
+5
-

Na tohle můžeš využít metodu Presenter::checkRequirements , např.:

class ProtectedPresenter extends BasePresenter
{
	public function checkRequirements($element) {
		if (!$this->user->isLoggedIn()) {
			$this->redirect('Homepage:default');
		}
	}
}
Joacim
Člen | 229
+
0
-

Dá se to použít v Basepresenteru i na

$this->user->isInRole(‚admin‘) ?

jelikož mám nastaveno

$permission = new Permission();

        /* seznam uživatelských rolí */
        $permission->addRole('user');
        $permission->addRole('admin');

        /* seznam zdrojů */
        $permission->addResource('Dashboard');
        $permission->addResource('Reservations');
        $permission->addResource('Setup');
        $permission->addResource('Workflow');

        /* seznam pravidel oprávnění */
        $permission->allow('user', array('Dashboard', 'Reservations'), 'list');
        //...

        /* admin má práva na všechno */
        $permission->allow('admin', Permission::ALL, Permission::ALL);

pro generováníé menu v default šabloně je to ok, teď už jen potřebuji hlídat přímé zadání url a je třeba zmínit že v mojí aplikaci je každý přihlášený, pokud není vidí jen přihlašovací okno

abstract class BasePresenter extends Nette\Application\UI\Presenter {

    public function startup() {
        parent::startup();

        if (!$this->getUser()->isLoggedIn() && ($this->getName() !== "Login")) {
            $this->redirect("Login:default");
        } else {
            if ($this->getUser()->isLoggedIn()) {
                $this->template->userLogged = $this->user->identity->getId();

			// Někde zde aplikovat pravidlo $this->user->isInRole('admin') a porovnat to s požadavkem na prezenter ?
            } else {
                $this->template->userLogged = FALSE;
            }
        }
    }
}

Editoval Joacim (2. 4. 2015 13:07)

greeny
Člen | 405
+
0
-

Jasně, místo $this->user->isLoggedIn() si můžeš napsat jakoukoliv podmínku. Ale nedělej to ve startup(), dělej to v checkRequirements().

<ot>
Předávání tý userLogged proměnné patří spíš do beforeRender, než startup.
</ot>

Joacim
Člen | 229
+
0
-

Problém nastane pokud uživatel není oprávněn a já volám redirect

class ProtectedPresenter extends BasePresenter{

    public function checkRequirements($param) {

        if ($this->user->isAllowed($this->request->presenterName)) {
            //var_dump('Je OPRAVNEN');
        } else {
            //var_dump('Neni OPRAVNEN');
            //$this->flashMessage('Nejste oprávněni přistupovat do ' . $this->request->presenterName, "danger");
            $this->redirect("Dashboard:default");
        }
    }

}

dostanu hlášku

User Notice Possible problem: you are sending a HTTP header while already having some data in output buffer. Try Tracy\OutputDebugger or start session earlier.

Všechny presentery které mají omezený přístup dědí z ProtectedPresenter

greeny
Člen | 405
+
0
-
  1. pokud každej presenter vyžaduje něco jiného, tak je to ideální napsat pro každej zvlášť a netahat to „magicky“ ze jména presenteru
  2. zkontroluj si, jestli jsi někde nenechal var_dump. Jo a pokud místo var_dump použiješ jenom dump, tak to budeš mít krásně barevný :P
Joacim
Člen | 229
+
0
-

Ted jsem zjistil, že tu hlášku skutečně zapříčinil var_dump() – za to se omlouvám

No zatím mám presenter pouze Setup(do něj muže přistupovat pouze uživatel s rolí admin) a k němu mám více odkazu(User, Users, Workflow) i šablon(user.latte, users.latte atd) a jen si v presenteru Setup volám příslušnou metodu pro kterou mám příslušný model, otázkou je jestli je to v rámci implementace atd dobře a nebo chybně – to zbnamená že pro každý presenter nemám pouze jeden template, ale vícero

<ul class="nav navbar-nav">
                        <li {ifCurrent Dashboard:} class="active" {/ifCurrent}><a href="{$basePath}/">Dashboard</a></li>
                        <li {ifCurrent Reservations:} class="active" {/ifCurrent}><a href="{$basePath}/reservations">reservation</a></li>
                            {if $user->isInRole('admin')}
                            <li {ifCurrent Approval:} class="active" {/ifCurrent}><a href="{$basePath}/approval">Schvalování</a></li>
                            <li {ifCurrent Setup:*} class="active" {/ifCurrent} class="dropdown" >
                                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Nastavení <span class="caret"></span></a>
                                <ul class="dropdown-menu" role="menu">
                                    <li><a n:href="Setup:users">users</a></li>
                                    <li><a n:href="Setup:teams">teams</a></li>
                                    <li><a n:href="Setup:departments">deprt</a></li>
                                    <li class="divider"></li>
                                    <li><a n:href="Workflow:default">wf</a></li>
                                </ul>
                            </li>
                        {/if}
                    </ul>

ale potom mám také

<ul class="nav navbar-nav loginAs">
                        <li class="dropdown" >
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Logged as <b>{$userLogged}</b> <span class="caret"></span></a>
                            <ul class="dropdown-menu" role="menu">
                                <li><a n:href="Setup:user">Nastavení</a></li>
                                <li class="divider"></li>
                                <li><a n:href="Login:out">Odhlásit</a></li>
                            </ul>
                        </li>
                    </ul>

a nevím jak nastavit vyjímku aby mohl každý uživatel přistoupit do svého nastavení (Za předpokladu že nepoužuji jiný presenter)

<li><a n:href="Setup:user">Nastavení</a></li>

Editoval Joacim (2. 4. 2015 15:10)