$c->user lazy restores from session
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Plugin / Authentication.pm
CommitLineData
06675d2e 1#!/usr/bin/perl
2
3package Catalyst::Plugin::Authentication;
4
b003080b 5use base qw/Class::Accessor::Fast Class::Data::Inheritable/;
06675d2e 6
b003080b 7BEGIN {
7bb06c91 8 __PACKAGE__->mk_accessors(qw/_user/);
96777f3a 9 __PACKAGE__->mk_classdata($_) for qw/_auth_stores _auth_store_names/;
b003080b 10}
06675d2e 11
12use strict;
13use warnings;
14
96777f3a 15use Tie::RefHash;
12dae309 16use Class::Inspector;
96777f3a 17
c7c003d3 18our $VERSION = "0.01";
19
06675d2e 20sub set_authenticated {
21 my ( $c, $user ) = @_;
22
23 $c->user($user);
24
25 if ( $c->isa("Catalyst::Plugin::Session")
96777f3a 26 and $c->config->{authentication}{use_session}
12dae309 27 and $user->supports("session") )
06675d2e 28 {
12dae309 29 $c->save_user_in_session($user);
06675d2e 30 }
31}
32
7bb06c91 33sub user {
34 my $c = shift;
35
36 if ( @_ ) {
37 return $c->_user( @_ );
38 }
39
40 my $user = $c->_user;
41
42 if ( $user and !Scalar::Util::blessed( $user ) ) {
43 return $c->auth_restore_user( $user );
44 }
45
46 return $user;
47}
48
12dae309 49sub save_user_in_session {
50 my ( $c, $user ) = @_;
51
52 my $store = $user->store || ref $user;
53 $c->session->{__user_store} = $c->get_auth_store_name($store) || $store;
54 $c->session->{__user} = $user->for_session;
55}
56
06675d2e 57sub logout {
58 my $c = shift;
59
60 $c->user(undef);
b003080b 61
62 if ( $c->isa("Catalyst::Plugin::Session")
63 and $c->config->{authentication}{use_session} )
64 {
96777f3a 65 delete @{ $c->session }{qw/__user __user_store/};
b003080b 66 }
06675d2e 67}
68
7d0922d8 69sub get_user {
70 my ( $c, $uid ) = @_;
71
72 if ( my $store = $c->default_auth_store ) {
73 return $store->get_user($uid);
74 }
75 else {
76 Catalyst::Exception->throw(
77 "The user id $uid was passed to an authentication "
78 . "plugin, but no default store was specified" );
79 }
80}
81
06675d2e 82sub prepare {
83 my $c = shift->NEXT::prepare(@_);
84
85 if ( $c->isa("Catalyst::Plugin::Session")
22be989b 86 and $c->default_auth_store
06675d2e 87 and !$c->user )
88 {
7bb06c91 89 if ( $c->sessionid and my $frozen_user = $c->session->{__user} ) {
90 $c->_user( $frozen_user );
06675d2e 91 }
92 }
93
94 return $c;
95}
96
7bb06c91 97sub auth_restore_user {
98 my ( $c, $frozen_user, $store_name ) = @_;
99
100 $store_name ||= $c->session->{__user_store};
101 $frozen_user ||= $c->session->{__user};
102
103 my $store = $c->get_auth_store( $store_name );
104 $c->_user( my $user = $store->from_session( $c, $frozen_user ) );
105 $c->request->{user} = $user; # compatibility kludge
106
107 return $user;
108
109}
110
06675d2e 111sub setup {
112 my $c = shift;
113
712a35bf 114 my $cfg = $c->config->{authentication} || {};
06675d2e 115
116 %$cfg = (
117 use_session => 1,
118 %$cfg,
119 );
b003080b 120
12dae309 121 $c->register_auth_stores(
122 default => $cfg->{store},
123 %{ $cfg->{stores} || {} },
124 );
96777f3a 125
b003080b 126 $c->NEXT::setup(@_);
06675d2e 127}
128
96777f3a 129sub get_auth_store {
12dae309 130 my ( $self, $name ) = @_;
131 $self->auth_stores->{$name} || ( Class::Inspector->loaded($name) && $name );
96777f3a 132}
133
134sub get_auth_store_name {
12dae309 135 my ( $self, $store ) = @_;
136 $self->auth_store_names->{$store};
96777f3a 137}
138
139sub register_auth_stores {
12dae309 140 my ( $self, %new ) = @_;
96777f3a 141
12dae309 142 foreach my $name ( keys %new ) {
143 my $store = $new{$name} or next;
144 $self->auth_stores->{$name} = $store;
145 $self->auth_store_names->{$store} = $name;
146 }
96777f3a 147}
148
149sub auth_stores {
12dae309 150 my $self = shift;
151 $self->_auth_stores(@_) || $self->_auth_stores( {} );
96777f3a 152}
153
154sub auth_store_names {
12dae309 155 my $self = shift;
96777f3a 156
12dae309 157 unless ( $self->_auth_store_names ) {
158 tie my %hash, 'Tie::RefHash';
159 $self->_auth_store_names( \%hash );
160 }
96777f3a 161
12dae309 162 $self->_auth_store_names;
96777f3a 163}
164
165sub default_auth_store {
12dae309 166 my $self = shift;
96777f3a 167
12dae309 168 if ( my $new = shift ) {
169 $self->register_auth_stores( default => $new );
170 }
96777f3a 171
12dae309 172 $self->get_auth_store("default");
96777f3a 173}
174
06675d2e 175__PACKAGE__;
176
177__END__
178
179=pod
180
181=head1 NAME
182
183Catalyst::Plugin::Authentication -
184
185=head1 SYNOPSIS
186
187 use Catalyst qw/
188 Authentication
189 Authentication::Store::Foo
190 Authentication::Credential::Password
191 /;
192
193=head1 DESCRIPTION
194
195The authentication plugin is used by the various authentication and
196authorization plugins in catalyst.
197
198It defines the notion of a logged in user, and provides integration with the
199
200=head1 METHODS
201
202=over 4
203
204=item logout
205
206Delete the currently logged in user from C<user> and the session.
207
208=item user
209
210Returns the currently logged user or undef if there is none.
211
7d0922d8 212=item get_user $uid
213
214Delegate C<get_user> to the default store.
215
216=item default_auth_store
217
218Returns C<< $c->config->{authentication}{store} >>.
219
06675d2e 220=back
221
222=head1 INTERNAL METHODS
223
224=over 4
225
226=item set_authenticated $user
227
228Marks a user as authenticated. Should be called from a
229C<Catalyst::Plugin::Authentication::Credential> plugin after successful
230authentication.
231
232This involves setting C<user> and the internal data in C<session> if
233L<Catalyst::Plugin::Session> is loaded.
234
235=item prepare
236
237Revives a user from the session object if there is one.
238
239=item setup
240
241Sets the default configuration parameters.
242
243=item
244
245=back
246
247=head1 CONFIGURATION
248
249=over 4
250
251=item use_session
252
253Whether or not to store the user's logged in state in the session, if the
254application is also using the L<Catalyst::Plugin::Authentication> plugin.
255
256=back
257
258=cut
259
260