Making id_field dynamic - so that session storage works
Jay Kuri [Thu, 8 Feb 2007 03:29:20 +0000 (03:29 +0000)]
on tables where the id field is not simply 'id'.
Also - a big chunk of documentation - though still more is needed

lib/Catalyst/Plugin/Authentication/Store/DBIx/Class.pm
lib/Catalyst/Plugin/Authentication/Store/DBIx/Class/User.pm

index 1ecbe68..3f58f2f 100644 (file)
@@ -84,65 +84,195 @@ This documentation refers to version 0.01.
 
 =head1 SYNOPSIS
 
-use Catalyst::Plugin::Authentication::Store::DBIx::Class;
-
+    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 implements ...
+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
 
-=head1 SUBROUTINES / METHODS
+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>.
 
-=head2 new (constructor)
+=item id_field
 
-Parameters:
-    class
-    config
-    app
+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'.
 
-Insert description of constructor here...
+=item role_column
 
-=head2 from_session (method)
+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.  
 
-Parameters:
-    c
-    frozenuser
+=item role_relation
 
-Insert description of method here...
+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.
 
-=head2 for_session (method)
+=item role_field
 
-Parameters:
-    c
-    user
+This is the name of the field in the role table that contains the string 
+identifying the role.  
 
-Insert description of method here...
+=item ignore_fields_in_find
 
-=head2 find_user (method)
+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.
 
-Parameters:
-    authinfo
-    c
+=item store_user_class
 
-Insert description of method here...
+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.
 
-=head2 user_supports
+=back
 
-Parameters:
-    none
+=head1 USAGE 
 
-Insert description of subroutine here...
+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.  
 
-=head1 DEPENDENCIES
+... documentation fairy fell asleep here ...
 
-Modules used, version dependencies, core yes/no
 
-strict
+=head1 METHODS
 
-warnings
+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
 
@@ -150,7 +280,8 @@ None known currently, please email the author if you find any.
 
 =head1 SEE ALSO
 
-L<Catalyst::Plugin::Authentication>, L<Catalyst::Plugin::Authorization::Roles>
+L<Catalyst::Plugin::Authentication>, L<Catalyst::Plugin::Authentication::Internals>,
+and L<Catalyst::Plugin::Authorization::Roles>
 
 =head1 AUTHOR
 
@@ -158,8 +289,8 @@ Jason Kuri (jayk@cpan.org)
 
 =head1 LICENCE
 
-Copyright 2006 by Jason Kuri.
-
-This software is free.  It is licensed under the same terms as Perl itself.
+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
index 9a08fbe..61b46e7 100644 (file)
@@ -22,6 +22,9 @@ sub new {
     bless $self, $class;
     
 
+    if (!exists($self->config->{'id_field'})) {
+        $self->config->{'id_field'} = 'id';
+    }
     
     ## if we have lazyloading turned on - we should not query the DB unless something gets read.
     ## that's the idea anyway - still have to work out how to manage that - so for now we always force
@@ -72,7 +75,7 @@ sub load {
     }
 
     if ($self->get_object) {
-        return $self
+        return $self;
     } else {
         return undef;
     }
@@ -101,7 +104,7 @@ sub roles {
     
     my @roles = ();
     if (exists($self->config->{'role_column'})) {
-        @roles = split /[ ,\|]/, $self->get($self->config->{'role_column'});
+        @roles = split /[ ,\|]+/, $self->get($self->config->{'role_column'});
         $self->_roles(\@roles);
     } elsif (exists($self->config->{'role_relation'})) {
         my $relation = $self->config->{'role_relation'};
@@ -121,7 +124,7 @@ sub roles {
 sub for_session {
     my $self = shift;
     
-    return $self->get('id');
+    return $self->get($self->config->{'id_field'});
 }
 
 sub from_session {
@@ -129,7 +132,7 @@ sub from_session {
     
     # this could be a lot better.  But for now it just assumes $frozenuser is an id and uses find_user
     # XXX: hits the database on every request?  Not good...
-    return $self->load( { id => $frozenuser }, $c);
+    return $self->load( { $self->config->{'id_field'} => $frozenuser }, $c);
 }
 
 sub get {
@@ -175,7 +178,10 @@ This documentation refers to version 0.01.
 
 =head1 SYNOPSIS
 
-use Catalyst::Plugin::Authentication::Store::DBIx::Class::User;
+Internal - not used directly.  use Catalyst::Plugin::Authentication::Store::DBIx::Class::User;
+
+
+                
 
 =head1 DESCRIPTION