File Coverage

blib/lib/Catalyst/Authentication/Store/DBIx/Class/User.pm
Criterion Covered Total %
statement 16 110 14.5
branch 0 42 0.0
condition 0 9 0.0
subroutine 6 19 31.5
pod 11 11 100.0
total 33 191 17.2


line stmt bran cond sub pod time code
1             package Catalyst::Authentication::Store::DBIx::Class::User;
2              
3 1     1   1484 use strict;
  1         2  
  1         26  
4 1     1   4 use warnings;
  1         1  
  1         27  
5 1     1   429 use List::MoreUtils qw(all);
  1         6882  
  1         6  
6 1     1   426 use base qw/Catalyst::Authentication::User/;
  1         2  
  1         428  
7 1     1   11374 use base qw/Class::Accessor::Fast/;
  1         1  
  1         71  
8              
9             BEGIN {
10 1     1   6 __PACKAGE__->mk_accessors(qw/config resultset _user _roles/);
11             }
12              
13             sub new {
14 0     0 1   my ( $class, $config, $c) = @_;
15              
16             $config->{user_model} = $config->{user_class}
17 0 0         unless defined $config->{user_model};
18              
19             my $self = {
20 0           resultset => $c->model($config->{'user_model'}),
21             config => $config,
22             _roles => undef,
23             _user => undef
24             };
25              
26 0           bless $self, $class;
27              
28             Catalyst::Exception->throw(
29 0           "\$c->model('${ \$self->config->{user_model} }') did not return a resultset."
30             . " Did you set user_model correctly?"
31 0 0         ) unless $self->{resultset};
32              
33             $self->config->{'id_field'} = [$self->{'resultset'}->result_source->primary_columns]
34 0 0         unless exists $self->config->{'id_field'};
35              
36             $self->config->{'id_field'} = [$self->config->{'id_field'}]
37 0 0         unless ref $self->config->{'id_field'} eq 'ARRAY';
38              
39             Catalyst::Exception->throw(
40             "id_field set to "
41 0           . join(q{,} => @{ $self->config->{'id_field'} })
42             . " but user table has no column by that name!"
43 0 0   0     ) unless all { $self->{'resultset'}->result_source->has_column($_) } @{ $self->config->{'id_field'} };
  0            
  0            
44              
45             ## if we have lazyloading turned on - we should not query the DB unless something gets read.
46             ## that's the idea anyway - still have to work out how to manage that - so for now we always force
47             ## lazyload to off.
48 0           $self->config->{lazyload} = 0;
49              
50             # if (!$self->config->{lazyload}) {
51             # return $self->load_user($authinfo, $c);
52             # } else {
53             # ## what do we do with a lazyload?
54             # ## presumably this is coming out of session storage.
55             # ## use $authinfo to fill in the user in that case?
56             # }
57              
58 0           return $self;
59             }
60              
61              
62             sub load {
63 0     0 1   my ($self, $authinfo, $c) = @_;
64              
65 0           my $dbix_class_config = 0;
66              
67 0 0         if (exists($authinfo->{'dbix_class'})) {
68 0           $authinfo = $authinfo->{'dbix_class'};
69 0           $dbix_class_config = 1;
70             }
71              
72             ## User can provide an arrayref containing the arguments to search on the user class.
73             ## or even provide a prepared resultset, allowing maximum flexibility for user retreival.
74             ## these options are only available when using the dbix_class authinfo hash.
75 0 0 0       if ($dbix_class_config && exists($authinfo->{'resultset'})) {
    0 0        
76 0           $self->_user($authinfo->{'resultset'}->first);
77             } elsif ($dbix_class_config && exists($authinfo->{'searchargs'})) {
78 0           $self->_user($self->resultset->search(@{$authinfo->{'searchargs'}})->first);
  0            
79             } else {
80             ## merge the ignore fields array into a hash - so we can do an easy check while building the query
81 0           my %ignorefields = map { $_ => 1} @{$self->config->{'ignore_fields_in_find'}};
  0            
  0            
82 0           my $searchargs = {};
83              
84             # now we walk all the fields passed in, and build up a search hash.
85 0           foreach my $key (grep {!$ignorefields{$_}} keys %{$authinfo}) {
  0            
  0            
86 0 0         if ($self->resultset->result_source->has_column($key)) {
87 0           $searchargs->{$key} = $authinfo->{$key};
88             }
89             }
90 0 0         if (keys %{$searchargs}) {
  0            
91 0           $self->_user($self->resultset->search($searchargs)->first);
92             } else {
93             Catalyst::Exception->throw(
94 0           "Failed to load user data. You passed [" . join(',', keys %{$authinfo}) . "]"
95 0           . " to authenticate() but your user source (" . $self->config->{'user_model'} . ")"
96             . " only has these columns: [" . join( ",", $self->resultset->result_source->columns ) . "]"
97             . " Check your authenticate() call."
98             );
99             }
100             }
101              
102 0 0         if ($self->get_object) {
103 0           return $self;
104             } else {
105 0           return undef;
106             }
107              
108             }
109              
110             sub supported_features {
111 0     0 1   my $self = shift;
112              
113             return {
114 0           session => 1,
115             roles => 1,
116             };
117             }
118              
119              
120             sub roles {
121 0     0 1   my ( $self ) = shift;
122             ## this used to load @wantedroles - but that doesn't seem to be used by the roles plugin, so I dropped it.
123              
124             ## shortcut if we have already retrieved them
125 0 0         if (ref $self->_roles eq 'ARRAY') {
126 0           return(@{$self->_roles});
  0            
127             }
128              
129 0           my @roles = ();
130 0 0         if (exists($self->config->{'role_column'})) {
    0          
131 0           my $role_data = $self->get($self->config->{'role_column'});
132 0 0         if ($role_data) {
133 0           @roles = split /[\s,\|]+/, $self->get($self->config->{'role_column'});
134             }
135 0           $self->_roles(\@roles);
136             } elsif (exists($self->config->{'role_relation'})) {
137 0           my $relation = $self->config->{'role_relation'};
138 0 0         if ($self->_user->$relation->result_source->has_column($self->config->{'role_field'})) {
139             @roles = map {
140             $_->get_column($self->config->{role_field})
141 0           } $self->_user->$relation->search(undef, {
142 0           columns => [ $self->config->{role_field} ]
143             })->all;
144 0           $self->_roles(\@roles);
145             } else {
146 0           Catalyst::Exception->throw("role table does not have a column called " . $self->config->{'role_field'});
147             }
148             } else {
149 0           Catalyst::Exception->throw("user->roles accessed, but no role configuration found");
150             }
151              
152 0           return @{$self->_roles};
  0            
153             }
154              
155             sub for_session {
156 0     0 1   my $self = shift;
157              
158             #return $self->get($self->config->{'id_field'});
159              
160             #my $frozenuser = $self->_user->result_source->schema->freeze( $self->_user );
161             #return $frozenuser;
162              
163 0           my %userdata = $self->_user->get_columns();
164 0           return \%userdata;
165             }
166              
167             sub from_session {
168 0     0 1   my ($self, $frozenuser, $c) = @_;
169              
170             #my $obj = $self->resultset->result_source->schema->thaw( $frozenuser );
171             #$self->_user($obj);
172              
173             #if (!exists($self->config->{'use_userdata_from_session'}) || $self->config->{'use_userdata_from_session'} == 0) {
174             # $self->_user->discard_changes();
175             # }
176             #
177             # return $self;
178             #
179             ## if use_userdata_from_session is defined in the config, we fill in the user data from the session.
180 0 0 0       if (exists($self->config->{'use_userdata_from_session'}) && $self->config->{'use_userdata_from_session'} != 0) {
181 0           my $obj = $self->resultset->new_result({ %$frozenuser });
182 0           $obj->in_storage(1);
183 0           $self->_user($obj);
184 0           return $self;
185             }
186              
187 0 0         if (ref $frozenuser eq 'HASH') {
188             return $self->load({
189 0           map { ($_ => $frozenuser->{$_}) }
190 0           @{ $self->config->{id_field} }
  0            
191             });
192             }
193              
194 0           return $self->load( { $self->config->{'id_field'} => $frozenuser }, $c);
195             }
196              
197             sub get {
198 0     0 1   my ($self, $field) = @_;
199              
200 0 0         if ($self->_user->can($field)) {
201 0           return $self->_user->$field;
202             } else {
203 0           return undef;
204             }
205             }
206              
207             sub get_object {
208 0     0 1   my ($self, $force) = @_;
209              
210 0 0         if ($force) {
211 0           $self->_user->discard_changes;
212             }
213              
214 0           return $self->_user;
215             }
216              
217             sub obj {
218 0     0 1   my ($self, $force) = @_;
219              
220 0           return $self->get_object($force);
221             }
222              
223             sub auto_create {
224 0     0 1   my $self = shift;
225 0           $self->_user( $self->resultset->auto_create( @_ ) );
226 0           return $self;
227             }
228              
229             sub auto_update {
230 0     0 1   my $self = shift;
231 0           $self->_user->auto_update( @_ );
232             }
233              
234             sub AUTOLOAD {
235 0     0     my $self = shift;
236 0           (my $method) = (our $AUTOLOAD =~ /([^:]+)$/);
237 0 0         return if $method eq "DESTROY";
238              
239 0           $self->_user->$method(@_);
240             }
241              
242             1;
243             __END__
244              
245             =head1 NAME
246              
247             Catalyst::Authentication::Store::DBIx::Class::User - The backing user
248             class for the Catalyst::Authentication::Store::DBIx::Class storage
249             module.
250              
251             =head1 VERSION
252              
253             This documentation refers to version 0.1100.
254              
255             =head1 SYNOPSIS
256              
257             Internal - not used directly, please see
258             L<Catalyst::Authentication::Store::DBIx::Class> for details on how to
259             use this module. If you need more information than is present there, read the
260             source.
261              
262              
263              
264             =head1 DESCRIPTION
265              
266             The Catalyst::Authentication::Store::DBIx::Class::User class implements user storage
267             connected to an underlying DBIx::Class schema object.
268              
269             =head1 SUBROUTINES / METHODS
270              
271             =head2 new
272              
273             Constructor.
274              
275             =head2 load ( $authinfo, $c )
276              
277             Retrieves a user from storage using the information provided in $authinfo.
278              
279             =head2 supported_features
280              
281             Indicates the features supported by this class. These are currently Roles and Session.
282              
283             =head2 roles
284              
285             Returns an array of roles associated with this user, if roles are configured for this user class.
286              
287             =head2 for_session
288              
289             Returns a serialized user for storage in the session.
290              
291             =head2 from_session
292              
293             Revives a serialized user from storage in the session.
294              
295             =head2 get ( $fieldname )
296              
297             Returns the value of $fieldname for the user in question. Roughly translates to a call to
298             the DBIx::Class::Row's get_column( $fieldname ) routine.
299              
300             =head2 get_object
301              
302             Retrieves the DBIx::Class object that corresponds to this user
303              
304             =head2 obj (method)
305              
306             Synonym for get_object
307              
308             =head2 auto_create
309              
310             This is called when the auto_create_user option is turned on in
311             Catalyst::Plugin::Authentication and a user matching the authinfo provided is not found.
312             By default, this will call the C<auto_create()> method of the resultset associated
313             with this object. It is up to you to implement that method.
314              
315             =head2 auto_update
316              
317             This is called when the auto_update_user option is turned on in
318             Catalyst::Plugin::Authentication. Note that by default the DBIx::Class store
319             uses every field in the authinfo hash to match the user. This means any
320             information you provide with the intent to update must be ignored during the
321             user search process. Otherwise the information will most likely cause the user
322             record to not be found. To ignore fields in the search process, you
323             have to add the fields you wish to update to the 'ignore_fields_in_find'
324             authinfo element. Alternately, you can use one of the advanced row retrieval
325             methods (searchargs or resultset).
326              
327             By default, auto_update will call the C<auto_update()> method of the
328             DBIx::Class::Row object associated with the user. It is up to you to implement
329             that method (probably in your schema file)
330              
331             =head1 BUGS AND LIMITATIONS
332              
333             None known currently, please email the author if you find any.
334              
335             =head1 AUTHOR
336              
337             Jason Kuri (jayk@cpan.org)
338              
339             =head1 LICENSE
340              
341             Copyright (c) 2007 the aforementioned authors. All rights
342             reserved. This program is free software; you can redistribute
343             it and/or modify it under the same terms as Perl itself.
344              
345             =cut