Changing version number
[catagits/Catalyst-Authentication-Store-DBIx-Class.git] / lib / Catalyst / Authentication / Store / DBIx / Class.pm
CommitLineData
6727afe2 1package Catalyst::Authentication::Store::DBIx::Class;
5000f545 2
3use strict;
4use warnings;
5use base qw/Class::Accessor::Fast/;
6
a58978c0 7our $VERSION= "0.101";
6727afe2 8
b33ee900 9
10BEGIN {
11 __PACKAGE__->mk_accessors(qw/config/);
12}
13
6727afe2 14
5000f545 15sub new {
16 my ( $class, $config, $app ) = @_;
17
b33ee900 18 ## figure out if we are overriding the default store user class
19 $config->{'store_user_class'} = (exists($config->{'store_user_class'})) ? $config->{'store_user_class'} :
6727afe2 20 "Catalyst::Authentication::Store::DBIx::Class::User";
b33ee900 21
5000f545 22 ## make sure the store class is loaded.
b33ee900 23 Catalyst::Utils::ensure_class_loaded( $config->{'store_user_class'} );
5000f545 24
b33ee900 25 ## fields can be specified to be ignored during user location. This allows
ff7203cb 26 ## the store to ignore certain fields in the authinfo hash.
5000f545 27
b33ee900 28 $config->{'ignore_fields_in_find'} ||= [ ];
29
30 my $self = {
31 config => $config
32 };
5000f545 33
34 bless $self, $class;
b33ee900 35
5000f545 36}
37
ba48c9c3 38## --jk note to self:
39## let's use DBICs get_columns method to return a hash and save / restore that
40## from the session. Then we can respond to get() calls, etc. in most cases without
41## resorting to a DB call. If user_object is called, THEN we can hit the DB and
42## return a real object.
5000f545 43sub from_session {
44 my ( $self, $c, $frozenuser ) = @_;
45
46 return $frozenuser if ref $frozenuser;
b33ee900 47
48 my $user = $self->config->{'store_user_class'}->new($self->{'config'}, $c);
49
50 return $user->from_session($frozenuser, $c);
5000f545 51}
52
53sub for_session {
54 my ($self, $c, $user) = @_;
55
56 return $user->for_session($c);
57}
58
59sub find_user {
60 my ( $self, $authinfo, $c ) = @_;
61
b33ee900 62 my $user = $self->config->{'store_user_class'}->new($self->{'config'}, $c);
5000f545 63
b33ee900 64 return $user->load($authinfo, $c);
65
66}
5000f545 67
68sub user_supports {
b33ee900 69 my $self = shift;
70 # this can work as a class method on the user class
71 $self->config->{'store_user_class'}->supports( @_ );
5000f545 72}
73
67f6319b 74sub auto_create_user {
fb689852 75 my( $self, $authinfo, $c ) = @_;
76 my $res = $self->config->{'store_user_class'}->new($self->{'config'}, $c);
77 return $res->auto_create( $authinfo, $c );
78}
79
67f6319b 80sub auto_update_user {
fb689852 81 my( $self, $authinfo, $c, $res ) = @_;
82 $res->auto_update( $authinfo, $c );
83 return $res;
84}
85
5000f545 86__PACKAGE__;
87
88__END__
89
90=head1 NAME
91
6727afe2 92Catalyst::Authentication::Store::DBIx::Class - A storage class for Catalyst Authentication using DBIx::Class
5000f545 93
94=head1 VERSION
95
ad93b3e9 96This documentation refers to version 0.10.
5000f545 97
98=head1 SYNOPSIS
99
93102ff5 100 use Catalyst qw/
101 Authentication
102 Authorization::Roles/;
103
104 __PACKAGE__->config->{authentication} =
105 {
106 default_realm => 'members',
107 realms => {
108 members => {
109 credential => {
110 class => 'Password',
111 password_field => 'password',
112 password_type => 'clear'
113 },
114 store => {
115 class => 'DBIx::Class',
116 user_class => 'MyApp::Users',
117 id_field => 'user_id',
118 role_relation => 'roles',
119 role_field => 'rolename',
120 }
c1d29ab7 121 }
93102ff5 122 }
123 };
124
125 # Log a user in:
126
127 sub login : Global {
128 my ( $self, $c ) = @_;
129
130 $c->authenticate({
c1d29ab7 131 username => $c->req->params->username,
132 password => $c->req->params->password,
133 status => [ 'registered', 'loggedin', 'active']
134 }))
93102ff5 135 }
136
137 # verify a role
138
139 if ( $c->check_user_roles( 'editor' ) ) {
140 # do editor stuff
141 }
142
5000f545 143=head1 DESCRIPTION
144
6727afe2 145The Catalyst::Authentication::Store::DBIx::Class class provides
93102ff5 146access to authentication information stored in a database via DBIx::Class.
147
148=head1 CONFIGURATION
149
150The DBIx::Class authentication store is activated by setting the store
c1d29ab7 151config's B<class> element to DBIx::Class as shown above. See the
93102ff5 152L<Catalyst::Plugin::Authentication> documentation for more details on
153configuring the store.
154
155The DBIx::Class storage module has several configuration options
156
93102ff5 157
158 __PACKAGE__->config->{authentication} =
159 {
160 default_realm => 'members',
161 realms => {
162 members => {
163 credential => {
164 # ...
165 },
166 store => {
167 class => 'DBIx::Class',
168 user_class => 'MyApp::Users',
169 id_field => 'user_id',
170 role_relation => 'roles',
171 role_field => 'rolename',
172 ignore_fields_in_find => [ 'remote_name' ]
173 }
174 }
175 }
176 };
177
b81ead77 178=over 4
179
93102ff5 180=item class
181
6727afe2 182Class is part of the core Catalyst::Plugin::Authentication module, it
93102ff5 183contains the class name of the store to be used.
184
185=item user_class
5000f545 186
93102ff5 187Contains the class name (as passed to $c->model()) of the DBIx::Class schema
188to use as the source for user information. This config item is B<REQUIRED>.
5000f545 189
93102ff5 190=item id_field
5000f545 191
93102ff5 192Contains the field name containing the unique identifier for a user. This is
193used when storing and retrieving a user from the session. The value in this
194field should correspond to a single user in the database. Defaults to 'id'.
5000f545 195
93102ff5 196=item role_column
5000f545 197
93102ff5 198If your role information is stored in the same table as the rest of your user
199information, this item tells the module which field contains your role
200information. The DBIx::Class authentication store expects the data in this
201field to be a series of role names separated by some combination of spaces,
202commas or pipe characters.
5000f545 203
93102ff5 204=item role_relation
5000f545 205
93102ff5 206If your role information is stored in a separate table, this is the name of
207the relation that will lead to the roles the user is in. If this is
208specified then a role_field is also required. Also when using this method
209it is expected that your role table will return one row for each role
210the user is in.
5000f545 211
93102ff5 212=item role_field
5000f545 213
93102ff5 214This is the name of the field in the role table that contains the string
215identifying the role.
5000f545 216
93102ff5 217=item ignore_fields_in_find
5000f545 218
c1d29ab7 219This item is an array containing fields that may be passed to the
220$c->authenticate() routine (and therefore find_user in the storage class), but
221which should be ignored when creating the DBIx::Class search to retrieve a
222user. This makes it possible to avoid problems when a credential requires an
223authinfo element whose name overlaps with a column name in your users table.
224If this doesn't make sense to you, you probably don't need it.
5000f545 225
93102ff5 226=item store_user_class
5000f545 227
93102ff5 228This allows you to override the authentication user class that the
229DBIx::Class store module uses to perform it's work. Most of the
230work done in this module is actually done by the user class,
6727afe2 231L<Catalyst::Authentication::Store::DBIx::Class::User>, so
93102ff5 232overriding this doesn't make much sense unless you are using your
233own class to extend the functionality of the existing class.
234Chances are you do not want to set this.
5000f545 235
93102ff5 236=back
5000f545 237
93102ff5 238=head1 USAGE
5000f545 239
6727afe2 240The L<Catalyst::Authentication::Store::DBIx::Class> storage module
93102ff5 241is not called directly from application code. You interface with it
242through the $c->authenticate() call.
5000f545 243
c1d29ab7 244There are three methods you can use to retrieve information from the DBIx::Class
245storage module. They are Simple retrieval, and the advanced retrieval methods
246Searchargs and Resultset.
247
248=head2 Simple Retrieval
249
250The first, and most common, method is simple retrieval. As it's name implies
251simple retrieval allows you to simply to provide the column => value pairs
252that should be used to locate the user in question. An example of this usage
253is below:
254
255 if ($c->authenticate({
256 username => $c->req->params->{'username'},
257 password => $c->req->params->{'password'},
258 status => [ 'registered', 'active', 'loggedin']
259 })) {
260
261 # ... authenticated user code here
262 }
263
264The above example would attempt to retrieve a user whose username column
265matched the username provided, and whose status column matched one of the
266values provided. These name => value pairs are used more or less directly in
267the DBIx::Class' search() routine, so in most cases, you can use DBIx::Class
268syntax to retrieve the user according to whatever rules you have.
269
270NOTE: Because the password in most cases is encrypted - it is not used
271directly but it's encryption and comparison with the value provided is usually
272handled by the Password Credential. Part of the Password Credential's behavior
273is to remove the password argument from the authinfo that is passed to the
6727afe2 274storage module. See L<Catalyst::Authentication::Credential::Password>.
c1d29ab7 275
276One thing you need to know about this retrieval method is that the name
277portion of the pair is checked against the user class' column list. Pairs are
278only used if a matching column is found. Other pairs will be ignored. This
279means that you can only provide simple name-value pairs, and that some more
280advanced DBIx::Class constructs, such as '-or', '-and', etc. are in most cases
281not possible using this method. For queries that require this level of
282functionality, see the 'searchargs' method below.
283
284=head2 Advanced Retrieval
285
286The Searchargs and Resultset retrieval methods are used when more advanced
287features of the underlying L<DBIx::Class> schema are required. These methods
288provide a direct interface with the DBIx::Class schema and therefore
289require a better understanding of the DBIx::Class module.
290
291=head3 The dbix_class key
292
293Since the format of these arguments are often complex, they are not keys in
294the base authinfo hash. Instead, both of these arguments are placed within
295a hash attached to the store-specific 'dbix_class' key in the base $authinfo
296hash. When the DBIx::Class authentication store sees the 'dbix_class' key
297in the passed authinfo hash, all the other information in the authinfo hash
298is ignored and only the values within the 'dbix_class' hash are used as
299though they were passed directly within the authinfo hash. In other words, if
300'dbix_class' is present, it replaces the authinfo hash for processing purposes.
301
302The 'dbix_class' hash can be used to directly pass arguments to the
303DBIx::Class authentication store. Reasons to do this are to avoid credential
304modification of the authinfo hash, or to avoid overlap between credential and
305store key names. It's a good idea to avoid using it in this way unless you are
306sure you have an overlap/modification issue. However, the two advanced
307retrieval methods, B<searchargs> and B<resultset>, require it's use, as they
308are only processed as part of the 'dbix_class' hash
309
310=over 4
311
312=item Searchargs
313
314The B<searchargs> method of retrieval allows you to specify an arrayref containing
ad93b3e9 315the two arguments to the search() method from L<DBIx::Class::ResultSet>. If provided,
c1d29ab7 316all other args are ignored, and the search args provided are used directly to locate
317the user. An example will probably make more sense:
318
319 if ($c->authenticate(
320 {
321 password => $password,
322 'dbix_class' =>
323 {
324 searchargs = [ { -or => [ username => $username,
325 email => $email,
326 clientid => $clientid ]
327 },
328 { prefetch => qw/ preferences / }
329 ]
330 }
331 } ) )
332 {
333 # do successful authentication actions here.
334 }
335
336The above would allow authentication based on any of the three items -
337username, email or clientid and would prefetch the data related to that user
338from the preferences table. The searchargs array is passed directly to the
339search() method associated with the user_class.
340
341=item Resultset
342
343The B<resultset> method of retrieval allows you to directly specify a
344resultset to be used for user retrieval. This allows you to create a resultset
345within your login action and use it for retrieving the user. A simple example:
346
347 my $rs = $c->model('MyApp::User')->search({ email => $c->request->params->{'email'} });
348 ... # further $rs adjustments
349
350 if ($c->authenticate({
351 password => $password,
352 'dbix_class' => { resultset = $rs }
353 })) {
354 # do successful authentication actions here.
355 }
356
357Be aware that the resultset method will not verify that you are passing a
358resultset that is attached to the same user_class as specified in the config.
359
360NOTE: All of these methods of user retrieval, including the resultset method,
361consider the first row returned to be the matching user. In most cases there
362will be only one matching row, but it is easy to produce multiple rows,
363especially when using the advanced retrieval methods. Remember, what you get
364when you use this module is what you would get when calling
365search(...)->first;
366
367NOTE ALSO: The user info used to save the user to the session and to retrieve
368it is the same regardless of what method of retrieval was used. In short,
369the value in the id field (see 'id_field' config item) is used to retrieve the
370user from the database upon restoring from the session. When the DBIx::Class storage
371module does this, it does so by doing a simple search using the id field. In other
372words, it will not use the same arguments you used to request the user initially.
373This is especially important to those using the advanced methods of user retrieval.
374If you need more complicated logic when reviving the user from the session, you will
6727afe2 375most likely want to subclass the L<Catalyst::Authentication::Store::DBIx::Class::User> class
c1d29ab7 376and provide your own for_session and from_session routines.
377
378=back
5000f545 379
6727afe2 380
93102ff5 381=head1 METHODS
5000f545 382
93102ff5 383There are no publicly exported routines in the DBIx::Class authentication
384store (or indeed in most authentication stores) However, below is a
385description of the routines required by L<Catalyst::Plugin::Authentication>
386for all authentication stores. Please see the documentation for
387L<Catalyst::Plugin::Authentication::Internals> for more information.
388
6727afe2 389
390=head2 new ( $config, $app )
93102ff5 391
c1d29ab7 392Constructs a new store object.
93102ff5 393
6727afe2 394=head2 find_user ( $authinfo, $c )
93102ff5 395
c1d29ab7 396Finds a user using the information provided in the $authinfo hashref and
397returns the user, or undef on failure; This is usually called from the
398Credential. This translates directly to a call to
6727afe2 399L<Catalyst::Authentication::Store::DBIx::Class::User>'s load() method.
93102ff5 400
6727afe2 401=head2 for_session ( $c, $user )
93102ff5 402
c1d29ab7 403Prepares a user to be stored in the session. Currently returns the value of
404the user's id field - (as indicated by the 'id_field' config element)
93102ff5 405
6727afe2 406=head2 from_session ( $c, $frozenuser)
93102ff5 407
c1d29ab7 408Revives a user from the session based on the info provided in $frozenuser.
93102ff5 409Currently treats $frozenuser as an id and retrieves a user with a matching id.
410
6727afe2 411=head2 user_supports
93102ff5 412
413Provides information about what the user object supports.
414
76e7a763 415=head2 auto_update_user( $authinfo, $c, $res )
416
417This method is called if the realm's auto_update_user setting is true. It
418will delegate to the user object's C<auto_update> method.
67f6319b 419
76e7a763 420=head2 auto_create_user( $authinfo, $c )
67f6319b 421
76e7a763 422This method is called if the realm's auto_create_user setting is true. It
423will delegate to the user class' (resultset) C<auto_create> method.
5000f545 424
425=head1 NOTES
426
93102ff5 427As of the current release, session storage consists of simply storing the user's
428id in the session, and then using that same id to re-retrieve the users information
429from the database upon restoration from the session. More dynamic storage of
430user information in the session is intended for a future release.
5000f545 431
432=head1 BUGS AND LIMITATIONS
433
434None known currently, please email the author if you find any.
435
436=head1 SEE ALSO
437
93102ff5 438L<Catalyst::Plugin::Authentication>, L<Catalyst::Plugin::Authentication::Internals>,
439and L<Catalyst::Plugin::Authorization::Roles>
5000f545 440
441=head1 AUTHOR
442
b33ee900 443Jason Kuri (jayk@cpan.org)
5000f545 444
c1d29ab7 445=head1 LICENSE
5000f545 446
c1d29ab7 447Copyright (c) 2007 the aforementioned authors. All rights
93102ff5 448reserved. This program is free software; you can redistribute
449it and/or modify it under the same terms as Perl itself.
5000f545 450
451=cut