Pozdní update práv při přihlášení

- maarlin
- Člen | 207
Mám napsaný authorization handler na přihlašování uživatelů s právy
a nějak nechápu důvod aktuálního řešení identity…
Po přihlášení se nastaví identita takto:
return new NIdentity($row->username, $row->role_key, $row);
Samozřejmě data o uživateli z té identity se používají v celé
aplikaci, ale neupdatují, resp. updatují až po
odhlášení/přihlášení.
Tedy pokud je uživatel přihlášen a někdo mu změní jeho úroveň
oprávnění (role_key), tak se tato změna nijak nepromítne… Leda bych si
připsal do BasePresenteru do startupu dotaz na aktuální role_key v databázi
a pak to updatnul pomocí getIdentity()->setRoles()… Jiné řešení asi
není, že?
Ovšem data o uživateli jako takovém se mi nijak nedaří updatovat… Co kdyby se user třeba překlepnul (ve jménu, příjmení, emailu… čemkoliv) a v databázi by došlo k opravě? Pak aby se to projevilo, musí provést relogin? To mi nepřijde ideální…
Řekněte mi někdo, že to řeším jinak, než bych měl a že to jde lépe… :)

- Aurielle
- Člen | 1281
Změnu práv neřeším (v mé aplikaci to bude hodně ojedinělý případ), ale identita se updatuje vždy, když si uživatel změní profil (samozřejmě vždy se změní i příslušný záznam v databázi):
/**
* Update user's identity
* @return void
*/
public static function updateIdentity($args)
{
$args = func_get_args();
if(sizeof($args) == 1)
{
if(is_array($args[0]))
{
foreach($args[0] as $col => $value)
{
Environment::getUser()->getIdentity()->$col = $value;
}
}
}
else if(sizeof($args) == 2)
{
Environment::getUser()->getIdentity()->$args[0] = $args[1];
}
else
{
throw new InvalidArgumentException("Arguments passed for " . __METHOD__ . "() are invalid.");
}
}
Editoval gmvasek (31. 12. 2009 20:58)

- Ondřej Mirtes
- Člen | 1536
Při změně práv v aplikaci můžeš ručně aktuální identitu změnit. Pokud ručně měníš DB, je to problém no :)

- Panda
- Člen | 569
Při změně práv v aplikaci se identita bude měnit docela těžko. Je to aplikovatelné jen na případ, kdy si uživatel mění práva sám sobě. Identity jiných uživatelů nemáš normálně k dispozici, protože se ukládají do session (a procházet serializované sessions a hledat tam identity onoho uživatele není úplně nejelegantnější).
Řešení tam ale je, napadla mě hned dvě.
První z nich je trochu univerzálnější. Spočívá ve vytvoření
vlastního globálního úložiště identit a podědění třídy
User tak, aby toto úložiště využívala – při přiřazení
identity uživateli (setIdentity()) by se identita neukládala
přímo do session, ale uložila by se do onoho globálního úložiště pod
nějakým klíčem (pozor, jeden uživatel může mít více identit, takže
klíče budou 2: uživatelské jméno a nějaké vygenerované UID) a až ten
pak uložit do session. V metodě getIdentity() by pak nová
třída User hledala novou identitu v globálním úložišti.
Toto úložiště by pak samozřejmě bylo dostupné kdekoliv v aplikaci a při
změně práv či profilu by šly údaje změnit pro všechny aktuální
identity uživatele.
Druhá se týká jen oprávnění s využitím třídy
Permission. Pro každého uživatele by do objektu
Permission vytvořila „pseudorole“ s jeho uživatelským
jménem, která by za rodiče měla všechny role daného uživatele (v Tvém
případě by ta role byla jen jedna – role_key z databáze).
Uživateli by se pak do identity nastavila tato „pseudorole“. Při změně
oprávnění by se invalidoval objekt Permission v cache a role by
se sestavily znovu – tentokrát by ale „pseudorole“ uživatele měla
jiné rodičovské role a tak by se promítla nová oprávnění. Aby se
předešlo velkému množství rolí v objektu „Permission“, šlo by
rozdělit jeho sestavování do 2 fází – sestavení obecného objektu
Permission (společný základ pro všechny uživatele) a
přidání oné „pseudorole“ pro každého uživatele zvlášť. Do cache by
se pak mohl uložit i objekt pro daného uživatele (samozřejmě pod pro něj
unikátním klíčem – uživatelské jméno) a nastavit mu závislost na
obecný objekt Permission v cache. Při invalidaci onoho obecného
objektu by se automaticky invalidovaly i objekty závislé a oprávnění by se
opět aktualizovala.