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