Fork me on GitHub

Caching circumvents permissions?  Bottom

  • Hi, I'm just upgrading a custom module of mine to including caching etc. I'm not that experienced or anything but it seems to me that the why caching is dealt with in the "Example" module circumvents the permissions for the item?

    Code

    // Create output object - this object will store all of our output so that
        // we can return it easily when required
        $pnRender =& new pnRender('Example');
       
        // For caching reasons you must pass a cache ID. This could be done as a
        // separate parameter to every method that uses caching (like fetch, is_cached
        // etc.) or by assigning the ID to the cache_id property like it is done in
        // this case.
        // The item ID is appropriate to be used as the cache ID.
        $pnRender->cache_id = $tid;
       
        // check out if the contents are cached.
        // If this is the case, we do not need to make DB queries.
        // Note that we print out "cached:" in front of a chached output --
        // of course, this is here to illustrate caching and needs to be removed!
        if ($pnRender->is_cached('example_user_display.htm')) {
           return 'cached:' . $pnRender->fetch('example_user_display.htm');
        }

        // The API function is called.  The arguments to the function are passed in
        // as their own arguments array
        $item = pnModAPIFunc('Example',
                             'user',
                             'get',
                             array('tid' => $tid));


    In the above code the items permissions are checked in the API function. This happens after the caching check. From my understanding if someone with permissions accesses the item it is cached. Then, when someone without permissions accesses the item it is retrieved from the cache, despite them not having permissions!

    How can this be fixed? I can't check ther permissions first as I don't have the item name, just its ID. So to get the name I'd need to call the DB, which kinda defeats the whole point of caching it in the first place...?

    If anyone can explain this to me I'd appreciate it...
    Thanks icon_smile



    edited by: adamjjackson, Aug 10, 2006 - 07:23 PM
  • I this case what you really want to do is cache the lookup result data instead of the form. The cached data can then be retrieved and the appropriate permissions applied.

    Curt
  • Okay thanks. How do you just cache the result data tho?

    I thought another option would be to change the permissions structure so it only uses the item ID? Unless there is an important reason why modules tend to use item name AND id for the permissions?

    -Adam



    edited by: adamjjackson, Aug 10, 2006 - 10:28 PM
  • To cache the data only you have to decide on a format. 2 possibilities are XML or a hash table that can be serialized/unserialized. The Smarty template is simple - only needs a single variable to hold the cache data, don't forget the cache_id. When cached data is fetched, the data is decoded and the used as if it was retrieved via SQL.

    This could also be done with simple files but then you would have to write the code to determine if the data is cached, expired, etc.

    Curt
  • Hi again, sorry but I don't follow. I've looked at the Smarty docs. I understand about caching my displayed output by using fetch etc, but I can't simply substitute my .htm filename for a variable can I?

    -Adam
  • Here is the Smarty template I use to cashe XML text. I used XML because that is the way I receive it.

    Code

    <!--[*
    ** currencyexchangedata.htm
    ** Inputs:
    **   $content
    **
    *]--><!--[$content]--><!--[* xml text *]-->


    Everything except '$content' is Smarty comments. '$content' is set to the XML text I retrieved. The caching is handled just like a form except when I fetch the cached data I get XML text.

    If you download RemoteBlock from the NOC you can see all of this code in the 'currencyexchange' block.

    Curt
  • Okay will do, thanks for your help icon_smile

    [Great, I've got it sorted now, that's a useful little technique. Nevertheless, I think the code in the "Example" module is flawed...
    Thanks again]



    edited by: adamjjackson, Aug 11, 2006 - 11:10 AM
  • I agree that the 'Example' module is flawed in it's caching logic.

    A couple of other things to think about:
    1. Make sure the retieval process warrents caching. For a simple query you could spend more time caching than just executing the query.
    2. Cache the data in it's rawest and most complete form so that it may be used by more than 1 request type. For example, if different data is displayed depending on whether or not a person is logged in, try to use 1 cache record for both requests.
    3. Smarty will sometimes add unexpected whitespace before/after the cached text. This could cause problems when you are pulling data out of the cache.
    4. Take care not to cache 'bad' results (eg. temporary DB connection problem).

    Curt



    edited by: ctimmer, Aug 14, 2006 - 12:29 PM

This list is based on users active over the last 60 minutes.