$acl autorizace – použití

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
masterr
Začátečník | 141
+
0
-

Pročetl jsem si https://doc.nette.org/…thentication
a i forko. Ale pořád mi to není jasné. Chci použít ACL, kde přidám role a opravnění k nim.

To je mi vše jasné, akorát nechápu jak tomu řeknu ,,Hej já mám roli admin" a pak se řid pravidli pro admina.

Vím že je tam isInRole, ale to asi nepoužiju v ACL?

vvoody
Člen | 910
+
0
-

Áno, nepoužiješ v ACL, ty ho musíš použiť napríklad v presenteri. Pre zamespečenie administrácie môžeš v BaseAdminPresenteri v startup metóde kontrolovat $this->user->isInRole(‚admin‘), ak je false tak zavoláš redirect na login stránku alebo na homepage frontendu.

masterr
Začátečník | 141
+
0
-

hmmm, ale já potřebuji ověřit jestli je na nějakém presenteru/akci, kde by být neměl a ne ho vždycky přesměrovat na login, to udělám jak?

Oli
Člen | 1215
+
0
-
function actionEdit($id)
{
	if ($this->user->isInRole(‚admin‘))
	{
		// Nějaká část, kterou může dělat jen admin
	}
	if ($this->getUser()->isLoggedIn())
	{
		// Část, kterou může dělat jen přihlášený uživatel
	}
	// Část, kterou může dělat uplně každý
}
Šaman
Člen | 2666
+
0
-

Ale lepší je používat

<?php
$this->user->isAllowed($resource, $privilege);
?>

a ono ti to vrátí TRUE, pokud aktuální uživatel má příslušné právo.

masterr
Začátečník | 141
+
0
-

Oli tvoje řešení mě napadlo jako první, ale chtěl jsem něco abych nemusel mít práva v jednotlivých presenterech a akcích, ale odděleně třeba v basePresenteru.

Šamane už jsem asi konečně pochopil, jak funguje tvoje řešení, který jsem chtěl už od začátku. Akorát mi není jasná jedna zásadní věc:

Nastavím si nějaký oprávnění pro uživatele, isAllowed() mi vrátí TRUE/FALSE, ale kde vezmu $resource, $privilege? Jak poznám kde se uživatel momentálně nachází a jakou používá akci? Abych si mohl ověřit jestli má na to práva.

Dík

Šaman
Člen | 2666
+
-1
-

Napíšu to zatím staticky, dynamicky by to bylo trochu obsáhlejší.

<?php
class AccessList extends Permission
{
	public function __construct()
	{
		/* seznam uživatelských rolí */
		$this->addRole('guest');
		$this->addRole('user');
		$this->addRole('admin', 'user');

		/* seznam zdrojů */
		$this->addResource('User');
		$this->addResource('Person');
		$this->addResource('Present');
		$this->addResource('Event');

		/* seznam pravidel oprávnění */
		$this->allow('user', array('Person', 'Present', 'Event'), 'list');
		...

		# admin má práva na všechno
		$this->allow('admin', self::ALL, self::ALL);
	}
}


//v configu si přidej službu
services:
	authorizator: MyApp\Model\Security\AccessList


//a v presenteru
$this->user->isAllowed('Person', 'list'); // u nepřihlášeného FALSE, jinak TRUE
?>

Víc o nastavování práv zjistíš v dokumentaci

Editoval Šaman (29. 7. 2013 20:58)

enumag
Člen | 2118
+
+3
-

@Šaman: Dědit Permission mi nepřipadá čísté.

<?php
namespace App;

use Nette\Security\Permission;

class AuthorizatorFactory
{

	/**
	 * @return \Nette\Security\IAuthorizator
	 */
	public function create()
	{
		$permission = new Permission();

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

		/* seznam zdrojů */
		$permission->addResource('User');
		$permission->addResource('Person');
		$permission->addResource('Present');
		$permission->addResource('Event');

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

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

		return $permission;
	}

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

Editoval enumag (11. 12. 2013 20:42)

Šaman
Člen | 2666
+
0
-

Je fakt, že moje řešení je staršího data a od é doby ho jen přetahuji na nové projekty. Koukal jsem, že se to mezitím změnilo i v té dokumentaci.
Ale proč by mělo být dědění v tomto případě nečisté? DI to neporušuje, pokud si chci mocknout vlastní ACL, tak mám možnost, takže nevidím problém.

enumag
Člen | 2118
+
0
-

@Šaman: Je to čistě můj osobní přístup. Dědičnost používám výhradně pokud do třídy chci přidat nové možnosti případně změnit stávající chování. Jde-li o konfiguraci konkrétní instance, používám raději továrnu. V podstatě je to totéž co David doporučuje tady aplikované i mimo formuláře.

Editoval enumag (29. 7. 2013 22:11)

masterr
Začátečník | 141
+
0
-

Dík, ale asi stejně nejde to, co jsem myslel. Nebo ne alespoň podle toho, co píšete.

Má představa byla, že si vytvořím list, kde budou napsaná práva pro přístup do presenteru a jeho metodám.
A nebudu muset vůbec do presenteru zasahovat. Že nette si to přelouská samo.

Takto budu muset mít vždycky v každé metodě v presenteru (ne v každé, stačí když to hodím do constructoru většinou)

//a v presenteru
$this->user->isAllowed('Person', 'list'); // u nepřihlášeného FALSE, jinak TRUE

Což není zrovna ,,cool", to se nedá udělat tak jak píšu?

David Matějka
Moderator | 6445
+
0
-

tohle se nejlepe resi v prepsane metode checkRequirements, Šaman tu nedavno posilal svoji implementaci

enumag
Člen | 2118
+
0
-

@masterr: Za prvé presenter není resource a action není privilege. Samozřejmě bys to tak mohl mohl velmi snadno používat pomocí metody checkRequirements, ale přímo v Nette to nemá co dělat.

EDIT: Pozdě. :-)

