Catalyst::Plugin::Session::Store::CDBI - CDBI sessions for Catalyst


Catalyst-Plugin-Session-Store-CDBI documentation Contained in the Catalyst-Plugin-Session-Store-CDBI distribution.

Index


Code Index:

NAME

Top

Catalyst::Plugin::Session::Store::CDBI - CDBI sessions for Catalyst

SYNOPSIS

Top

    use Catalyst qw/Session Session::Store::CDBI Session::State::Cookie/;

    MyApp->config->{session} = {
        storage_class => 'MyApp::M::CDBI::Session',
        id_field      => 'id',
        storage_field => 'storage',
        expires_field => 'expires',
        expires       => 3600,
        need_commit   => 0,
    };

    # ... in an action:
    $c->session->{foo} = 'bar'; # will be saved

DESCRIPTION

Top

Catalyst::Plugin::Session::Store::CDBI is a session storage plugin for Catalyst that uses Class::DBI.

METHODS

get_session_data
store_session_data
delete_session_data
delete_expired_sessions
setup_actions
setup_session

These are implementations of the required methods for a store. See Catalyst::Plugin::Session::Store.

serialize

Returns the serialized form of the data passed in.

deserialize

Returns the deserialized data.

CONFIGURATION

Top

These parameters are placed in the hash under the session key in the configuration hash.

storage_class

CDBI-subclass that represents the table that stores session-data.

id_field

Column name for the primary key. Defaults to 'id'.

storage_field

Column name used to store the serialized session data. Defaults to 'storage'.

expires_field

Column name to store the expire time. Defaults to 'expires'.

expires

Session time to live. Defaults to 3600.

need_commit

Defaults to 0. Set to 1 when the CDBI class has AutoCommit turned off.

SEE ALSO

Top

Catalyst, Catalyst::Plugin::Session, Class::DBI.

AUTHOR

Top

Jason Woodward <woodwardj@jaos.org>

Based on work by Lyo Kato <lyo.kato@gmail.com> Yuval Kogman <nothingmuch@woobling.org> Sebastian Riedel <sri@cpan.org>, Marcus Ramberg <mramberg@cpan.org>, Andrew Ford <andrewf@cpan.org>,

COPYRIGHT

Top


Catalyst-Plugin-Session-Store-CDBI documentation Contained in the Catalyst-Plugin-Session-Store-CDBI distribution.
package Catalyst::Plugin::Session::Store::CDBI;

use strict;
use base qw/Catalyst::Plugin::Session::Store/;
use NEXT;
use Catalyst::Exception ();
use Class::DBI;
use MIME::Base64;
use Storable qw/freeze thaw/;

our $VERSION = '0.03';

sub get_session_data {
    my ( $c, $sid ) = @_;

    return unless $sid;

    my $cfg           = $c->config->{session};
    my $storage_class = $c->_verify_storage_class( $cfg->{storage_class} );

    my $storage_field = $cfg->{storage_field} || 'storage';
    my $id_field      = $c->_get_session_id_field();
    my $expires_field = $cfg->{expires_field} || 'expires';

    my $want_expires = 0;

    if ( $sid =~ /^expires:/ ) {
        my ($key) = $sid =~ /^expires:(.*)/;
        $sid = "session:$key";
        $want_expires = 1;
    }

    if ( my $s = $storage_class->search( $id_field => $sid )->first ) {
        if ( $want_expires ) {
            $c->log->debug("returning expires for $sid") if $c->debug;
            return $s->get($expires_field);
        }
        else {
          if ( my $data = $s->get($storage_field) ) {
              $c->log->debug("Deserializing session data for $sid") if $c->debug;
              return $c->deserialize($data);
          }
          else {
              return;
          }
        }
    }
    $c->log->debug("Could not find session for $sid") if $c->debug;

    return;
}

sub store_session_data {
    my ( $c, $sid, $data ) = @_;

    return unless $sid;

    my $cfg           = $c->config->{session};
    my $storage_class = $c->_verify_storage_class( $cfg->{storage_class} );

    my $storage_field = $cfg->{storage_field} || 'storage';
    my $id_field      = $c->_get_session_id_field();
    my $expires_field = $cfg->{expires_field} || 'expires';
    my $expires       = $cfg->{expires}       || 3600;
    my $need_commit   = $cfg->{need_commit}   || 0;

    my $want_expires = 0;

    if ( $sid =~ /^expires:/ ) {
        my ($key) = $sid =~ /^expires:(.*)/;
        $sid = "session:$key";
        $want_expires = 1;
    }

    if ( my $s = $storage_class->find_or_create( $id_field => $sid ) ) {

        if ( $want_expires ) {
            $s->set( $expires_field, $c->session_expires );
            $s->update;
        }
        else {
            $c->log->debug("Serializing session data for $sid") if $c->debug;
            $s->set( $storage_field, $c->serialize($data) );
            if ( $sid =~ /^(?:session|flash):/ ) {
                $s->set( $expires_field, $c->session_expires );
            }
            $s->update;
        }

    }
    else {

        $c->log->debug("Could not find session for $sid") if $c->debug;

    }

    $storage_class->dbi_commit if $need_commit;

    return;
}

sub delete_session_data {
    my ( $c, $sid ) = @_;

    return unless $sid;
    return if $sid =~ /^expires/;

    my $cfg           = $c->config->{session};
    my $storage_class = $c->_verify_storage_class( $cfg->{storage_class} );

    my $id_field      = $c->_get_session_id_field();

    $storage_class->search( $id_field => $sid )->delete_all();
    $storage_class->dbi_commit if ( $cfg->{need_commit} );

    $c->log->debug("Deleted session for $sid") if $c->debug;

    return;
}

sub delete_expired_sessions {
    my $c = shift;

    my $cfg           = $c->config->{session};
    my $storage_class = $c->_verify_storage_class( $cfg->{storage_class} );

    my $expires_field = $cfg->{expires_field} || 'expires';

    $storage_class->db_Main->do( sprintf "DELETE FROM %s WHERE %s < %d",
        $storage_class->table, $expires_field, time );
    $c->log->debug("Deleted expired sessions") if $c->debug;

    return;
}

sub _verify_storage_class {
    my ( $c, $storage_class ) = @_;

    $storage_class->require;
    if ($@) {
        Catalyst::Exception->throw(
            qq/Failed to require "$storage_class", "$@"/);
    }
    unless ( $storage_class->isa('Class::DBI') ) {
        Catalyst::Exception->throw(
            qq/Session-Class should be made with Class::DBI./);
    }

    return $storage_class;
}

sub serialize {
    my ( $c, $data ) = @_;
    encode_base64( freeze($data) );
}

sub deserialize {
    my ( $c, $data ) = @_;
    thaw( decode_base64($data) );
}

sub setup_session {
    my $c = shift;
    $c->NEXT::setup_session(@_);
}

sub setup_actions {
    my $c = shift;
    $c->NEXT::setup_actions(@_);
}

sub _get_session_id_field {
    my $c = shift;
    
    my $cfg = $c->config->{session};
    return $cfg->{id_field} if $cfg->{id_field};
    
    my $storage_class = $c->_verify_storage_class( $cfg->{storage_class} );

    my @pkeys = $storage_class->columns('Primary');
    if(scalar(@pkeys) > 1)
    {
        $c->error("More than one primary key setup on the session table.");
    }

    return $pkeys[0]->name;
}


1;