X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FAuthentication%2FRealm.pm;h=db9b4c27a81b3fe66965620872502ca435eb53b0;hb=f0312fca4a199bf694276f180d566ca4e4e28875;hp=25994b4b7994ca4e462213dd6340d603fbfd0f8d;hpb=aa4a1855cbb55e9026955901734df8ba0d85c60c;p=catagits%2FCatalyst-Plugin-Authentication.git diff --git a/lib/Catalyst/Authentication/Realm.pm b/lib/Catalyst/Authentication/Realm.pm index 25994b4..db9b4c2 100644 --- a/lib/Catalyst/Authentication/Realm.pm +++ b/lib/Catalyst/Authentication/Realm.pm @@ -26,13 +26,16 @@ sub new { $self->config->{'use_session'} = 1; } } - print STDERR "use session is " . $self->config->{'use_session'} . "\n"; + $app->log->debug("Setting up auth realm $realmname") if $app->debug; - # use the Null store as a default - if( ! exists $config->{store}{class} ) { + # use the Null store as a default - Don't complain if the realm class is being overridden, + # as the new realm may behave differently. + if( ! exists($config->{store}{class}) ) { $config->{store}{class} = '+Catalyst::Authentication::Store::Null'; - $app->log->debug( qq(No Store specified for realm "$realmname", using the Null store.) ); + if (! exists($config->{class})) { + $app->log->debug( qq(No Store specified for realm "$realmname", using the Null store.) ); + } } my $storeclass = $config->{'store'}{'class'}; @@ -71,12 +74,18 @@ sub new { }; if ($@) { + # If the file is missing, then try the old-style fallback, + # but re-throw anything else for the user to deal with. + die unless $@ =~ /^Can't locate/; $app->log->warn( qq(Credential class "$credentialclass" not found, trying deprecated ::Plugin:: style naming. ) ); my $origcredentialclass = $credentialclass; $credentialclass =~ s/Catalyst::Authentication/Catalyst::Plugin::Authentication/; eval { Catalyst::Utils::ensure_class_loaded( $credentialclass ); }; if ($@) { + # Likewise this croak is useful if the second exception is also "not found", + # but would be confusing if it's anything else. + die unless $@ =~ /^Can't locate/; Carp::croak "Unable to load credential class, " . $origcredentialclass . " OR " . $credentialclass . " in realm " . $self->name; } @@ -87,11 +96,17 @@ sub new { }; if ($@) { + # If the file is missing, then try the old-style fallback, + # but re-throw anything else for the user to deal with. + die unless $@ =~ /^Can't locate/; $app->log->warn( qq(Store class "$storeclass" not found, trying deprecated ::Plugin:: style naming. ) ); my $origstoreclass = $storeclass; $storeclass =~ s/Catalyst::Authentication/Catalyst::Plugin::Authentication/; eval { Catalyst::Utils::ensure_class_loaded( $storeclass ); }; if ($@) { + # Likewise this croak is useful if the second exception is also "not found", + # but would be confusing if it's anything else. + die unless $@ =~ /^Can't locate/; Carp::croak "Unable to load store class, " . $origstoreclass . " OR " . $storeclass . " in realm " . $self->name; } @@ -159,7 +174,7 @@ sub user_is_restorable { my ($self, $c) = @_; return unless - $c->isa("Catalyst::Plugin::Session") + $c->can('session') and $self->config->{'use_session'} and $c->session_is_valid; @@ -172,19 +187,37 @@ sub restore_user { $frozen_user ||= $self->user_is_restorable($c); return unless defined($frozen_user); - $c->_user( my $user = $self->from_session( $c, $frozen_user ) ); + my $user = $self->from_session( $c, $frozen_user ); - # this sets the realm the user originated in. - $user->auth_realm($self->name); + if ($user) { + $c->_user( $user ); + # this sets the realm the user originated in. + $user->auth_realm($self->name); + } + else { + $self->failed_user_restore($c) || + $c->error("Store claimed to have a restorable user, but restoration failed. Did you change the user's id_field?"); + } + return $user; } +## this occurs if there is a session but the thing the session refers to +## can not be found. Do what you must do here. +## Return true if you can fix the situation and find a user, false otherwise +sub failed_user_restore { + my ($self, $c) = @_; + + $self->remove_persisted_user($c); + return; +} + sub persist_user { my ($self, $c, $user) = @_; if ( - $c->isa("Catalyst::Plugin::Session") + $c->can('session') and $self->config->{'use_session'} and $user->supports("session") ) { @@ -206,7 +239,7 @@ sub remove_persisted_user { my ($self, $c) = @_; if ( - $c->isa("Catalyst::Plugin::Session") + $c->can('session') and $self->config->{'use_session'} and $c->session_is_valid ) { @@ -263,6 +296,11 @@ user doesn't exist (most useful for remote authentication schemes). Set this to true if you wish this realm to auto-update user accounts after authentication (most useful for remote authentication schemes). +=item use_session + +Sets session usage for this particular realm - overriding the global use_sesion setting. + + =back =head1 METHODS @@ -292,17 +330,53 @@ Performs the authentication process for the current realm. The default realm class simply delegates this to the credential and sets the authenticated user on success. Returns the authenticated user object; -=head2 save_user_in_session($c, $user) +=head1 USER PERSISTENCE + +The Realm class allows complete control over the persistance of users +between requests. By default the realm attempts to use the Catalyst +session system to accomplish this. By overriding the methods below +in a custom Realm class, however, you can handle user persistance in +any way you see fit. + +=head2 persist_user($c, $user) + +persist_user is the entry point for saving user information between requests +in most cases this will utilize the session. By default this uses the +catalyst session system to store the user by calling for_session on the +active store. The user object must be a subclass of +Catalyst::Authentication::User. If you have updated the user object, you +must call persist_user again to ensure that the persisted user object reflects +your updates. -Used to save the user in a session. Saves $user in the current session, -marked as originating in the current realm. Calls $store->for_session() by -default. If for_session is not available in the store class, will attempt -to call $user->for_session(). +=head2 remove_persisted_user($c) + +Removes any persisted user data. By default, removes the user from the session. + +=head2 user_is_restorable( $c ) + +Returns whether there is a persisted user that may be restored. Returns +a token used to restore the user. With the default session persistance +it returns the raw frozen user information. + +=head2 restore_user($c, [$frozen_user]) + +Restores the user from the given frozen_user parameter, or if not provided, +using the response from $self->user_is_restorable(); Uses $self->from_session() +to decode the frozen user. + +=head2 failed_user_restore($c) + +If there is a session to restore, but the restore fails for any reason then this method +is called. This method supplied just removes the persisted user, but can be overridden +if required to have more complex logic (e.g. finding a the user by their 'old' username). =head2 from_session($c, $frozenuser ) -Triggers restoring of the user from data in the session. The default realm -class simply delegates the call to $store->from_session($c, $frozenuser); +Decodes the frozenuser information provided and returns an instantiated +user object. By default, this call is delegated to $store->from_session(). -=cut +=head2 save_user_in_session($c, $user) +DEPRECATED. Use persist_user instead. (this simply calls persist_user) + +=cut