Editoval enumag (29. 7. 2013 22:46)

Šaman
Člen | 2666
+
0
-

Lehce offtopic, ale souvisí to s výše postnutým kódem od enumaga.
Ty to tam máš správně, ale já jsem zkoušel spoléhat v @return anotaci na znalost sekce use a narazil jsem.

<?php
namespace Annivers\Model\Security;

use Nette\Security\Permission,
	Nette\Security\IResource;


/**
 * Třída pro definování uživatelských práv
 */
class PermissionFactory
{

	/**
	 * Vytvoří a nastaví instanci Permission
	 *
	 * @return Permission  <=============
	 */
	public function createPermission()
	{
		$acl = new Permission;
		...
?>

Nejspíš je to poprvé, co return anotaci používám pro DI autowiring, ale ve všech ostatních případech ji mám bez namespace a napovídání v NetBeans funguje, takže jsem předpokládal, že i v anotacích se zohledňuje sekce use. Proč tomu zde tak není? Nedalo by se s tím něco dělat? (Když mám všechny použité třídy vypíchnuté v use sekci – jako seznam závislostí – tak pak nejsem v kódu zvyklý psát celé NS.)

Tak alespoň upozorňuji na tento problém, aby ho nemusel ladit každý znova.


enumag: A když už jsem offtopic, tak ještě jeden dotaz. Je někde sepsané, jak pracovat se sekcema (nebo prefixama, či jak se to mazývá) v configu? Jde mi o ten tvůj app.authorizator, konkrétně o předponu app.
Běžně jsem psal bez přepon a myslel jsem, že si container vyhledá službu authorizator. Teď jsem si uvědomil, že mu jde jen o typ (třída, rozhraní) a služba může být pojmenovaná jakkoliv. Ale ještě mi není jasné, jak se pracuje s těmi předponami – má to nějaký hlubší smysl, nebo je to jen optické rozdělení? Díky.

Editoval Šaman (30. 7. 2013 4:16)

enumag
Člen | 2118
+
0
-

@Šaman:

O use statementech se ví, že nefungují a je to v podstatě protože to ještě nikdo neimplementoval respektive nezahrnul do Nette (externí implementaci nad Nette jsem nedávno na GitHubu zahlédl).

EDIT: Mimochodem by bylo lepší tu továrnu nazvat jako AuthorizatorFactory a vracet IAuthorizator. Že je to Permission už nikoho zajímat nemusí, časem mohu použít jiný autorizátor.

Pokud jde o prefixy služeb (sekce jsou v souvislosti s configem ty věci jako development < common:, což je úplně něco jiného) tak je to čistě mé rozdělení. Přistupovat ke službě přes název je samozřejmě možné přes getService, považuji ale za mnohem rozumnější používat getByType když už nepoužiju inject. Pokud tohle tvá aplikace splňuje tak na názvy můžeš zapomentout a můžeš služby registrovat klidně i bez názvů. Ten můj app prefix je jen pro rozlišení služeb definovaných aplikací od služeb definovaných nějakým extension v debug baru. Tam se služby řadí dle abecedy takže mám služby aplikace pěkně na začátku.

EDIT: Koukám že už teď načítám asi 12 různých extensions, což znamená spoustu služeb. Ty prefixy mi jen umožňují mít v tom pořádek, jiný význam pro mne nemají.

Editoval enumag (30. 7. 2013 10:52)

masterr
Začátečník | 141
+
0
-

Dík, už mi to funguje.

enumag
Člen | 2118
+
0
-

@_enigma: Tohle nemá co dělat s ACL, založ nové vlákno. Obecně když máš nějaký problém je většinou lepší založit nové vlákno a případně uvést odkaz na staré kde se řešil podobný problém.

Tomáš Votruba
Moderator | 1114
+
0
-

K ACL existuje jednoduché demo na Planette: https://doc.nette.org/…thentication, včetně fčního dema.
Pull-requesty vítány :)

_enigma
Člen | 17
+
0
-

OK, díky za radu.

Vytvořil jsem nové téma.