package Catalyst::Plugin::Authentication::Store::DBIx::Class;

use strict;
use warnings;
use base qw/Class::Accessor::Fast/;

our $VERSION= "0.02";

BEGIN {
    __PACKAGE__->mk_accessors(qw/config/);
}


sub new {
    my ( $class, $config, $app ) = @_;

    ## figure out if we are overriding the default store user class 
    $config->{'store_user_class'} = (exists($config->{'store_user_class'})) ? $config->{'store_user_class'} :
                                        "Catalyst::Plugin::Authentication::Store::DBIx::Class::User";

    ## make sure the store class is loaded.
    Catalyst::Utils::ensure_class_loaded( $config->{'store_user_class'} );
    
    ## fields can be specified to be ignored during user location.  This allows
    ## the store to ignore certain fields in the authinfo hash.
    
    $config->{'ignore_fields_in_find'} ||= [ ];

    my $self = {
                    config => $config
               };

    bless $self, $class;

}

## --jk note to self:
## let's use DBICs get_columns method to return a hash and save / restore that
## from the session.  Then we can respond to get() calls, etc. in most cases without
## resorting to a DB call.  If user_object is called, THEN we can hit the DB and
## return a real object.  
sub from_session {
    my ( $self, $c, $frozenuser ) = @_;

    return $frozenuser if ref $frozenuser;
    
    my $user = $self->config->{'store_user_class'}->new($self->{'config'}, $c);
    
    return $user->from_session($frozenuser, $c);
}

sub for_session {
    my ($self, $c, $user) = @_;
    
    return $user->for_session($c);
}

sub find_user {
    my ( $self, $authinfo, $c ) = @_;
    
    my $user = $self->config->{'store_user_class'}->new($self->{'config'}, $c);

    return $user->load($authinfo, $c);

}

sub user_supports {
    my $self = shift;
    # this can work as a class method on the user class
    $self->config->{'store_user_class'}->supports( @_ );
}

__PACKAGE__;

__END__

=head1 NAME

Catalyst::Plugin::Authentication::Store::DBIx::Class - A storage class for Catalyst Authentication using DBIx::Class

=head1 VERSION

This documentation refers to version 0.01.

=head1 SYNOPSIS

    use Catalyst qw/
                    Authentication
                    Authorization::Roles/;

    __PACKAGE__->config->{authentication} = 
                    {  
                        default_realm => 'members',
                        realms => {
                            members => {
                                credential => {
                                    class => 'Password',
                                    password_field => 'password',
                                    password_type => 'clear'
                                },
                                store => {
                                    class => 'DBIx::Class',
            	                    user_class => 'MyApp::Users',
            	                    id_field => 'user_id',
            	                    role_relation => 'roles',
            	                    role_field => 'rolename',	                
            	                }
                	        }
                    	}
                    };

    # Log a user in:
    
    sub login : Global {
        my ( $self, $c ) = @_;
        
        $c->authenticate({  
		                    username => $c->req->params->username,
		                    password => $c->req->params->password,
		                    status => [ 'registered', 'loggedin', 'active' ]
		                 }))
    }
    
    # verify a role 
    
    if ( $c->check_user_roles( 'editor' ) ) {
        # do editor stuff
    }
    
=head1 DESCRIPTION

The Catalyst::Plugin::Authentication::Store::DBIx::Class class provides 
access to authentication information stored in a database via DBIx::Class.

=head1 CONFIGURATION

The DBIx::Class authentication store is activated by setting the store
config's class element to DBIx::Class as shown above.  See the 
L<Catalyst::Plugin::Authentication> documentation for more details on 
configuring the store.

The DBIx::Class storage module has several configuration options

=over 4

    __PACKAGE__->config->{authentication} = 
                    {  
                        default_realm => 'members',
                        realms => {
                            members => {
                                credential => {
                                    # ...
                                },
                                store => {
                                    class => 'DBIx::Class',
            	                    user_class => 'MyApp::Users',
            	                    id_field => 'user_id',
            	                    role_relation => 'roles',
            	                    role_field => 'rolename',
            	                    ignore_fields_in_find => [ 'remote_name' ]          
            	                }
                	        }
                    	}
                    };

=item class

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

=item user_class

Contains the class name (as passed to $c->model()) of the DBIx::Class schema
to use as the source for user information.  This config item is B<REQUIRED>.

=item id_field

Contains the field name containing the unique identifier for a user.  This is 
used when storing and retrieving a user from the session.  The value in this
field should correspond to a single user in the database.  Defaults to 'id'.

=item role_column

If your role information is stored in the same table as the rest of your user
information, this item tells the module which field contains your role
information.  The DBIx::Class authentication store expects the data in this
field to be a series of role names separated by some combination of spaces, 
commas or pipe characters.  

=item role_relation

If your role information is stored in a separate table, this is the name of
the relation that will lead to the roles the user is in.  If this is 
specified then a role_field is also required.  Also when using this method
it is expected that your role table will return one row for each role 
the user is in.

=item role_field

This is the name of the field in the role table that contains the string 
identifying the role.  

=item ignore_fields_in_find

This item is an array containing fields that may be passed to the 
find_user routine, but which should be ignored when creating the 
DBIx::Class search to retrieve a user.  This makes it possible to
avoid problems when a credential requires an authinfo element whose
name overlaps with a column name in your users table.  If this doesn't
make sense to you, you probably don't need it.

=item store_user_class

This allows you to override the authentication user class that the 
DBIx::Class store module uses to perform it's work.  Most of the
work done in this module is actually done by the user class, 
L<Catalyst::Plugin::Authentication::Store::DBIx::Class::User>, so
overriding this doesn't make much sense unless you are using your
own class to extend the functionality of the existing class.  
Chances are you do not want to set this.

=back

=head1 USAGE 

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

... documentation fairy fell asleep here ...


=head1 METHODS

There are no publicly exported routines in the DBIx::Class authentication 
store (or indeed in most authentication stores)  However, below is a 
description of the routines required by L<Catalyst::Plugin::Authentication> 
for all authentication stores.  Please see the documentation for 
L<Catalyst::Plugin::Authentication::Internals> for more information.

=over 4

=item new ( $config, $app )

Constructs a new store object, which uses the user element of the supplied config 
hash ref as it's backing structure.

=item find_user ( $authinfo, $c ) 

Finds a user using the information provided in the $authinfo hashref and returns
the user, or undef on failure;  This translates directly to a call to 
L<Catalyst::Plugin::Authentication::Store::DBIx::Class::User>'s load() method.

=item for_session ( $c, $user )

Prepares a user to be stored in the session.  Currently returns the value of the
user's id field - (as indicated by the 'id_field' config element)

=item from_session ( $c, $frozenuser)

Revives a user from the session based on the info provided in $frozenuser.  
Currently treats $frozenuser as an id and retrieves a user with a matching id.

=item user_supports

Provides information about what the user object supports.  

=back 

=head1 NOTES

As of the current release, session storage consists of simply storing the user's
id in the session, and then using that same id to re-retrieve the users information
from the database upon restoration from the session.  More dynamic storage of
user information in the session is intended for a future release.

=head1 BUGS AND LIMITATIONS

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

=head1 SEE ALSO

L<Catalyst::Plugin::Authentication>, L<Catalyst::Plugin::Authentication::Internals>,
and L<Catalyst::Plugin::Authorization::Roles>

=head1 AUTHOR

Jason Kuri (jayk@cpan.org)

=head1 LICENCE

Copyright (c) 2005 the aforementioned authors. All rights
reserved. This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

=cut
