File Coverage

blib/lib/Catalyst/Authentication/Store/DBIx/Class.pm
Criterion Covered Total %
statement 10 32 31.2
branch 0 2 0.0
condition 0 2 0.0
subroutine 4 11 36.3
pod 7 7 100.0
total 21 54 38.8


line stmt bran cond sub pod time code
1             package Catalyst::Authentication::Store::DBIx::Class;
2              
3 2     2   23971 use strict;
  2         4  
  2         68  
4 2     2   10 use warnings;
  2         4  
  2         85  
5 2     2   10 use base qw/Class::Accessor::Fast/;
  2         8  
  2         1348  
6              
7             our $VERSION= "0.1100";
8              
9              
10             BEGIN {
11 2     2   6318 __PACKAGE__->mk_accessors(qw/config/);
12             }
13              
14              
15             sub new {
16 0     0 1   my ( $class, $config, $app ) = @_;
17              
18             ## figure out if we are overriding the default store user class
19 0 0         $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 0           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 0   0       $config->{'ignore_fields_in_find'} ||= [ ];
29              
30 0           my $self = {
31             config => $config
32             };
33              
34 0           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 0     0 1   my ( $self, $c, $frozenuser ) = @_;
45              
46             # return $frozenuser if ref $frozenuser;
47              
48 0           my $user = $self->config->{'store_user_class'}->new($self->{'config'}, $c);
49 0           return $user->from_session($frozenuser, $c);
50             }
51              
52             sub for_session {
53 0     0 1   my ($self, $c, $user) = @_;
54              
55 0           return $user->for_session($c);
56             }
57              
58             sub find_user {
59 0     0 1   my ( $self, $authinfo, $c ) = @_;
60              
61 0           my $user = $self->config->{'store_user_class'}->new($self->{'config'}, $c);
62              
63 0           return $user->load($authinfo, $c);
64              
65             }
66              
67             sub user_supports {
68 0     0 1   my $self = shift;
69             # this can work as a class method on the user class
70 0           $self->config->{'store_user_class'}->supports( @_ );
71             }
72              
73             sub auto_create_user {
74 0     0 1   my( $self, $authinfo, $c ) = @_;
75 0           my $res = $self->config->{'store_user_class'}->new($self->{'config'}, $c);
76 0           return $res->auto_create( $authinfo, $c );
77             }
78              
79             sub auto_update_user {
80 0     0 1   my( $self, $authinfo, $c, $res ) = @_;
81 0           $res->auto_update( $authinfo, $c );
82 0           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.1100.
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> and B<resultset>, require its use, as they
336             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 Resultset
370              
371             The B<resultset> method of retrieval allows you to directly specify a
372             resultset to be used for user retrieval. This allows you to create a resultset
373             within your login action and use it for retrieving the user. A simple example:
374              
375             my $rs = $c->model('MyApp::User')->search({ email => $c->request->params->{'email'} });
376             ... # further $rs adjustments
377              
378             if ($c->authenticate({
379             password => $password,
380             'dbix_class' => { resultset => $rs }
381             })) {
382             # do successful authentication actions here.
383             }
384              
385             Be aware that the resultset method will not verify that you are passing a
386             resultset that is attached to the same user_model as specified in the config.
387              
388             NOTE: All of these methods of user retrieval, including the resultset method,
389             consider the first row returned to be the matching user. In most cases there
390             will be only one matching row, but it is easy to produce multiple rows,
391             especially when using the advanced retrieval methods. Remember, what you get
392             when you use this module is what you would get when calling
393             search(...)->first;
394              
395             NOTE ALSO: The user info used to save the user to the session and to retrieve
396             it is the same regardless of what method of retrieval was used. In short,
397             the value in the id field (see 'id_field' config item) is used to retrieve the
398             user from the database upon restoring from the session. When the DBIx::Class storage
399             module does this, it does so by doing a simple search using the id field. In other
400             words, it will not use the same arguments you used to request the user initially.
401             This is especially important to those using the advanced methods of user retrieval.
402             If you need more complicated logic when reviving the user from the session, you will
403             most likely want to subclass the L<Catalyst::Authentication::Store::DBIx::Class::User> class
404             and provide your own for_session and from_session routines.
405              
406             =back
407              
408              
409             =head1 METHODS
410              
411             There are no publicly exported routines in the DBIx::Class authentication
412             store (or indeed in most authentication stores). However, below is a
413             description of the routines required by L<Catalyst::Plugin::Authentication>
414             for all authentication stores. Please see the documentation for
415             L<Catalyst::Plugin::Authentication::Internals> for more information.
416              
417              
418             =head2 new ( $config, $app )
419              
420             Constructs a new store object.
421              
422             =head2 find_user ( $authinfo, $c )
423              
424             Finds a user using the information provided in the $authinfo hashref and
425             returns the user, or undef on failure. This is usually called from the
426             Credential. This translates directly to a call to
427             L<Catalyst::Authentication::Store::DBIx::Class::User>'s load() method.
428              
429             =head2 for_session ( $c, $user )
430              
431             Prepares a user to be stored in the session. Currently returns the value of
432             the user's id field (as indicated by the 'id_field' config element)
433              
434             =head2 from_session ( $c, $frozenuser)
435              
436             Revives a user from the session based on the info provided in $frozenuser.
437             Currently treats $frozenuser as an id and retrieves a user with a matching id.
438              
439             =head2 user_supports
440              
441             Provides information about what the user object supports.
442              
443             =head2 auto_update_user( $authinfo, $c, $res )
444              
445             This method is called if the realm's auto_update_user setting is true. It
446             will delegate to the user object's C<auto_update> method.
447              
448             =head2 auto_create_user( $authinfo, $c )
449              
450             This method is called if the realm's auto_create_user setting is true. It
451             will delegate to the user class's (resultset) C<auto_create> method.
452              
453             =head1 NOTES
454              
455             As of the current release, session storage consists of simply storing the user's
456             id in the session, and then using that same id to re-retrieve the user's information
457             from the database upon restoration from the session. More dynamic storage of
458             user information in the session is intended for a future release.
459              
460             =head1 BUGS AND LIMITATIONS
461              
462             None known currently; please email the author if you find any.
463              
464             =head1 SEE ALSO
465              
466             L<Catalyst::Plugin::Authentication>, L<Catalyst::Plugin::Authentication::Internals>,
467             and L<Catalyst::Plugin::Authorization::Roles>
468              
469             =head1 AUTHOR
470              
471             Jason Kuri (jayk@cpan.org)
472              
473             =head1 LICENSE
474              
475             Copyright (c) 2007 the aforementioned authors. All rights
476             reserved. This program is free software; you can redistribute
477             it and/or modify it under the same terms as Perl itself.
478              
479             =cut