Zend_Acl and pagination

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Zend_Acl and pagination

jazzslider
Hello!

Got an interesting problem I was hoping some of you could help me with.  I'm trying to figure out the best way to do result set pagination in combination with Zend_Acl-based access control.  Let me explain…

Start with the following assumptions:

1. You have a database table containing 500 or so blog posts.
2. One of the resources set up in your Bootstrap class is a Zend_Acl object, containing all the rules you'll need to control access to those blog posts.  Some of these rules might be based on stuff in the database, but some of them might not be…the ACL object controls all that.
3. You want to set up a paginated listing view for your blog posts; each page is to list exactly 10 posts, and contain pagination links to get to all the other pages.

So, in the action method for that listing view, we do the following:

1. Pull the models in by database query (really, the query would probably be in a service layer rather than hard-coded into the action, but for this example that's not really important)
2. Loop through the result set and check each result against the ACL object to see if it's allowed for the current user; if not, remove it from the result set.
3. Pass the adjusted result set to the view for rendering.

Suppose, however, that of the 10 results we get back, 3 of them aren't permissible for the current user.  That means we're only left with 7 results to show, when the user is expecting 10.  Or, suppose that of the 10 results, all 10 are impermissible…in that case, the user sees nothing but a set of pagination links, with no guarantee that any of the links will lead to better results.

Now, one possible solution here would be to adjust the database query to account for access control, but then we'd have to maintain access control logic in two places: the ACL and the database query itself.  Plus, if the ACL object is basing its rules on information not found in the database (dunno how realistic that is, but I'm exploring all angles), we can't take this approach at all.

So the problem in a nutshell is this: how can I ensure a paginated result set of exactly 10 items per page when the access control is handled outside of the database query?

Thanks!
Adam Jensen
Reply | Threaded
Open this post in threaded view
|

Re: Zend_Acl and pagination

Matthew Ratzloff
Hi Adam,

I'd store an array representation of the result set in memory (memcache or similar) and apply the ACL rules against the cached array, generating a new array you can paginate.  Cache this new array with an ID that is easily recoverable.

{{{
if specific array does not exist in memcache
    if raw array does not exist in memcache
        query database
        store array in memcache
    end if

    create specific array from filtered raw array
    store specific array
end if

return specific array
}}}

-Matt

On Fri, Sep 4, 2009 at 5:55 AM, Adam Jensen <[hidden email]> wrote:
Hello!

Got an interesting problem I was hoping some of you could help me with.  I'm trying to figure out the best way to do result set pagination in combination with Zend_Acl-based access control.  Let me explain…

Start with the following assumptions:

1. You have a database table containing 500 or so blog posts.
2. One of the resources set up in your Bootstrap class is a Zend_Acl object, containing all the rules you'll need to control access to those blog posts.  Some of these rules might be based on stuff in the database, but some of them might not be…the ACL object controls all that.
3. You want to set up a paginated listing view for your blog posts; each page is to list exactly 10 posts, and contain pagination links to get to all the other pages.

So, in the action method for that listing view, we do the following:

1. Pull the models in by database query (really, the query would probably be in a service layer rather than hard-coded into the action, but for this example that's not really important)
2. Loop through the result set and check each result against the ACL object to see if it's allowed for the current user; if not, remove it from the result set.
3. Pass the adjusted result set to the view for rendering.

Suppose, however, that of the 10 results we get back, 3 of them aren't permissible for the current user.  That means we're only left with 7 results to show, when the user is expecting 10.  Or, suppose that of the 10 results, all 10 are impermissible…in that case, the user sees nothing but a set of pagination links, with no guarantee that any of the links will lead to better results.

Now, one possible solution here would be to adjust the database query to account for access control, but then we'd have to maintain access control logic in two places: the ACL and the database query itself.  Plus, if the ACL object is basing its rules on information not found in the database (dunno how realistic that is, but I'm exploring all angles), we can't take this approach at all.

So the problem in a nutshell is this: how can I ensure a paginated result set of exactly 10 items per page when the access control is handled outside of the database query?

Thanks!
Adam Jensen

Reply | Threaded
Open this post in threaded view
|

Re: Zend_Acl and pagination

jazzslider
Interesting…I hadn't thought to apply caching in that way; good call.  Allows me to do all the access control at the application level rather than tying it to the database, which is exactly what I wanted. 

The one downside, I suppose, is that the unlucky user who hits the site when neither cache has been generated yet will have to wait quite awhile, especially if there are lots of posts in the database, since that initial query doesn't have the benefit of pagination at all.  I suppose I could try to grab that request via a cron job periodically so that it didn't have to affect any live users.

Anyway, thanks for your help!
Adam


