The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Catalyst::Authentication::Store::FromSub::Hash - A storage class for Catalyst Authentication using one Catalyst Model class (hash returned)

SYNOPSIS

    use Catalyst qw/Authentication/;

    __PACKAGE__->config->{authentication} = 
                    {  
                        default_realm => 'members',
                        realms => {
                            members => {
                                credential => {
                                    class => 'Password',
                                    password_field => 'password',
                                    password_type => 'clear'
                                },
                                store => {
                                    class => 'FromSub::Hash',
                                    model_class => 'UserAuth',
                                    id_field => 'user_id',
                                }
                            }
                        }
                    };

    # Log a user in:
    sub login : Global {
        my ( $self, $c ) = @_;
        
        $c->authenticate({  
                          username => $c->req->params->username,
                          password => $c->req->params->password,
                          }))
    }
    
    package MyApp::Model::UserAuth; # map with model_class in config above
    use base qw/Catalyst::Model/;
    use strict;
    
    sub auth { # sub name needs to be 'auth'
        my ($self, $c, $userinfo) = @_;
        
        my $where;
        if (exists $userinfo->{user_id}) { # restore from session (id_field => 'user_id')
            $where = { user_id => $userinfo->{user_id} };
        } elsif (exists $userinfo->{username}) { # from authenticate
            $where = { username => $userinfo->{username} };
        } else { return; }
    
        
        # deal with cache
        # if (my $val = $c->cache->get($key) {
        #     return $val;
        # } else {
            my $user = $c->model('TestApp')->resultset('User')->search( $where )->first;
            $user = $user->{_column_data}; # hash
        #     $c->cache->set($key, $user);
        # }

        return $user;
    }

    

DESCRIPTION

Catalyst::Authentication::Store::FromSub::Hash class provides access to authentication information by using a Catalyst Model sub auth.

In sub auth of the Catalyst model, we can use cache there. it would avoid the hit of db every request.

CONFIGURATION

The FromSub::Hash authentication store is activated by setting the store config class element to 'FromSub::Hash'. See the Catalyst::Plugin::Authentication documentation for more details on configuring the store.

The FromSub::Hash storage module has several configuration options

    __PACKAGE__->config->{authentication} = 
                    {  
                        default_realm => 'members',
                        realms => {
                            members => {
                                credential => {
                                    # ...
                                },
                                store => {
                                    class => 'FromSub::Hash',
                                    model_class => 'UserAuth',
                                    id_field => 'user_id',
                                }
                            }
                        }
                    };

    authentication:
      default_realm: 'members'
      password_hash_type: "clear"
      realms:
        members:
          credential:
            class: 'Password'
            password_field: 'password'
            password_type: "hashed"
            password_hash_type: "SHA-1"
          store:
            class: 'FromSub::Hash'
            model_class: "UserAuth"
class

Class is part of the core Catalyst::Authentication::Plugin module, it contains the class name of the store to be used.

user_class

Contains the class name (as passed to $c->model()) of Catalyst. This config item is REQUIRED.

id_field

For restore from session, we pass { $id_field => $c->session->{__user}->{$id_field} } to sub auth, so be sure you deal with this $userinfo in sub auth like

    sub auth { # sub name needs to be 'auth'
        my ($self, $c, $userinfo) = @_;
        
        my $where;
        if (exists $userinfo->{user_id}) { # restore from session (id_field => 'user_id')
            $where = { user_id => $userinfo->{user_id} };
        } elsif (exists $userinfo->{username}) { # from authenticate
            $where = { username => $userinfo->{username} };
        } else { return; }

It is a primary key in the hash return by sub auth. Default is 'user_id'

USAGE

The Catalyst::Authentication::Store::FromSub::Hash storage module is not called directly from application code. You interface with it through the $c->authenticate() call.

EXAMPLES

Adv.

    # for login
    sub login : Global {
        my ( $self, $c ) = @_;
        
        $c->authenticate({  
                          username => $c->req->params->username,
                          password => $c->req->params->password,
                          status => [ 'active', 'registered' ],
                          }))
    }

    sub is_admin : Global {
        my ( $self, $c ) = @_;
        
        # use Set::Object in C::P::A::Roles
        eval {
            if ( $c->assert_user_roles( qw/admin/ ) ) {
                $c->res->body( 'ok' );
            }
        };
        if ($@) {
            $c->res->body( 'failed' );
        }
    }
    
    package MyApp::Model::UserAuth; # map with model_class in config above
    use base qw/Catalyst::Model/;
    use strict;
    
    sub auth {
        my ($self, $c, $userinfo) = @_;
        
        my ($where, $cache_key);
        if (exists $userinfo->{user_id}) {
            $where = { user_id => $userinfo->{user_id} };
            $cache_key = 'global|user|user_id=' . $userinfo->{user_id};
        } elsif (exists $userinfo->{username}) {
            $where = { username => $userinfo->{username} };
            $cache_key = 'global|user|username=' . $userinfo->{username};
        } else { return; }
    
        my $user;
        if (my $val = $c->cache->get($cache_key) {
            $user = $val;
        } else {
            $user = $c->model('TestApp')->resultset('User')->search( $where )->first;
            $user = $user->{_column_data}; # hash to cache
            # get user roles
            my $role_rs = $c->model('TestApp')->resultset('UserRole')->search( {
                user => $user->{id}
            } );
            while (my $r = $role_rs->next) {
                my $role = $c->model('TestApp')->resultset('Role')->find( {
                    id => $r->roleid
                } );
                push @{$user->{roles}}, $role->role;
            }
            # $user = {
            #     'roles' => [
            #         'admin',
            #         'user'
            #     ],
            #    'status' => 'active',
            #    'session_data' => undef,
            #    'username' => 'jayk',
            #    'email' => 'j@cpants.org',
            #    'password' => 'letmein',
            #    'id' => '3'
            #}
            $c->cache->set($cache_key, $user);
        }
        
        # validate status
        if ( exists $userinfo->{status} and ref $userinfo->{status} eq 'ARRAY') {
            unless (grep { $_ eq $user->{status} } @{$userinfo->{status}}) {
                return;
            }
        }

        return $user;
    }

CODE USED IN LIVE

http://foorum.googlecode.com/svn/trunk/

BUGS

None known currently, please email the author if you find any.

SEE ALSO

Catalyst::Plugin::Authentication, Catalyst::Plugin::Authentication::Internals, Catalyst::Plugin::Authorization::Roles

AUTHOR

Fayland Lam, <fayland at gmail.com>

COPYRIGHT & LICENSE

Copyright 2007 Fayland Lam, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.