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