Kam umiestniť $acl = new Nette\Security\Permission;

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

Naydar,
Prosím vás kam vlastne patrí riadok $acl = new Nette\Security\Permission; a nastavenie všetkých rolí, zdrojov a pravidiel?
PS: Nedá sa to urobiť cez NEON?

enumag
Člen | 2118
+
+1
-

Přes neon se to myslím nastavit dá, ale nedoporučuji to. Když budeš potřebovat naspecifikovat něco složitějšího tak to přes neon nepůjde.

Osobně to řeším takhle.

Čamo
Člen | 786
+
0
-

enumag:
Hm, mňa to ťahá k tomu, čo napísal v tom vlákne Šaman nad tebou. Je to síce asi to znásilnenie dedičnosti, ale je to také minimalistické. Žiadny medzikrok.

Dalo by sa to spraviť tak,že by to fungovalo ako RouterFactory? Že by to spracoval bootstrap automaticky? Viac mi to pripadá ako konfigurácia aplikácie, než ako nejaká služba. Ale možno úplne trepem…

PS:
Potreboval by som vysvetliť ten neon čo tam máš:

services:
    app.authorizatorFactory: App\AuthorizatorFactory
    app.authorizator: @app.authorizatorFactory::create

načo je to app. + celý ten druhý riadok. Z neonu mám stále dosť guláš.

Editoval Čamo (20. 1. 2015 23:54)

Filip Procházka
Moderator | 4668
+
0
-

Souhlasím s @enumag – řešení s factory je dobré řešení a rozhodně je čistější než dědit Permission objekt, jenom abys ho v konstruktoru nastavil.

Ta definice v services znamená

  • zaregistruj službu app.authorizatorFactory, jejíž třída bude App\AuthorizatorFactory
  • zaregistruj službu app.authorizator, která se vytváří zavoláním metody create nad objektem, který získáš ze služby app.authorizatorFactory

Přepsáno na procedurální kód by to vypadalo zjednodušeně takto nějak

$factory = new App\AuthorizatorFactory;
$container->addService('app.authorizator', $factory->create());
Čamo
Člen | 786
+
0
-

Díky za odpovede. Snáď som to pochopil.

Ale dedenie sa používa aj vtedy, keď sa prepisuje nejaká metóda. V tomto prípade je to konštruktor nie?

Filip Procházka
Ten kód by nemal vyzerať skôr takto?

$container->addService('factory', new App\AuthorizatorFactory());
$container->addService('app.authorizator', $container->factory->create());

Tie prefixi som si už prečítal.

Díky.

Editoval Čamo (21. 1. 2015 8:23)

enumag
Člen | 2118
+
+1
-

@Čamo V podstatě ano, Filip to zjednodušil protože AuthorizatorFactory je službou vlastně jen proto aby se to volání create dalo nastavit přes neon. V procedurálním zápisu to nutné není. Reálně v aplikaci tu službu factory potřebovat nebudeš, injectneš si přímo ten authorizator.

Editoval enumag (21. 1. 2015 9:31)

Šaman
Člen | 2640
+
0
-

Čamo napsal(a):

enumag:
Hm, mňa to ťahá k tomu, čo napísal v tom vlákne Šaman nad tebou. Je to síce asi to znásilnenie dedičnosti, ale je to také minimalistické. Žiadny medzikrok.

No, znásilnění dědičnosti to není (můj AccessList JE konkretizovaná Permission), ale spíš jde o to, že je zbytečné vytvářet novou třídu děděním, když na to stačí továrnička (stejná situace je ve formulářích).

Tu továrnu pak stejně potřebuju (ACL by ještě mohla být služba, ale formuláře chci určitě vytvářet továrnou, abych jich mohl mít několik), tak si rovnou napíšu továrnu, co mi nakonfiguruje a vrátí konkrétní instanci, než nejprve dědit, vytvořit jednoúčelovou classu a pak si stejně nechat vygenerovat továrnu (vpodstatě prázdnou).


Dokud máš dojem, že se tu bavíme na zbytečně akademické úrovni, nebo dokud jsi rád, že rozchodíš aspoň jeden způsob, tak oba jsou dostatečně dobré. Ale dneska už používám přednostně @enumagův způsob všude, kde potřebuju nakonfigurovat a vrátit konkrétní instanci nějaké třídy – za best practise bych bral jeho řešení.

David Grudl
Nette Core | 8172
+
0
-

Já bych to udělal jako @enumag a klidně i použil místo metody funkci (resp. statickou metodu, protože funkce neumí autoloading):

class AuthorizatorFactory
{

	/**
	 * @return \Nette\Security\IAuthorizator
	 */
	public static function create()
	{
		...
		return $acl;
	}

}

Protože pak je snadnější zápis do configu

services:
	app.authorizator: App\AuthorizatorFactory::create
enumag
Člen | 2118
+
+2
-

@DavidGrudl V AuthorizatorFactory někdy potřebuji nějakou další službu, typicky pokud role tahám z databáze. Proto ponechávám factory jako službu abych si mohl závislosti injectnout. Samozřejmě v případě, že factory závislosti nemá je tvůj způsob zcela v pořádku.

Šaman
Člen | 2640
+
0
-

