ACL = Access Control List je SEZNAM – jak získat seznam toho co uživatel může?
- Honza Kuchař
- Člen | 1662
Ahoj,
netušíte někdo prosím vás, jak dostat z jinak perfektní třídy
Permission
seznam toho, co uživatel může.
Potřebuji takovýto seznam dopravit na klienta, kde se podle něj vygeneruje
GUI. Je to možné? Byla by škoda, jednou ládovat data do třídy
Permission
a pak dělat další vlastní implementaci na získání
toho seznamu.
Výsledek by měl vypadat, jako přehled zdrojů a privilegií nad nimi. V případě, že uživatel může nad něčím vše, použije se hvězdička, či se nějak jinak označí.
Pěkný večer všem zde přeje,
Honza Kuchař
- Filip Procházka
- Moderator | 4668
ACL máš pravděpodobně někde uložené, je tak?
Do Permissions to musíš načíst pokaždé po startu znova (cachování na tom
nic nemění)
Takže máš někde uloženej strom závislostí s Resources, Roles a
Privileges
proč to teda nevygeneruješ z toho? je to 1 max 3 SQL, popř si extendnout Permissions a udělat tam jednoduchou funkci na vycucnutí cache
- Honza Kuchař
- Člen | 1662
Ono to s tím vytažením z databáze, zase tak jednoduché není. Zdroje a role mají dodiče, tedy jsou dědičné…
A z Permission cache „vycucnout“ nejde, protože je
private
.
PS: Tady ten „seznam“ toho, co uživatel může, by asi měl souviset s
Identity
, protože se generuje pro uživatele…
- Filip Procházka
- Moderator | 4668
myslím že v to hledáš moc vědu :)
inspiroval bych se tady
https://forum.nette.org/…control-list
+pár podmínek vyřeší filtr pro uživatele
- Honza Kuchař
- Člen | 1662
Ano, ano, vyšel jsem z toho a myslím, že jsem na správné cestě. Akorát tedy nevím, když mám třeba třicet zdrojů a pět privilegií = 150 výsledků, to je docela dost. Ale co, pravda, načítá se to jen při přihlášení uživatele… :) Pak sem dám, to co jsem tedy upravil. :)
- Honza Kuchař
- Člen | 1662
AccessSumaryModel
class AccessSummaryModel extends Object {
/** @var array */
private $summary = array();
/**
* @param array Array of roles
*/
public function __construct(array $roles) {
$aclModel = new AclModel();
$resources = $aclModel->getResources();
$privileges = $aclModel->getPrivileges();
$acl = Environment::getService("Nette\Security\IAuthorizator");
$i = 0;
foreach ($resources as $res) {
$res_array = array();
foreach ($privileges as $pri) {
foreach ($roles as $role) {
if ($acl->isAllowed($role, $res->name, $pri->name)) {
$res_array[] = $pri->name;
break 1; // Další privilegium...
}
}
}
if(count($res_array) < 1) continue;
if(count($res_array) == count($privileges)) {
$res_array = "*";
}
$this->summary[$res->name] = $res_array;
}
}
/**
* @return array Resources and privileges for current roles
*/
public function getAccess() {
return $this->summary;
}
}
AclModel (komunikace s databází)
class AclModel extends Object {
const ACL_TABLE = 'ACL';
const PRIVILEGES_TABLE = 'Privilegia';
const RESOURCES_TABLE = 'Zdroje';
const ROLES_TABLE = 'Role';
public function getRoles() {
return dibi::fetchAll('SELECT `r1`.`KlicovyNazev` AS `name`, `r2`.`KlicovyNazev` as `parent_name`
FROM [' . self::ROLES_TABLE . '] AS `r1`
LEFT JOIN [' . self::ROLES_TABLE . '] AS `r2` ON (`r1`.`IdRodice` = `r2`.`IdRole`)
ORDER BY `r1`.`IdRole`
');
}
public function getResources() {
return dibi::fetchAll('SELECT `r1`.`KlicovyNazev` AS `name`, `r2`.`KlicovyNazev` as `parent_name`
FROM [' . self::RESOURCES_TABLE . '] AS `r1`
LEFT JOIN [' . self::RESOURCES_TABLE . '] AS `r2` ON (`r1`.`IdRodice` = `r2`.`IdZdroje`)
ORDER BY `r1`.`IdZdroje`');
}
public function getPrivileges() {
return dibi::fetchAll('SELECT `r1`.`KlicovyNazev` AS `name`
FROM [' . self::PRIVILEGES_TABLE . '] AS `r1`
ORDER BY `r1`.`IdPrivilegia`
');
}
public function getRules() {
$q = dibi::query('
SELECT
`a`.`Povolit` as `allowed`,
`ro`.`KlicovyNazev` AS `role`,
`re`.`KlicovyNazev` AS `resource`,
`p`.`KlicovyNazev` AS `privilege`
FROM [' . self::ACL_TABLE . '] AS `a`
JOIN [' . self::ROLES_TABLE . '] AS `ro` ON (`a`.`IdRole` = `ro`.`IdRole`)
LEFT JOIN [' . self::RESOURCES_TABLE . '] AS `re` ON (`a`.`IdZdroje` = `re`.`IdZdroje`)
LEFT JOIN [' . self::PRIVILEGES_TABLE . '] AS `p` ON (`a`.`IdPrivilegia` = `p`.`IdPrivilegia`)
/*ORDER BY `a`.`Id` ASC*/
');
$q->setType('access', Dibi::BOOL);
return $q->fetchAll();
}
}
Authorizator
class Authorizator extends 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, $resource->parent_name);
foreach($model->getRules() as $rule)
$this->{$rule->allowed == true ? 'allow' : 'deny'}($rule->role, $rule->resource, $rule->privilege);
}
}
Výsledek (souhrn práv uživatele):
{
"studio": [
"zobrazit"
],
"vyroba": [
"zobrazit"
],
"zakazkaZakladni": "*",
"zakazkaPokrocila": "*"
}