dynamická správa rolí a nastavení config.neon

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

Vím že se to tu již dost řešilo a taky jsem dost našel ale nikde jsem nenašel kam nejlépe umístit ony soubory vytvořené na základě návodu "":https://doc.nette.org/…oli-a-zdroju
Podle dokumentace jsem si vytvořil vlastní autentikátor ale nevím jak zapsat acl do congif.neon
Již tam mám toto:authenticator:
class: Authenticator

Takže když to shrnu chtěl bych klidně i v bodech vědět: 1) Kam umístit Acl.php a AclModel.php podle odkazu výše. 2) Jak vše registrovat v config.neon
Poradíte někdo pls? Snad jsem to tu někde nepřehlédl.
Díky moc

bojovyletoun
Člen | 667
+
0
-

vytvořil bych si třeba továrnu, a do configu to zapsal takto. Ještě je třeba dolat věci jako dědičnost atd. V příkladu počítám s tím, že si do configu třeba budeš psát jen role, zbytek zůstává. Zatím to nedává moc smysl, ale nápad je snad jasný, jak předat parametry do továrny.

	function createAuth($class,$roles)
	{
		$q=new $class;
		foreach ($roles as $value) {
			$q->addRole($value)
		}
		// konfigurace
		přidat resource a povolit
		return $q;
	}


}

+config

services:
	authorizator:
		factory: createauth
		arguments:
			- \Nette\Security\Permission
			- [admin,user]

Editoval bojovyletoun (1. 12. 2011 0:57)

spiider
Člen | 162
+
0
-

Role bych do configu nechtel psat, ty chci mit ulozene v DB, přesně jako v ukázkovém příkladu. Mám zatím vytvořeny dva soubory Acl.php který obsahuje toto:

class Acl extends \Nette\Security\Permission{
    public function __construct() {
        $model = new \AclModel();

        foreach($model->getRoles() as $role)
            $this->addRole($role->name, $role->parent_name);

        foreach($model->getResources() as $resource)
            $this->addResource($resource->name);

        foreach($model->getRules() as $rule)
            $this->{$rule->allowed == 'Y' ? 'allow' : 'deny'}($rule->role, $rule->resource, $rule->privilege);
    }
}

a soubor AclModel.php který osahuje toto:

class AclModel extends Nette\Object {

    const ACL_TABLE = 'acl';
    const PRIVILEGES_TABLE = 'privileges';
    const RESOURCES_TABLE = 'resources';
    const ROLES_TABLE = 'roles';

    public function getRoles() {
        return dibi::fetchAll('SELECT r1.name, r2.name as parent_name
                               FROM ['. self::ROLES_TABLE . '] r1
                               LEFT JOIN ['. self::ROLES_TABLE . '] r2 ON (r1.parent_id = r2.id)
                              ');
    }

    public function getResources() {
        return dibi::fetchAll('SELECT name FROM ['. self::RESOURCES_TABLE . '] ');
    }

    public function getRules() {
        return dibi::fetchAll('
            SELECT
                a.allowed as allowed,
                ro.name as role,
                re.name as resource,
                p.name as privilege
                FROM [' . self::ACL_TABLE . '] a
                JOIN [' . self::ROLES_TABLE . '] ro ON (a.role_id = ro.id)
                LEFT JOIN [' . self::RESOURCES_TABLE . '] re ON (a.resource_id = re.id)
                LEFT JOIN [' . self::PRIVILEGES_TABLE . '] p ON (a.privilege_id = p.id)
                ORDER BY a.id ASC
        ');
    }
}

Kam tyto dva soubory nejlepe umístit? snazil jsem se vyčíst i něco z návodu na statické role a tam je, že se má vytvořit složka v libs/Acl a tam umístit soubor

A jak správně tyto soubory zaregistrovat v configu?
Popř. máte někdo jiné řešení?
Díky

bojovyletoun
Člen | 667
+
0
-

jo aha, ty už máš vše hotové a jde jenom o to, do které složky uložiz.
Předpokládám, že ti běží RobotLoader, takže to dej do nějaké složky kam vidí robotloader – defaultně prohledává libsDir a appDir (/app) – takže do složky app/services třeba – oboje soubory přičemž do ještě musíš nějak sdělit, že službu authorizator tvoří třída Acl. Možností máš několik, třeba v bootstrap.php zavolat $container->addService('authorizator',new Acl); nebo do configu:

services:
	auhorizator: Acl
spiider
Člen | 162
+
0
-

OK to mě už nejspíš funguje a teď teda stačí udělat něco takového do každého presenteru ke každé akci??

$acl = new Acl();
if ($acl->isAllowed('nejaka role', 'presenter', 'akce')){

}else{
     $this->flashMessage('Nemáte oprávnění pro zobrazení této stránky');
}

díky

JuniorJR
Člen | 181
+
0
-

@spiider: No, lepší než to dávat ke každé akci, tak si to hoď v univerzální podobě do startup() a ještě lépe do nějakého SecuredPresenteru, od kterého budeš pak dědit dále všechny presentery, které mají být zabezpečené :)

class SecuredPresenter extends BasePresenter
{
    protected function startup()
    {
        if ($this->user->isAllowed($this->name, $this->action)) {
            ...
        } else {
            $this->flashMessage('Action not allowed.');
        }
    }
}

Editoval JuniorJR (1. 12. 2011 15:16)

bojovyletoun
Člen | 667
+
0
-

spider: ta ukázka se mi moc nelíbí. 1) $acl = new Acl(); je pohřbení DI pro získání autorizatoru použij $this->context->authorizator
Ohledně toho zbytku, furt vypisovat zjistíš, že je to nuda. Říkáš, že kontroluješ u akcí, tak by se hodilo v Basepresenteru přepsat metodu checkRequirements.co tahle metoda dělá? je volána před každou akcí a render a jejím úkolem je tedy vyhodit vyjímku, pokud user nemá práva.

Podívej se „https://api.nette.org/nette/2.0/source-Application.UI.Presenter.php.html#265“ – tahle metoda dělá podobnou věc, jen místo pro akce je volána pro presenter. Této funkci checkrequirements je předána reflection volané metody. TO že si ji můžeš přepsat sám, ti dá volnost. Můžeš kontrolovat úplně každou metodu nebo jen pokud má anotaci. Zároveň nemusíš ani nijak uvádět jméno to se zjistí z reflection.

Dost řečí, ukázka řekne víc. Související téma

public function checkRequirements($refl)
{
	$act = substr($refl->name, 6); //uřízne 'action'
	if ($refl->getAnnotation('auth') && !$this->presenter->user->isAllowed($act)) {
		throw new Application\ForbiddenRequestException;
	}
}
/** @auth */
function action FormatDisk($ip){}

Editoval bojovyletoun (1. 12. 2011 19:35)