On Fri, Sep 4, 2009 at 12:20 PM, Matthew Ratzloff <[hidden email]> wrote:
Hi Adam,

I'd store an array representation of the result set in memory (memcache or similar) and apply the ACL rules against the cached array, generating a new array you can paginate.  Cache this new array with an ID that is easily recoverable.

{{{
if specific array does not exist in memcache
    if raw array does not exist in memcache
        query database
        store array in memcache
    end if

    create specific array from filtered raw array
    store specific array
end if

return specific array
}}}

-Matt

On Fri, Sep 4, 2009 at 5:55 AM, Adam Jensen <[hidden email]> wrote:
Hello!

Got an interesting problem I was hoping some of you could help me with.  I'm trying to figure out the best way to do result set pagination in combination with Zend_Acl-based access control.  Let me explain…

Start with the following assumptions:

1. You have a database table containing 500 or so blog posts.
2. One of the resources set up in your Bootstrap class is a Zend_Acl object, containing all the rules you'll need to control access to those blog posts.  Some of these rules might be based on stuff in the database, but some of them might not be…the ACL object controls all that.
3. You want to set up a paginated listing view for your blog posts; each page is to list exactly 10 posts, and contain pagination links to get to all the other pages.

So, in the action method for that listing view, we do the following:

1. Pull the models in by database query (really, the query would probably be in a service layer rather than hard-coded into the action, but for this example that's not really important)
2. Loop through the result set and check each result against the ACL object to see if it's allowed for the current user; if not, remove it from the result set.
3. Pass the adjusted result set to the view for rendering.

Suppose, however, that of the 10 results we get back, 3 of them aren't permissible for the current user.  That means we're only left with 7 results to show, when the user is expecting 10.  Or, suppose that of the 10 results, all 10 are impermissible…in that case, the user sees nothing but a set of pagination links, with no guarantee that any of the links will lead to better results.

Now, one possible solution here would be to adjust the database query to account for access control, but then we'd have to maintain access control logic in two places: the ACL and the database query itself.  Plus, if the ACL object is basing its rules on information not found in the database (dunno how realistic that is, but I'm exploring all angles), we can't take this approach at all.

So the problem in a nutshell is this: how can I ensure a paginated result set of exactly 10 items per page when the access control is handled outside of the database query?

Thanks!
Adam Jensen


Reply | Threaded
Open this post in threaded view
|

Re: Zend_Acl and pagination

Matthew Ratzloff
Hi Adam,

That sounds like it may be premature optimization.  If you find while
testing that it is a problem, however, create a script that generates
lists for each role and kick it off synchronously when an article is
created or deleted.

-Matt

On Friday, September 4, 2009, Adam Jensen <[hidden email]> wrote:

> Interesting…I hadn't thought to apply caching in that way; good call.  Allows me to do all the access control at the application level rather than tying it to the database, which is exactly what I wanted.
>
> The one downside, I suppose, is that the unlucky user who hits the site when neither cache has been generated yet will have to wait quite awhile, especially if there are lots of posts in the database, since that initial query doesn't have the benefit of pagination at all.  I suppose I could try to grab that request via a cron job periodically so that it didn't have to affect any live users.
>
> Anyway, thanks for your help!
> Adam
>
>
> On Fri, Sep 4, 2009 at 12:20 PM, Matthew Ratzloff <[hidden email]> wrote:
> Hi Adam,
> I'd store an array representation of the result set in memory (memcache or similar) and apply the ACL rules against the cached array, generating a new array you can paginate.  Cache this new array with an ID that is easily recoverable.
>
>
> {{{if specific array does not exist in memcache    if raw array does not exist in memcache        query database        store array in memcache    end if
>
>
>     create specific array from filtered raw array    store specific arrayend if
> return specific array}}}
> -Matt
>
>
> On Fri, Sep 4, 2009 at 5:55 AM, Adam Jensen <[hidden email]> wrote:
>
>
> Hello!
>
> Got an interesting problem I was hoping some of you could help me with.  I'm trying to figure out the best way to do result set pagination in combination with Zend_Acl-based access control.  Let me explain…
>
> Start with the following assumptions:
>
> 1. You have a database table containing 500 or so blog posts.
> 2. One of the resources set up in your Bootstrap class is a Zend_Acl object, containing all the rules you'll need to control access to those blog posts.  Some of these rules might be based on stuff in the database, but some of them might not be…the ACL object controls all that.
> 3. You want to set up a paginated listing view for your blog posts; each page is to list exactly 10 posts, and contain pagination links to get to all the other pages.
>
> So, in the action method for that listing view, we do the following:
>
> 1. Pull the models in by database query (really, the query would probably be in a service layer rather than hard-coded into the action, but for this example that's not really important)
> 2. Loop through the result set and check each result against the ACL object to see if it's allowed for the current user; if not, remove it from the result set.
> 3. Pass the adjusted result set to the view for rendering.
>
> Suppose, however, that of the 10 results we get back, 3 of them aren't permissible for the current user.  That means we're only left with 7 results to show, when the user is expecting 10.  Or, suppose that of the 10 results, all 10 are impermissible…in that case, the user sees nothing but a set of pagination links, with no guarantee that any of the links will lead to better results.
>
> Now, one possible solution here would be to adjust the database query to account for access control, but then we'd have to maintain access control logic in two places: the ACL and the database query itself.  Plus, if the ACL object is basing its rules on information not found in the database (dunno how realistic that is, but I'm exploring all angles), we can't take this approach at all.
>
> So the problem in a nutshell is this: how can I ensure a paginated result set of exactly 10 items per page when the access control is handled outside of the database query?
>
> Thanks!
> Adam Jensen
>
>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Zend_Acl and pagination

