Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best action persistence technique for a Catalyst application?

Tags:

I'm writing a Catalyst application that's required to have a fairly short session expiration (15 minutes). I'm using the standard Catalyst framework authentication modules, so the user data is stored in the session -- i.e., when your session expires, you get logged out.

Many of the uses of this application will require >15 minutes to complete, so users will frequently submit a form only to find their session state is gone and they're required to log back in.

If this happens I want to preserve the original form submission, and if they log in successfully, continue on and carry out the form submission just as if the session had not expired.

I've got the authentication stuff being handled by an auto() method in the controller -- if you request an action that requires authentication and you're not currently logged in, you get redirected to the login() method, which displays the login form and then processes it once it's submitted. It seems like it should be possible to store the request and any form parameters when the auto method redirects to the login(), and then pull them back out if the login() succeeds -- but I'm not entirely sure of the best way to grab or store this information in a generic/standard/reusable way. (I'm figuring on storing it in the session and then deleting it once it's pulled back out; if that seems like a bad idea, that's something else to address.)

Is there a standard "best practices" or cookbook way to do this?

(One wrinkle: these forms are being submitted via POST.)

like image 640
genehack Avatar asked Jan 06 '09 22:01

genehack


1 Answers

I can't help thinking that there's a fundamental flaw in mandating a 15 minute timeout in an app that routinely requires >15 minutes between actions.

Be that as it may, I would look at over-riding the Catalyst::Plugin::Session->delete_session method so that any contents of $c->request->body_parameters are serialised and saved (presumably to the database) for later recovery. You would probably want some rudimentary check of the POST arguments to ensure they're what you're expecting.

Similarly, create_session needs to take responsibility for pulling this data back out of the database and making it available to the original form action.

It does seem like a messy situation, and I'm inclined to repeat my first sentence...

UPDATE:

Whether you use delete_session or auto, the paradoxical issue remains: you can't store this info in the session because the time-out event will destroy the session. You've got to store it somewhere more permanent so it survives the session re-initialization. Catalyst::Plugin::Session itself is using Storable, and you should be able to with something along these lines:

use Storable;
...
sub auto {
    ...
    unless (...) { #ie don't do this if processing the login action
        my $formitems = freeze $c->request->body_parameters;
        my $freezer = $rs->update_or_create(
              {user => $c->user, formitems => $formitems} );
        # Don't quote me on the exact syntax, I don't use DBIx::Class
    }
    ...
    my $formitems = $c->request->body_parameters
                  || thaw $rs->find({$user => $c->user})->formitems
                  || {} ;
    # use formitems instead of $c->request->body_parameters from here on in

The underlying table probably has (user CHAR(x), formitems TEXT) or similar. Perhaps a timestamp so that nothing too stale gets recovered. You might also want to store the action you were processing, to be sure the retrieved form items belong to the right form. You know the issues for your app better than me.

like image 62
RET Avatar answered Jan 04 '23 14:01

RET