Moving to new namespace
[catagits/Catalyst-Authentication-Store-DBIx-Class.git] / lib / Catalyst / Authentication / Store / DBIx / Class / User.pm
CommitLineData
5000f545 1package Catalyst::Plugin::Authentication::Store::DBIx::Class::User;
2
3use strict;
4use warnings;
5use base qw/Catalyst::Plugin::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
171sub AUTOLOAD {
172 my $self = shift;
173 (my $method) = (our $AUTOLOAD =~ /([^:]+)$/);
174 return if $method eq "DESTROY";
175
ff7203cb 176 $self->_user->$method(@_);
5000f545 177}
178
1791;
180__END__
181
182=head1 NAME
183
c1d29ab7 184Catalyst::Plugin::Authentication::Store::DBIx::Class::User - The backing user
185class for the Catalyst::Plugin::Authentication::Store::DBIx::Class storage
186module.
5000f545 187
188=head1 VERSION
189
ad93b3e9 190This documentation refers to version 0.10.
5000f545 191
192=head1 SYNOPSIS
193
c1d29ab7 194Internal - not used directly, please see
195L<Catalyst::Plugin::Authentication::Store::DBIx::Class> for details on how to
196use this module. If you need more information than is present there, read the
197source.
93102ff5 198
199
5000f545 200
201=head1 DESCRIPTION
202
c1d29ab7 203The Catalyst::Plugin::Authentication::Store::DBIx::Class::User class implements user storage
204connected to an underlying DBIx::Class schema object.
5000f545 205
206=head1 SUBROUTINES / METHODS
207
c1d29ab7 208=head2 new
5000f545 209
c1d29ab7 210Constructor.
5000f545 211
fbe76043 212=head2 load ( $authinfo, $c )
5000f545 213
c1d29ab7 214Retrieves a user from storage using the information provided in $authinfo.
5000f545 215
c1d29ab7 216=head2 supported_features
5000f545 217
c1d29ab7 218Indicates the features supported by this class. These are currently Roles and Session.
5000f545 219
220=head2 roles
221
c1d29ab7 222Returns an array of roles associated with this user, if roles are configured for this user class.
5000f545 223
224=head2 for_session
225
c1d29ab7 226Returns a serialized user for storage in the session. Currently, this is the value of the field
227specified by the 'id_field' config variable.
5000f545 228
fbe76043 229=head2 from_session
230
231Revives a serialized user from storage in the session. Currently, this uses the serialized data as the
232value of the 'id_field' config variable.
233
c1d29ab7 234=head2 get ( $fieldname )
5000f545 235
c1d29ab7 236Returns the value of $fieldname for the user in question. Roughly translates to a call to
237the DBIx::Class::Row's get_column( $fieldname ) routine.
5000f545 238
c1d29ab7 239=head2 get_object
5000f545 240
c1d29ab7 241Retrieves the DBIx::Class object that corresponds to this user
5000f545 242
243=head2 obj (method)
244
c1d29ab7 245Synonym for get_object
5000f545 246
247=head1 BUGS AND LIMITATIONS
248
249None known currently, please email the author if you find any.
250
251=head1 AUTHOR
252
fbe76043 253Jason Kuri (jayk@cpan.org)
5000f545 254
c1d29ab7 255=head1 LICENSE
5000f545 256
c1d29ab7 257Copyright (c) 2007 the aforementioned authors. All rights
258reserved. This program is free software; you can redistribute
259it and/or modify it under the same terms as Perl itself.
5000f545 260
261=cut