Tiny example for register_auth_stores
[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
e145babc 18#BEGIN {
19# require constant;
20# constant->import(have_want => eval { require Want });
21#}
a1e5bd36 22
e09a839c 23our $VERSION = "0.02";
c7c003d3 24
06675d2e 25sub set_authenticated {
26 my ( $c, $user ) = @_;
27
28 $c->user($user);
e300c5b6 29 $c->request->{user} = $user; # compatibility kludge
06675d2e 30
31 if ( $c->isa("Catalyst::Plugin::Session")
96777f3a 32 and $c->config->{authentication}{use_session}
12dae309 33 and $user->supports("session") )
06675d2e 34 {
12dae309 35 $c->save_user_in_session($user);
06675d2e 36 }
55395841 37
4fbe2e14 38 $c->NEXT::set_authenticated($user);
06675d2e 39}
40
7bb06c91 41sub user {
e300c5b6 42 my $c = shift;
7bb06c91 43
e300c5b6 44 if (@_) {
45 return $c->_user(@_);
46 }
7bb06c91 47
e300c5b6 48 my $user = $c->_user;
7bb06c91 49
e300c5b6 50 if ( $user and !Scalar::Util::blessed($user) ) {
cde43a59 51# return 1 if have_want() && Want::want("BOOL");
e300c5b6 52 return $c->auth_restore_user($user);
53 }
7bb06c91 54
e300c5b6 55 return $user;
7bb06c91 56}
57
ce0b058d 58sub user_exists {
59 my $c = shift;
60 return defined($c->_user);
61}
62
12dae309 63sub save_user_in_session {
e300c5b6 64 my ( $c, $user ) = @_;
12dae309 65
66 my $store = $user->store || ref $user;
67 $c->session->{__user_store} = $c->get_auth_store_name($store) || $store;
68 $c->session->{__user} = $user->for_session;
69}
70
06675d2e 71sub logout {
72 my $c = shift;
73
74 $c->user(undef);
b003080b 75
76 if ( $c->isa("Catalyst::Plugin::Session")
77 and $c->config->{authentication}{use_session} )
78 {
96777f3a 79 delete @{ $c->session }{qw/__user __user_store/};
b003080b 80 }
06675d2e 81}
82
7d0922d8 83sub get_user {
84 my ( $c, $uid ) = @_;
85
86 if ( my $store = $c->default_auth_store ) {
87 return $store->get_user($uid);
88 }
89 else {
90 Catalyst::Exception->throw(
91 "The user id $uid was passed to an authentication "
92 . "plugin, but no default store was specified" );
93 }
94}
95
06675d2e 96sub prepare {
97 my $c = shift->NEXT::prepare(@_);
98
4fbe2e14 99 if ( $c->isa("Catalyst::Plugin::Session")
06675d2e 100 and !$c->user )
101 {
7bb06c91 102 if ( $c->sessionid and my $frozen_user = $c->session->{__user} ) {
e300c5b6 103 $c->_user($frozen_user);
06675d2e 104 }
105 }
106
107 return $c;
108}
109
7bb06c91 110sub auth_restore_user {
e300c5b6 111 my ( $c, $frozen_user, $store_name ) = @_;
7bb06c91 112
4fbe2e14 113 return
cde43a59 114 unless $c->isa("Catalyst::Plugin::Session")
4fbe2e14 115 and $c->config->{authentication}{use_session}
116 and $c->sessionid;
4402d92d 117
e300c5b6 118 $store_name ||= $c->session->{__user_store};
119 $frozen_user ||= $c->session->{__user};
7bb06c91 120
e300c5b6 121 my $store = $c->get_auth_store($store_name);
122 $c->_user( my $user = $store->from_session( $c, $frozen_user ) );
7bb06c91 123
e300c5b6 124 return $user;
7bb06c91 125
126}
127
06675d2e 128sub setup {
129 my $c = shift;
130
712a35bf 131 my $cfg = $c->config->{authentication} || {};
06675d2e 132
133 %$cfg = (
134 use_session => 1,
135 %$cfg,
136 );
b003080b 137
12dae309 138 $c->register_auth_stores(
139 default => $cfg->{store},
140 %{ $cfg->{stores} || {} },
141 );
96777f3a 142
b003080b 143 $c->NEXT::setup(@_);
06675d2e 144}
145
96777f3a 146sub get_auth_store {
12dae309 147 my ( $self, $name ) = @_;
148 $self->auth_stores->{$name} || ( Class::Inspector->loaded($name) && $name );
96777f3a 149}
150
151sub get_auth_store_name {
12dae309 152 my ( $self, $store ) = @_;
153 $self->auth_store_names->{$store};
96777f3a 154}
155
156sub register_auth_stores {
12dae309 157 my ( $self, %new ) = @_;
96777f3a 158
12dae309 159 foreach my $name ( keys %new ) {
160 my $store = $new{$name} or next;
161 $self->auth_stores->{$name} = $store;
162 $self->auth_store_names->{$store} = $name;
163 }
96777f3a 164}
165
166sub auth_stores {
12dae309 167 my $self = shift;
168 $self->_auth_stores(@_) || $self->_auth_stores( {} );
96777f3a 169}
170
171sub auth_store_names {
12dae309 172 my $self = shift;
96777f3a 173
4402d92d 174 $self->_auth_store_names || do {
12dae309 175 tie my %hash, 'Tie::RefHash';
176 $self->_auth_store_names( \%hash );
4fbe2e14 177 }
96777f3a 178}
179
180sub default_auth_store {
12dae309 181 my $self = shift;
96777f3a 182
12dae309 183 if ( my $new = shift ) {
184 $self->register_auth_stores( default => $new );
185 }
96777f3a 186
12dae309 187 $self->get_auth_store("default");
96777f3a 188}
189
06675d2e 190__PACKAGE__;
191
192__END__
193
194=pod
195
196=head1 NAME
197
55395841 198Catalyst::Plugin::Authentication - Infrastructure plugin for the Catalyst
199authentication framework.
06675d2e 200
201=head1 SYNOPSIS
202
189b5b0c 203 use Catalyst qw/
204 Authentication
205 Authentication::Store::Foo
206 Authentication::Credential::Password
207 /;
208
209 # later on ...
210 # ->login is provided by the Credential::Password module
211 $c->login('myusername', 'mypassword');
212 my $age = $c->user->age;
213 $c->logout;
06675d2e 214
215=head1 DESCRIPTION
216
e7522758 217The authentication plugin provides generic user support. It is the basis
218for both authentication (checking the user is who they claim to be), and
219authorization (allowing the user to do what the system authorises them to do).
06675d2e 220
e7522758 221Using authentication is split into two parts. A Store is used to actually
222store the user information, and can store any amount of data related to
223the user. Multiple stores can be accessed from within one application.
224Credentials are used to verify users, using the store, given data from
225the frontend.
189b5b0c 226
e7522758 227To implement authentication in a catalyst application you need to add this
228module, plus at least one store and one credential module.
189b5b0c 229
e7522758 230Authentication data can also be stored in a session, if the application
231is using the L<Catalyst::Plugin::Session> module.
06675d2e 232
233=head1 METHODS
234
235=over 4
236
06675d2e 237=item user
238
189b5b0c 239Returns the currently logged in user or undef if there is none.
06675d2e 240
ce0b058d 241=item user_exists
242
243Whether or not a user is logged in right now.
244
245The reason this method exists is that C<<$c->user>> may needlessly load the
246user from the auth store.
247
248If you're just going to say
249
250 if ( $c->user_user ) {
251 # foo
252 } else {
253 $c->forward("login");
254 }
255
256it should be more efficient than C<<$c->user>> when a user is marked in the session
257but C<<$c->user>> hasn't been called yet.
258
4402d92d 259=item logout
260
261Delete the currently logged in user from C<user> and the session.
262
7d0922d8 263=item get_user $uid
264
189b5b0c 265Fetch a particular users details, defined by the given ID, via the default store.
266
267=back
268
269=head1 CONFIGURATION
270
271=over 4
272
273=item use_session
274
275Whether or not to store the user's logged in state in the session, if the
e7522758 276application is also using the L<Catalyst::Plugin::Session> plugin. This
277value is set to true per default.
278
279=item store
280
281If multiple stores are being used, name the store you want as default here.
7d0922d8 282
4fbe2e14 283=back
284
285=head1 METHODS FOR STORE MANAGEMENT
286
fe4cf44a 287=over 4
288
7d0922d8 289=item default_auth_store
290
4fbe2e14 291Return the store whose name is 'default'.
7d0922d8 292
189b5b0c 293This is set to C<< $c->config->{authentication}{store} >> if that value exists,
4fbe2e14 294or by using a Store plugin:
295
296 use Catalyst qw/Authentication Authentication::Store::Minimal/;
297
298Sets the default store to
299L<Catalyst::Plugin::Authentication::Store::Minimal::Backend>.
300
a1e5bd36 301
4fbe2e14 302=item get_auth_store $name
303
304Return the store whose name is $name.
305
306=item get_auth_store_name $store
307
308Return the name of the store $store.
309
310=item auth_stores
311
312A hash keyed by name, with the stores registered in the app.
313
314=item auth_store_names
315
316A ref-hash keyed by store, which contains the names of the stores.
317
318=item register_auth_stores %stores_by_name
319
320Register stores into the application.
06675d2e 321
fe4cf44a 322=back
323
06675d2e 324=head1 INTERNAL METHODS
325
326=over 4
327
328=item set_authenticated $user
329
330Marks a user as authenticated. Should be called from a
331C<Catalyst::Plugin::Authentication::Credential> plugin after successful
332authentication.
333
334This involves setting C<user> and the internal data in C<session> if
335L<Catalyst::Plugin::Session> is loaded.
336
e300c5b6 337=item auth_restore_user $user
338
339Used to restore a user from the session, by C<user> only when it's actually
340needed.
341
342=item save_user_in_session $user
343
344Used to save the user in a session.
345
06675d2e 346=item prepare
347
348Revives a user from the session object if there is one.
349
350=item setup
351
352Sets the default configuration parameters.
353
354=item
355
356=back
357
fbe577ac 358=head1 SEE ALSO
359
360L<Catalyst::Plugin::Authentication::Credential::Password>,
361L<Catalyst::Plugin::Authentication::Store::Minimal>,
362L<Catalyst::Plugin::Authorization::ACL>,
363L<Catalyst::Plugin::Authorization::Roles>.
364
365=head1 AUTHOR
366
367Yuval Kogman, C<nothingmuch@woobling.org>
06675d2e 368
fbe577ac 369=head1 COPYRIGHT & LICNESE
370
371 Copyright (c) 2005 the aforementioned authors. All rights
372 reserved. This program is free software; you can redistribute
373 it and/or modify it under the same terms as Perl itself.
374
375=cut
06675d2e 376