Při tvorbě assertion pro autorizaci se místo objektů vrací string
- Operator21
- Člen | 2
Zdravím, zkouším si vytvořit kontrolu oprávnění, konkrétně aby vlastník článku mohl daný článek odstranit aniž by mohl mazat ostatním, postupoval jsem podle dokumentace na https://doc.nette.org/…uthorization a zasekl jsem se u tvorby assertion.
use Nette\Security\Permission;
class AuthorizatorFactory {
const ROLE_ADMIN = "admin";
const ROLE_USER = "user";
const RESOURCE_ARTICLE = "article";
const RESOURCE_USER = "user";
const ACTION_CREATE = "create";
const ACTION_UPDATE = "update";
const ACTION_DELETE = "delete";
public static function create(): Permission {
$acl = new Permission();
// add resources
$acl->addResource(self::RESOURCE_USER);
$acl->addResource(self::RESOURCE_ARTICLE);
//add roles
$acl->addRole(self::ROLE_ADMIN);
$acl->addRole(self::ROLE_USER);
//admin has total control
$acl->allow(self::ROLE_ADMIN, self::RESOURCE_USER);
$acl->allow(self::ROLE_ADMIN, self::RESOURCE_ARTICLE);
//if user is author -> allow deletion
$assertion = function (Permission $acl, string $role, string $resource, string $privilege): bool {
$role = $acl->getQueriedRole();
$resource = $acl->getQueriedResource();
return $role->getId() === $resource->getOwner()->getId();
};
$acl->allow(self::ROLE_USER, self::RESOURCE_ARTICLE, self::ACTION_DELETE, $assertion);
return $acl;
}
}
Dostávám chybu:
Error: Call to a member function getId() on string in /app/app/Model/AuthorizatorFactory.php:32
Což je tato část
return $role->getId() === $resource->getOwner()->getId();
Logicky to na mě řve, že se snažím vyvolat funkci ze stringu, ale co jsem pochopil z toho stručného návodu v dokumentaci, tak metody getQueriedRole() a getQueriedResource() vrátí objekt podle funkcí getRoleId() respektivě getResourceId().
V třídách klasicky implementuju interface:
- User implementuje jak Role tak i Resource (doufám, že to je tak správně, pokud chci mít i správu uživatelů)
public function getRoleId(): string {
# role se získává z databáze, hodnoty jsou ekvivaletní konstantám v authorizátoru
return $this->role;
}
public function getResourceId(): string {
return AuthorizatorFactory::RESOURCE_USER;
}
- Article implementuje pouze Resource
public function getResourceId(): string {
return AuthorizatorFactory::RESOURCE_ARTICLE;
}
Pokud klasicky ověřím pomocí $user->isAllowed($otherUser) nebo $user->isAllowed($article) a $user má v tu chvíli roli admin, tak všechno funguje jak má, ale jakmile má roli user tak se to dostane k té chybě v assertion.
Procházel jsem si i dokumentaci api https://api.nette.org/…mission.html#… ale o moc víc informací mi to neposkytlo.
Věděl by někdo co dělám špatně?
- dakur
- Člen | 493
Co je špatně, to nevím, ale můžeš zjistit, že jestli se ta chyba
týká $role->getId()
nebo
$resource->getOwner()->getId()
(obojí má
getId()
). Pak se můžeš podívat, co je v tom teda za string a
proč tam není objekt (prokliknutím do dané metody/proměnné).
Editoval dakur (23. 6. 2022 10:05)
- Operator21
- Člen | 2
Vyřešil jsem to, jakmile se používá funkce $user->isAllowed($article), tak $article se sice předá jako instance na objekt, ovšem $user už ne, podle mě se předá pouze role z identity a o objektu se už neví.
Vytvořil jsem si tedy statickou referenci na $acl v AuthorizationFactory
(přiřazuju si ji těsně před return $acl) a na tu si šahám v presenteru,
kde ji používám pomocí
$acl->isAllowed($loggedUser, $article, "delete")
, kde
$loggedUser je instance objektu User získaná pomocí id v identitě. Jestli
to je ideální řešení nevím, ale je funkční.