typo fixing
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Authentication / Realm.pm
CommitLineData
e0499ed6 1package Catalyst::Authentication::Realm;
810966b5 2
3use strict;
4use warnings;
2c7d23af 5
810966b5 6use base qw/Class::Accessor::Fast/;
7
8BEGIN {
9 __PACKAGE__->mk_accessors(qw/store credential name config/);
10};
11
9a37ffba 12## Add use_session config item to realm.
13
810966b5 14sub new {
15 my ($class, $realmname, $config, $app) = @_;
16
17 my $self = { config => $config };
18 bless $self, $class;
19
20 $self->name($realmname);
21
9a37ffba 22 if (!exists($self->config->{'use_session'})) {
23 if (exists($app->config->{'Plugin::Authentication'}{'use_session'})) {
24 $self->config->{'use_session'} = $app->config->{'Plugin::Authentication'}{'use_session'};
25 } else {
26 $self->config->{'use_session'} = 1;
27 }
28 }
9c08483f 29
810966b5 30 $app->log->debug("Setting up auth realm $realmname") if $app->debug;
8513d51b 31
32 # use the Null store as a default
33 if( ! exists $config->{store}{class} ) {
0f673ca7 34 $config->{store}{class} = '+Catalyst::Authentication::Store::Null';
8513d51b 35 $app->log->debug( qq(No Store specified for realm "$realmname", using the Null store.) );
810966b5 36 }
810966b5 37 my $storeclass = $config->{'store'}{'class'};
38
39 ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
40 ## taken to mean C::P::A::Store::(specifiedclass)
41 if ($storeclass !~ /^\+(.*)$/ ) {
0f673ca7 42 $storeclass = "Catalyst::Authentication::Store::${storeclass}";
810966b5 43 } else {
44 $storeclass = $1;
45 }
810966b5 46
47 # a little niceness - since most systems seem to use the password credential class,
48 # if no credential class is specified we use password.
0f673ca7 49 $config->{credential}{class} ||= '+Catalyst::Authentication::Credential::Password';
810966b5 50
51 my $credentialclass = $config->{'credential'}{'class'};
52
53 ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
0f673ca7 54 ## taken to mean C::A::Credential::(specifiedclass)
810966b5 55 if ($credentialclass !~ /^\+(.*)$/ ) {
0f673ca7 56 $credentialclass = "Catalyst::Authentication::Credential::${credentialclass}";
810966b5 57 } else {
58 $credentialclass = $1;
59 }
60
0f673ca7 61 # if we made it here - we have what we need to load the classes
62
63 ### BACKWARDS COMPATIBILITY - DEPRECATION WARNING:
64 ### we must eval the ensure_class_loaded - because we might need to try the old-style
65 ### ::Plugin:: module naming if the standard method fails.
66
71486cb0 67 ## Note to self - catch second exception and bitch in detail?
68
0f673ca7 69 eval {
70 Catalyst::Utils::ensure_class_loaded( $credentialclass );
71 };
72
73 if ($@) {
74 $app->log->warn( qq(Credential class "$credentialclass" not found, trying deprecated ::Plugin:: style naming. ) );
71486cb0 75 my $origcredentialclass = $credentialclass;
0f673ca7 76 $credentialclass =~ s/Catalyst::Authentication/Catalyst::Plugin::Authentication/;
71486cb0 77
78 eval { Catalyst::Utils::ensure_class_loaded( $credentialclass ); };
79 if ($@) {
80 Carp::croak "Unable to load credential class, " . $origcredentialclass . " OR " . $credentialclass .
81 " in realm " . $self->name;
82 }
0f673ca7 83 }
84
85 eval {
86 Catalyst::Utils::ensure_class_loaded( $storeclass );
87 };
88
89 if ($@) {
90 $app->log->warn( qq(Store class "$storeclass" not found, trying deprecated ::Plugin:: style naming. ) );
71486cb0 91 my $origstoreclass = $storeclass;
0f673ca7 92 $storeclass =~ s/Catalyst::Authentication/Catalyst::Plugin::Authentication/;
71486cb0 93 eval { Catalyst::Utils::ensure_class_loaded( $storeclass ); };
94 if ($@) {
95 Carp::croak "Unable to load store class, " . $origstoreclass . " OR " . $storeclass .
96 " in realm " . $self->name;
97 }
0f673ca7 98 }
810966b5 99
100 # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms
101 # of get_user and add it to the class. this is because the auth routines use find_user,
102 # and rely on it being present. (this avoids per-call checks)
103 if (!$storeclass->can('find_user')) {
104 no strict 'refs';
105 *{"${storeclass}::find_user"} = sub {
106 my ($self, $info) = @_;
107 my @rest = @{$info->{rest}} if exists($info->{rest});
108 $self->get_user($info->{id}, @rest);
109 };
110 }
111
112 ## a little cruft to stay compatible with some poorly written stores / credentials
113 ## we'll remove this soon.
114 if ($storeclass->can('new')) {
115 $self->store($storeclass->new($config->{'store'}, $app, $self));
116 } else {
117 $app->log->error("THIS IS DEPRECATED: $storeclass has no new() method - Attempting to use uninstantiated");
118 $self->store($storeclass);
119 }
120 if ($credentialclass->can('new')) {
121 $self->credential($credentialclass->new($config->{'credential'}, $app, $self));
122 } else {
123 $app->log->error("THIS IS DEPRECATED: $credentialclass has no new() method - Attempting to use uninstantiated");
124 $self->credential($credentialclass);
125 }
126
127 return $self;
128}
129
130sub find_user {
131 my ( $self, $authinfo, $c ) = @_;
132
133 my $res = $self->store->find_user($authinfo, $c);
134
4437366d 135 if (!$res) {
9b840849 136 if ($self->config->{'auto_create_user'} && $self->store->can('auto_create_user') ) {
137 $res = $self->store->auto_create_user($authinfo, $c);
4437366d 138 }
9b840849 139 } elsif ($self->config->{'auto_update_user'} && $self->store->can('auto_update_user')) {
140 $res = $self->store->auto_update_user($authinfo, $c, $res);
4437366d 141 }
810966b5 142
143 return $res;
144}
145
146sub authenticate {
147 my ($self, $c, $authinfo) = @_;
148
149 my $user = $self->credential->authenticate($c, $self, $authinfo);
150 if (ref($user)) {
151 $c->set_authenticated($user, $self->name);
152 return $user;
153 } else {
154 return undef;
155 }
156}
157
71486cb0 158sub user_is_restorable {
159 my ($self, $c) = @_;
160
161 return unless
162 $c->isa("Catalyst::Plugin::Session")
9a37ffba 163 and $self->config->{'use_session'}
71486cb0 164 and $c->session_is_valid;
810966b5 165
71486cb0 166 return $c->session->{__user};
167}
168
169sub restore_user {
170 my ($self, $c, $frozen_user) = @_;
810966b5 171
71486cb0 172 $frozen_user ||= $self->user_is_restorable($c);
173 return unless defined($frozen_user);
174
9c08483f 175 my $user = $self->from_session( $c, $frozen_user );
71486cb0 176
9c08483f 177 if ($user) {
178 $c->_user( $user );
71486cb0 179
9c08483f 180 # this sets the realm the user originated in.
181 $user->auth_realm($self->name);
182 } else {
183 Catalyst::Exception->throw("Store claimed to have a restorable user, but restoration failed. Did you change the user's id_field?");
184 }
185
71486cb0 186 return $user;
187}
188
189sub persist_user {
190 my ($self, $c, $user) = @_;
191
192 if (
193 $c->isa("Catalyst::Plugin::Session")
9a37ffba 194 and $self->config->{'use_session'}
71486cb0 195 and $user->supports("session")
196 ) {
197 $c->session->{__user_realm} = $self->name;
198
199 # we want to ask the store for a user prepared for the session.
200 # but older modules split this functionality between the user and the
201 # store. We try the store first. If not, we use the old method.
202 if ($self->store->can('for_session')) {
203 $c->session->{__user} = $self->store->for_session($c, $user);
204 } else {
205 $c->session->{__user} = $user->for_session;
206 }
810966b5 207 }
71486cb0 208 return $user;
209}
210
211sub remove_persisted_user {
212 my ($self, $c) = @_;
213
214 if (
215 $c->isa("Catalyst::Plugin::Session")
9a37ffba 216 and $self->config->{'use_session'}
71486cb0 217 and $c->session_is_valid
218 ) {
219 delete @{ $c->session }{qw/__user __user_realm/};
220 }
221}
222
223## backwards compatibility - I don't think many people wrote realms since they
224## have only existed for a short time - but just in case.
225sub save_user_in_session {
226 my ( $self, $c, $user ) = @_;
227
228 return $self->persist_user($c, $user);
810966b5 229}
230
231sub from_session {
232 my ($self, $c, $frozen_user) = @_;
233
234 return $self->store->from_session($c, $frozen_user);
235}
236
237
238__PACKAGE__;
239
b72f8c2e 240__END__
2c7d23af 241
242=pod
243
244=head1 NAME
245
e0499ed6 246Catalyst::Authentication::Realm - Base class for realm objects.
2c7d23af 247
248=head1 DESCRIPTION
249
d2ca09b8 250=head1 CONFIGURATION
2c7d23af 251
252=over 4
253
d2ca09b8 254=item class
255
71486cb0 256By default this class is used by
257L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> for all
258realms. The class parameter allows you to choose a different class to use for
259this realm. Creating a new Realm class can allow for authentication methods
260that fall outside the normal credential/store methodology.
deebc899 261
d2ca09b8 262=item auto_create_user
2c7d23af 263
deebc899 264Set this to true if you wish this realm to auto-create user accounts when the
265user doesn't exist (most useful for remote authentication schemes).
266
d2ca09b8 267=item auto_update_user
2c7d23af 268
deebc899 269Set this to true if you wish this realm to auto-update user accounts after
270authentication (most useful for remote authentication schemes).
271
d2ca09b8 272=back
273
274=head1 METHODS
2c7d23af 275
71486cb0 276=head2 new( $realmname, $config, $app )
2c7d23af 277
deebc899 278Instantiantes this realm, plus the specified store and credential classes.
279
280=head2 store( )
281
71486cb0 282Returns an instance of the store object for this realm.
deebc899 283
284=head2 credential( )
285
71486cb0 286Returns an instance of the credential object for this realm.
deebc899 287
71486cb0 288=head2 find_user( $authinfo, $c )
d2ca09b8 289
71486cb0 290Retrieves the user given the authentication information provided. This
291is most often called from the credential. The default realm class simply
292delegates this call the store object. If enabled, auto-creation and
293auto-updating of users is also handled here.
deebc899 294
71486cb0 295=head2 authenticate( $c, $authinfo)
d2ca09b8 296
71486cb0 297Performs the authentication process for the current realm. The default
298realm class simply delegates this to the credential and sets
299the authenticated user on success. Returns the authenticated user object;
deebc899 300
84ebeae8 301=head2 save_user_in_session($c, $user)
d2ca09b8 302
71486cb0 303Used to save the user in a session. Saves $user in the current session,
304marked as originating in the current realm. Calls $store->for_session() by
305default. If for_session is not available in the store class, will attempt
306to call $user->for_session().
deebc899 307
bc119a79 308=head2 persist_user($c, $user)
309
310Takes the user data and persists it in the sessi.on
311
312=head2 remove_persisted_user($c)
313
314Removes any persisted user data in the session.
315
316=head2 restore_user($c, [$frozen_user])
317
318Restores the user from parameter, or the session by default.
319
320=head2 user_is_restorable( $c )
321
322Predicate to tell you if the current session has restorable user data.
323
71486cb0 324=head2 from_session($c, $frozenuser )
2c7d23af 325
71486cb0 326Triggers restoring of the user from data in the session. The default realm
327class simply delegates the call to $store->from_session($c, $frozenuser);
deebc899 328
2c7d23af 329=cut
330