9a08fbeeb2d28a323711ce76286c9866e1baa69b
[catagits/Catalyst-Authentication-Store-DBIx-Class.git] / lib / Catalyst / Plugin / Authentication / Store / DBIx / Class / User.pm
1 package Catalyst::Plugin::Authentication::Store::DBIx::Class::User;
2
3 use strict;
4 use warnings;
5 use base qw/Catalyst::Plugin::Authentication::User/;
6 use base qw/Class::Accessor::Fast/;
7
8 BEGIN {
9     __PACKAGE__->mk_accessors(qw/config resultset _user _roles/);
10 }
11
12 sub new {
13     my ( $class, $config, $c) = @_;
14
15     my $self = {
16         resultset => $c->model($config->{'user_class'}),
17         config => $config,
18         _roles => undef,
19         _user => undef
20     };
21     
22     bless $self, $class;
23     
24
25     
26     ## if we have lazyloading turned on - we should not query the DB unless something gets read.
27     ## that's the idea anyway - still have to work out how to manage that - so for now we always force
28     ## lazyload to off.
29     $self->config->{lazyload} = 0;
30     
31 #    if (!$self->config->{lazyload}) {
32 #        return $self->load_user($authinfo, $c);
33 #    } else {
34 #        ## what do we do with a lazyload?
35 #        ## presumably this is coming out of session storage.  
36 #        ## use $authinfo to fill in the user in that case?
37 #    }
38
39     return $self;
40 }
41
42
43 sub load {
44     my ($self, $authinfo, $c) = @_;
45     
46     my $dbix_class_config = 0;
47     
48     if (exists($authinfo->{'dbix_class'})) {
49         $authinfo = $authinfo->{'dbix_class'};
50         $dbix_class_config = 1;
51     }
52     
53     ## User can provide an arrayref containing the arguments to search on the user class.
54     ## or even provide a prepared resultset, allowing maximum flexibility for user retreival.
55     ## these options are only available when using the dbix_class authinfo hash. 
56     if ($dbix_class_config && exists($authinfo->{'resultset'})) {
57         $self->_user($authinfo->{'resultset'}->first);
58     } elsif ($dbix_class_config && exists($authinfo->{'searchargs'})) {
59         $self->_user($self->resultset->search(@{$authinfo->{'searchargs'}})->first);    
60     } else {
61         ## merge the ignore fields array into a hash - so we can do an easy check while building the query
62         my %ignorefields = map { $_ => 1} @{$self->config->{'ignore_fields_in_find'}};                                    
63         my $searchargs = {};
64         
65         # now we walk all the fields passed in, and build up a search hash.
66         foreach my $key (grep {!$ignorefields{$_}} keys %{$authinfo}) {
67             if ($self->resultset->result_source->has_column($key)) {
68                 $searchargs->{$key} = $authinfo->{$key};
69             }
70         }
71         $self->_user($self->resultset->search($searchargs)->first);
72     }
73
74     if ($self->get_object) {
75         return $self
76     } else {
77         return undef;
78     }
79     #$c->log->debug(dumper($self->{'user'}));
80
81 }
82
83 sub supported_features {
84     my $self = shift;
85
86     return {
87         session         => 1,
88         roles           => 1,
89     };
90 }
91
92
93 sub roles {
94     my ( $self ) = shift;
95     ## this used to load @wantedroles - but that doesn't seem to be used by the roles plugin, so I dropped it.
96
97     ## shortcut if we have already retrieved them
98     if (ref $self->_roles eq 'ARRAY') {
99         return(@{$self->_roles});
100     }
101     
102     my @roles = ();
103     if (exists($self->config->{'role_column'})) {
104         @roles = split /[ ,\|]/, $self->get($self->config->{'role_column'});
105         $self->_roles(\@roles);
106     } elsif (exists($self->config->{'role_relation'})) {
107         my $relation = $self->config->{'role_relation'};
108         if ($self->_user->$relation->result_source->has_column($self->config->{'role_field'})) {
109             @roles = map { $_->get_column($self->config->{'role_field'}) } $self->_user->$relation->search(undef, { columns => [ $self->config->{'role_field'}]})->all();
110             $self->_roles(\@roles);
111         } else {
112             Catalyst::Exception->throw("role table does not have a column called " . $self->config->{'role_field'});
113         }
114     } else {
115         Catalyst::Exception->throw("user->roles accessed, but no role configuration found");
116     }
117
118     return @{$self->_roles};
119 }
120
121 sub for_session {
122     my $self = shift;
123     
124     return $self->get('id');
125 }
126
127 sub from_session {
128     my ($self, $frozenuser, $c) = @_;
129     
130     # this could be a lot better.  But for now it just assumes $frozenuser is an id and uses find_user
131     # XXX: hits the database on every request?  Not good...
132     return $self->load( { id => $frozenuser }, $c);
133 }
134
135 sub get {
136     my ($self, $field) = @_;
137     
138     if ($self->_user->can($field)) {
139         return $self->_user->$field;
140     } else {
141         return undef;
142     }
143 }
144
145 sub obj {
146     my $self = shift;
147     
148     return $self->get_object;
149 }
150
151 sub get_object {
152     my $self = shift;
153     
154     return $self->_user;
155 }
156
157 sub AUTOLOAD {
158     my $self = shift;
159     (my $method) = (our $AUTOLOAD =~ /([^:]+)$/);
160     return if $method eq "DESTROY";
161
162     $self->_user->$method(@_);
163 }
164
165 1;
166 __END__
167
168 =head1 NAME
169
170 Catalyst::Plugin::Authentication::Store::DBIx::Class::User - A class to ...
171
172 =head1 VERSION
173
174 This documentation refers to version 0.01.
175
176 =head1 SYNOPSIS
177
178 use Catalyst::Plugin::Authentication::Store::DBIx::Class::User;
179
180 =head1 DESCRIPTION
181
182 The Catalyst::Plugin::Authentication::Store::DBIx::Class::User class implements ...
183
184 =head1 SUBROUTINES / METHODS
185
186 =head2 new (constructor)
187
188 Parameters:
189     class
190     authinfo
191     config
192     c
193     lazyload
194
195 Insert description of constructor here...
196
197 =head2 load_user (method)
198
199 Parameters:
200     authinfo
201     c
202
203 Insert description of method here...
204
205 =head2 supported_features (method)
206
207 Parameters:
208     none
209
210 Insert description of method here...
211
212 =head2 roles
213
214 Parameters:
215     none
216
217 Insert description of subroutine here...
218
219 =head2 for_session
220
221 Parameters:
222     none
223
224 Insert description of subroutine here...
225
226 =head2 get (method)
227
228 Parameters:
229     field
230
231 Insert description of method here...
232
233 =head2 obj (method)
234
235 Parameters:
236     none
237
238 Insert description of method here...
239
240 =head2 get_object (method)
241
242 Parameters:
243     none
244
245 Insert description of method here...
246
247 =head2 AUTOLOAD (method)
248
249 Parameters:
250     none
251
252 Insert description of method here...
253
254 =head1 DEPENDENCIES
255
256 Modules used, version dependencies, core yes/no
257
258 strict
259
260 warnings
261
262 =head1 NOTES
263
264 ...
265
266 =head1 BUGS AND LIMITATIONS
267
268 None known currently, please email the author if you find any.
269
270 =head1 AUTHOR
271
272 Jason Kuri (jk@domain.tld)
273
274 =head1 LICENCE
275
276 Copyright 2006 by Jason Kuri.
277
278 This software is free.  It is licensed under the same terms as Perl itself.
279
280 =cut