Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Using a Doctrine EventListener to keep a record from being returned?

X-BeenThere: dallasphp@googlegroups.com
Received: by 10.101.214.12 with SMTP id r12ls841211anq.0.p; Fri, 13 Nov 2009 
	11:38:37 -0800 (PST)
Received: by 10.101.164.25 with SMTP id r25mr4945140ano.14.1258141115662;
        Fri, 13 Nov 2009 11:38:35 -0800 (PST)
Received: by 10.101.164.25 with SMTP id r25mr4945139ano.14.1258141115629;
        Fri, 13 Nov 2009 11:38:35 -0800 (PST)
Return-Path: <jazzsli...@gmail.com>
Received: from mail-yw0-f158.google.com (mail-yw0-f158.google.com [209.85.211.158])
        by gmr-mx.google.com with ESMTP id 12si473482gxk.2.2009.11.13.11.38.35;
        Fri, 13 Nov 2009 11:38:35 -0800 (PST)
Received-SPF: pass (google.com: domain of jazzsli...@gmail.com designates 209.85.211.158 as permitted sender) client-ip=209.85.211.158;
Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of jazzsli...@gmail.com designates 209.85.211.158 as permitted sender) smtp.mail=jazzsli...@gmail.com
Received: by mail-yw0-f158.google.com with SMTP id 30so5488388ywh.25
        for <dallasphp@googlegroups.com>; Fri, 13 Nov 2009 11:38:35 -0800 (PST)
MIME-Version: 1.0
Received: by 10.101.84.2 with SMTP id m2mr195508anl.30.1258141115579; Fri, 13 
	Nov 2009 11:38:35 -0800 (PST)
Date: Fri, 13 Nov 2009 11:38:35 -0800 (PST)
X-IP: 76.237.224.134
User-Agent: G2/1.0
X-HTTP-UserAgent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_1; en-us) 
	AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9,gzip(gfe),gzip(gfe)
Message-ID: <e28f0447-8e55-4d5a-a487-0d273688129a@s31g2000yqs.googlegroups.com>
Subject: Using a Doctrine EventListener to keep a record from being returned?
From: jazzslider <jazzsli...@gmail.com>
To: DallasPHP <dallasphp@googlegroups.com>
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

Hello!

Gonna post this to the official Doctrine mailing list as soon as my
membership there is approved, but I figured since we talked about
Doctrine this past week it's fair game to ask here too :)

In one of my projects, I'm trying to do application-level access
control on my Doctrine models.  My access control system isn't
database-driven so I can't really include access control logic at the
query level =85as a result, I'm having to perform the checks after the
query has returned all its data, like so:

[code]
// for single records...
$record =3D $doctrineTable->find($id);
if (!$acl->isAllowed($role, $record, 'read')) {
    // Set $record to false so it will appear to later code
    // as though the requested record was not found.
    $record =3D false;
}

// for multiple records...
$records =3D $doctrineTable->findAll();
foreach ($records as $key =3D> $record) {
    if (!$acl->isAllowed($role, $record, 'read')) {
        // Remove the record from the collection so it will
        // not show up to later code.
        $records->remove($key);
    }
}
[/code]

Now, this works, but it gets pretty danged repetitive, and has a
tendency to muddy up my controller scripts significantly.  I'd much
rather allow the model layer to handle this directly, and after Jake's
presentation on Tuesday I realized that Doctrine's event and record
listeners might be able to help.

I've managed to get things working for other kinds of operations
(create, update, and delete) by using the preInsert(), preUpdate(),
and preDelete() methods of Doctrine_Record_Listener like so:

[code]
class My_Doctrine_Record_Listener_Acl extends Doctrine_Record_Listener
{
   public function __construct($acl, $currentRole);

   public function preInsert(Doctrine_Event $event)
   {
      $resource =3D $event->getInvoker();
      if (!$this->getAcl()->isAllowed($this->getCurrentRole(),
$resource, 'create')) {
         throw new My_Model_Exception('You are not allowed to do
that.');
      }
   }

   // and then preUpdate and preDelete too
}
[/code]

However, for the "read" operations in my first code sample, I'm having
trouble figuring out a couple of things.  First off, I'm not sure what
listener method to implement=85it's a bit difficult to tell which
listener is firing when, and the documentation is a bit terse.
Second, I'm not really sure what to do once I've got the listener
figured out =85the desired behavior is that if a record isn't allowed
for the role defined in the listener object, the table will simply
return whatever it would've returned if that record didn't even exist
in the first place.

I've tried this out in the Doctrine_Record_Listener::postHydrate()
hook, since I figured that would definitely get called for every
record returned by any given SELECT query =85but it doesn't always seem
to fire when I expect it to (e.g., if I call $table->findAll(), it
doesn't seem to be firing for the records being returned), and when it
does fire, I don't know how to tell it not to return the record=85maybe
set $event->data to NULL, or call $event->skipOperation()?

Anyway, I thought I'd go ahead and ask if anyone had run into this
kind of use case before, or if there's a better approach I'm not
considering.  Any ideas?

Thanks!
Adam