A better fix for the realm class name warning problem.
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Authentication / Realm.pm
index a0c3474..db9b4c2 100644 (file)
@@ -29,10 +29,13 @@ sub new {
 
     $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;
 
@@ -179,18 +194,30 @@ sub restore_user {
     
         # this sets the realm the user originated in.
         $user->auth_realm($self->name);
-    } else {
-               Catalyst::Exception->throw("Store claimed to have a restorable user, but restoration failed.  Did you change the user's id_field?");
+    } 
+    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") 
     ) {
@@ -212,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
     ) {
@@ -269,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
@@ -298,7 +330,7 @@ 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;
 
-=head1 USER PERSISTANCE
+=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
@@ -332,6 +364,11 @@ 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 )