@DavidGrudl: Přesně o tomhle jsm přemýšlel už u routeru. Jedna tovární metoda a v configu zbytečně dva řádky. Je nějaký důvod nepřepsat Router stejným způsobem?

enumag
Člen | 2118
+
+1
-

@Šaman Úplně stejný případ jako jsem odpovídal Davidovi. Pokud v RouterFactory nepotřebuješ závislosti, klidně si to tak přepiš. Já si factory nechávám jako službu vždy, ale dělám to jen ze setrvačnosti – respektive abych so nemusel měnit až budu závislost potřebovat.

EDIT: Teoreticky kdybys závislosti dal jako argumenty té statické funkce tak by to zřejmě fungovalo, ale to už se mi více zamlouvá normální třída a konstruktor.

Editoval enumag (21. 1. 2015 15:36)

David Grudl
Nette Core | 8172
+
+1
-

@enumag: službu si klidně nechám injectnout do statické funkce:

	/**
	 * @return \Nette\Security\IAuthorizator
	 */
	public static function create(Nette\Database\Connection $db)
	{
		...
	}

@Šaman už se stalo

Filip Procházka
Moderator | 4668
+
0
-

Čamo napsal(a):

Ale dedenie sa používa aj vtedy, keď sa prepisuje nejaká metóda.

Né vždy. A né vždy je vhodné přepisovat metody, občas (=skoro vždy) je lepší použít kompozici a nebo jiné techniky.

V tomto prípade je to konštruktor nie?

To je právě strašný omyl. Dědit třídu abys ji nastavil v konstruktoru je brutální prasárna. Od toho jsou továrny a konfigurace.

David Matějka
Moderator | 6445
+
+1
-

doplnim jen obligatni „inheritance is the root of all evil“ :)

@DavidGrudl to sice hezky funguje, kdyz je to pod spravou DIC, problem by byl mimo – zatimco u factory s nestatickou metodou si proste vyzadas onu FooFactory a zavolas create, u te staticke metody by jeji uzivatel musel znat a ziskavat vsechny jeji zavislosti, aby ji vubec mohl zavolat…

Čamo
Člen | 786
+
0
-

Paráda funguje to… (až na jednu maličkosť č.4)

Ak by mal niekto náladu :P

  1. Tá závislosť služby na DB sa musí povoliť v neone, aby sa to dalo injektovať, že ano?
  2. Prečo je konfigurácia v konštruktore „brutálna prasárna“?
  3. Ako by to vyzeralo bez možnosti injektovať(tú databázu)?
  4. Mám kód:
$permission->addRole('admin', 'redactor');
...
prihlási sa admin
...
if($user->isInRole('admin') { echo 'admin' }
if($user->isInRole('redactor') { echo 'redactor' }

Vypíše iba admin. Dedičnosť rolí to teda nedokáže zohľadniť?

Editoval Čamo (21. 1. 2015 20:42)

David Matějka
Moderator | 6445
+
+2
-

@Čamo

  1. pokud pouzivas ten zpusob od @enumag, tak pouze v konstruktoru te factory uved zavislost na DB, o zbytek se postara autowiring.
  2. je to zneuziti dedicnosti. Zbytecne tam vytvaris nejakou hierarchii trid, kdyz to vubec neni potreba. Factory pattern je mnohem tvarnejsi. Prece taky nedelas, ze by sis podedil Nette\Database\Connection, nazval to MojeSpojeni a v konstruktoru to nakonfiguroval :)) (ano, je to trochu ad absurdum, ale…).
  3. nechapu…
  4. bohuzel, dedicnost roli je vlastnost Nette\Security\Permission. Metoda isInRole, ktera je v Nette\Security\User o tom nevi a proto pracuje pouze s temi rolemi v identie. Pokud vsak budes pouzivat isAllowed, tak se dedicnost roli zohledni.

Editoval matej21 (21. 1. 2015 20:58)

David Grudl
Nette Core | 8172
+
0
-

@matej21 přesně tak. Záleží na tom, jestli chci mít v DIC továrnu na ACL nebo ACL, a podle toho to napíšu. Pokud továrnu nepotřebuju, je zbytečné ji vytvářet.

Třeba v případě routeru jsem se s potřebou mít na něj v DIC továrnu zatím nesetkal, předpokládám, že je to hodně vzácné, proto jsem ji ze sandboxu odstranil.

Šaman
Člen | 2640
+
0
-

Čamo napsal(a):

4. Mám kód:

$permission->addRole('admin', 'redactor');
...
prihlási sa admin
...
if($user->isInRole('admin') { echo 'admin' }
if($user->isInRole('redactor') { echo 'redactor' }

Vypíše iba admin. Dedičnosť rolí to teda nedokáže zohľadniť?

Dědičnost rolí funguje, jak už psal @matej21, jen co se týče opravnění. Ber to tak, že admin dědí práva redaktora, nikoliv tak, že admin je redaktor.
$user->isInRole() ti ověří, zda daný uživatel má přímo přidělenou nějakou roli. Pokud budeš chtít provádět jednoduché řízení práv na základě rolí aka if($user->isInRole()) {…}, tak s dědičností nepočítej. V tu chvíli ani objekt Permission nepotřebuješ.

Čamo
Člen | 786
+
0
-

Dobre isAllowed dáva viac možností ako isInRole.