Nema problema, ali... zar ti nije malo prerano za listener-e?
No, evo primer:
Code:
public function setUp()
{
parent::setUp();
$this->actAs('Searchable', array(
'fields' => array( 'suburb', 'related_index') ));
$this->actAs(new Doctrine_Template_Timestampable()) ;
$this->actAs('Sluggable', array(
'unique' => true,
'fields' => array('title'),
'canUpdate' => true ));
$this->addListener( new PropertyListener() ) ;
$this->hasOne('User', array(
'local' => 'user_id',
'foreign' => 'id',
'onDelete' => 'CASCADE'
));
Ovo je samo
delic, klasa Property ima puno relacija. Obrati paznju na
$this->addListener( new PropertyListener() ) ; . Ona je:
Code:
class PropertyListener extends Doctrine_Record_Listener
{
/**
* If limited user access mode is on, patch called dql
*
* @param Doctrine_Event $event
*/
public function preDqlSelect(Doctrine_Event $event)
{
$q = $event->getQuery();
if ( PropertyTable::getInstance()->isAccessLimitedToLoggedUser() )
$q->addWhere('user_id=?', User::getLogged()->id) ;
}
}
Prvo, da ti pojasnim sta program radi. Administracija ima vise admina, svaki kreira Property-e za sebe. Uzmimo da admin Pera ima property-e ciji su id-evi 1,2 i 3. Admin Djoka ima Property-e 4, 5, 6.
Admin Djoka dobije listu svojih property-a sa url-om tipa ...edit.php?id=4 . Medjutim, on izmeni taj URL u edit.php?id=3 a nema dozvolu da vidi Perine property-e.
E sad; ovaj problem se moze resiti na vise nacina. Definitivno najlosiji je da u kontroleru proveravas to; prvo sto kontroler ne sme da ima nikakvu logiku (MVC), drugo sto bi isti kod ponavljao, trece lako je pogresiti itd. Na moj nacin, ja sam 'patchovao' svaki Query koji se izvrsi. Tj. bez obzira kakav query da napises, ti ili neko drugi, NIKAD se taj property nece ucitati. Jednostavno, na query object ($q) se nalepi dodatni uslov a to je da kolona user_id mora biti id ulogovanog korisnika.
Vrlo jednostavno, izuzetno mocno, i lep bonus od mog klijenta koji nije dosad video ovako nesto. Budi siguran da cu i od tebe traziti kompezaciju na kraju
Zahvaljuci ovom pristupu, moj kontroler izgleda ovako:
Code:
/**
* Set limited access to properties
* Logged super-admin doesn't have restrictions
*/
public function construct()
{
parent::construct() ;
PropertyTable::getInstance()->applyUserAccess(true) ;
}
public function index()
{
// do the magic of pagination
$this->assign('allObjects', parent::setPagination(PropertyTable::getInstance()->createQuery())) ;
}
public function add()
{
$object = new Property() ;
$object->user_id = User::getLogged()->id ; // @todo put in constructor of Property class
$this->assign('object',parent::formManager($object)) ;
}
public function edit($id)
{
$this->reportHackIf( !$object = PropertyTable::getInstance()->find($id) ) ;
$this->assign('object',parent::formManager($object)) ;
}
public function delete($id)
{
$this->reportHackIf( !$object = PropertyTable::getInstance()->find($id) ) ;
$this->assign('object', parent::delete($object)) ;
}
Znaci; u poredjenju sa svim kontrolerima koje sam ikada napravio, jedina razlika je ovo:
Code:
PropertyTable::getInstance()->applyUserAccess(true) ;
Jednom linijom koda sam totalno zastitio program od bilo kakvog neovlastenog pristupa. U Listener-u ti cak ni ne treba preUpdate() ili preDelete(); jednostavno, objekat se nece ni ucitati da bi neko mogao da ga menja ili obrise.
[Ovu poruku je menjao mitke013 dana 23.10.2010. u 00:18 GMT+1]