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