Matthew Ratzloff
Of course I meant asynchronously, not synchronously.

-Matt

On Friday, September 4, 2009, Matthew Ratzloff <[hidden email]> wrote:

> Hi Adam,
>
> That sounds like it may be premature optimization.  If you find while
> testing that it is a problem, however, create a script that generates
> lists for each role and kick it off synchronously when an article is
> created or deleted.
>
> -Matt
>
> On Friday, September 4, 2009, Adam Jensen <[hidden email]> wrote:
>> Interesting…I hadn't thought to apply caching in that way; good call.  Allows me to do all the access control at the application level rather than tying it to the database, which is exactly what I wanted.
>>
>> The one downside, I suppose, is that the unlucky user who hits the site when neither cache has been generated yet will have to wait quite awhile, especially if there are lots of posts in the database, since that initial query doesn't have the benefit of pagination at all.  I suppose I could try to grab that request via a cron job periodically so that it didn't have to affect any live users.
>>
>> Anyway, thanks for your help!
>> Adam
>>
>>
>> On Fri, Sep 4, 2009 at 12:20 PM, Matthew Ratzloff <[hidden email]> wrote:
>> Hi Adam,
>> I'd store an array representation of the result set in memory (memcache or similar) and apply the ACL rules against the cached array, generating a new array you can paginate.  Cache this new array with an ID that is easily recoverable.
>>
>>
>> {{{if specific array does not exist in memcache    if raw array does not exist in memcache        query database        store array in memcache    end if
>>
>>
>>     create specific array from filtered raw array    store specific arrayend if
>> return specific array}}}
>> -Matt
>>
>>
>> On Fri, Sep 4, 2009 at 5:55 AM, Adam Jensen <[hidden email]> wrote:
>>
>>
>> Hello!
>>
>> Got an interesting problem I was hoping some of you could help me with.  I'm trying to figure out the best way to do result set pagination in combination with Zend_Acl-based access control.  Let me explain…
>>
>> Start with the following assumptions:
>>
>> 1. You have a database table containing 500 or so blog posts.
>> 2. One of the resources set up in your Bootstrap class is a Zend_Acl object, containing all the rules you'll need to control access to those blog posts.  Some of these rules might be based on stuff in the database, but some of them might not be…the ACL object controls all that.
>> 3. You want to set up a paginated listing view for your blog posts; each page is to list exactly 10 posts, and contain pagination links to get to all the other pages.
>>
>> So, in the action method for that listing view, we do the following:
>>
>> 1. Pull the models in by database query (really, the query would probably be in a service layer rather than hard-coded into the action, but for this example that's not really important)
>> 2. Loop through the result set and check each result against the ACL object to see if it's allowed for the current user; if not, remove it from the result set.
>> 3. Pass the adjusted result set to the view for rendering.
>>
>> Suppose, however, that of the 10 results we get back, 3 of them aren't permissible for the current user.  That means we're only left with 7 results to show, when the user is expecting 10.  Or, suppose that of the 10 results, all 10 are impermissible…in that case, the user sees nothing but a set of pagination links, with no guarantee that any of the links will lead to better results.
>>
>> Now, one possible solution here would be to adjust the database query to account for access control, but then we'd have to maintain access control logic in two places: the ACL and the database query itself.  Plus, if the ACL object is basing its rules on information not found in the database (dunno how realistic that is, but I'm exploring all angles), we can't take this approach at all.
>>
>> So the problem in a nutshell is this: how can I ensure a paginated result set of exactly 10 items per page when the access control is handled outside of the database query?
>>
>> Thanks!
>> Adam Jensen
>>
>>
>>
>>
>