$acl autorizace – použití
- masterr
- Začátečník | 141
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?
- masterr
- Začátečník | 141
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 | 2659
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
@Š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 | 2659
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
@Š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
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
tohle se nejlepe resi v prepsane metode checkRequirements, Šaman tu nedavno posilal svoji implementaci
- Šaman
- Člen | 2659
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
@Š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)
- Tomáš Votruba
- Moderator | 1114
K ACL existuje jednoduché demo na Planette: https://doc.nette.org/…thentication,
včetně fčního dema.
Pull-requesty vítány :)