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