Decoupling of Session and Auth-
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Authentication / Realm.pm
index 08c5541..db378ff 100644 (file)
@@ -54,14 +54,22 @@ sub new {
     ###  we must eval the ensure_class_loaded - because we might need to try the old-style
     ###  ::Plugin:: module naming if the standard method fails. 
     
+    ## Note to self - catch second exception and bitch in detail?
+    
     eval {
         Catalyst::Utils::ensure_class_loaded( $credentialclass );
     };
     
     if ($@) {
         $app->log->warn( qq(Credential class "$credentialclass" not found, trying deprecated ::Plugin:: style naming. ) );
+        my $origcredentialclass = $credentialclass;
         $credentialclass =~ s/Catalyst::Authentication/Catalyst::Plugin::Authentication/;
-        Catalyst::Utils::ensure_class_loaded( $credentialclass );
+
+        eval { Catalyst::Utils::ensure_class_loaded( $credentialclass ); };
+        if ($@) {
+            Carp::croak "Unable to load credential class, " . $origcredentialclass . " OR " . $credentialclass . 
+                        " in realm " . $self->name;
+        }
     }
     
     eval {
@@ -70,8 +78,13 @@ sub new {
     
     if ($@) {
         $app->log->warn( qq(Store class "$storeclass" not found, trying deprecated ::Plugin:: style naming. ) );
+        my $origstoreclass = $storeclass;
         $storeclass =~ s/Catalyst::Authentication/Catalyst::Plugin::Authentication/;
-        Catalyst::Utils::ensure_class_loaded( $storeclass );
+        eval { Catalyst::Utils::ensure_class_loaded( $storeclass ); };
+        if ($@) {
+            Carp::croak "Unable to load store class, " . $origstoreclass . " OR " . $storeclass . 
+                        " in realm " . $self->name;
+        }
     }
     
     # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms 
@@ -132,19 +145,71 @@ sub authenticate {
      }
 }
 
-sub save_user_in_session {
-    my ( $self, $c, $user ) = @_;
+sub user_is_restorable {
+    my ($self, $c) = @_;
+    
+    return unless
+         $c->isa("Catalyst::Plugin::Session")
+         and $c->config->{'Plugin::Authentication'}{'use_session'}
+         and $c->session_is_valid;
 
-    $c->session->{__user_realm} = $self->name;
+    return $c->session->{__user};
+}
+
+sub restore_user {
+    my ($self, $c, $frozen_user) = @_;
     
-    # we want to ask the store for a user prepared for the session.
-    # but older modules split this functionality between the user and the
-    # store.  We try the store first.  If not, we use the old method.
-    if ($self->store->can('for_session')) {
-        $c->session->{__user} = $self->store->for_session($c, $user);
-    } else {
-        $c->session->{__user} = $user->for_session;
+    $frozen_user ||= $self->user_is_restorable($c);
+    return unless defined($frozen_user);
+
+    $c->_user( my $user = $self->from_session( $c, $frozen_user ) );
+    
+    # this sets the realm the user originated in.
+    $user->auth_realm($self->name);
+    
+    return $user;
+}
+
+sub persist_user {
+    my ($self, $c, $user) = @_;
+    
+    if (
+        $c->isa("Catalyst::Plugin::Session")
+        and $c->config->{'Plugin::Authentication'}{'use_session'}
+        and $user->supports("session") 
+    ) {
+        $c->session->{__user_realm} = $self->name;
+    
+        # we want to ask the store for a user prepared for the session.
+        # but older modules split this functionality between the user and the
+        # store.  We try the store first.  If not, we use the old method.
+        if ($self->store->can('for_session')) {
+            $c->session->{__user} = $self->store->for_session($c, $user);
+        } else {
+            $c->session->{__user} = $user->for_session;
+        }
     }
+    return $user;
+}
+
+sub remove_persisted_user {
+    my ($self, $c) = @_;
+    
+    if (
+        $c->isa("Catalyst::Plugin::Session")
+        and $c->config->{'Plugin::Authentication'}{'use_session'}
+        and $c->session_is_valid
+    ) {
+        delete @{ $c->session }{qw/__user __user_realm/};
+    }    
+}
+
+## backwards compatibility - I don't think many people wrote realms since they
+## have only existed for a short time - but just in case.
+sub save_user_in_session {
+    my ( $self, $c, $user ) = @_;
+
+    return $self->persist_user($c, $user);
 }
 
 sub from_session {
@@ -172,8 +237,11 @@ Catalyst::Authentication::Realm - Base class for realm objects.
 
 =item class
 
-By default this class is the default realm class. You can specify a custom
-realm class with this config parameter.
+By default this class is used by
+L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> for all
+realms. The class parameter allows you to choose a different class to use for
+this realm. Creating a new Realm class can allow for authentication methods
+that fall outside the normal credential/store methodology.
 
 =item auto_create_user
 
@@ -189,34 +257,42 @@ authentication (most useful for remote authentication schemes).
 
 =head1 METHODS
 
-=head2 new( )
+=head2 new( $realmname, $config, $app )
 
 Instantiantes this realm, plus the specified store and credential classes.
 
 =head2 store( )
 
-Holds an instance of the store object for this realm.
+Returns an instance of the store object for this realm.
 
 =head2 credential( )
 
-Holds an instance of the credential object for this realm.
+Returns an instance of the credential object for this realm.
 
-=head2 find_user( )
+=head2 find_user( $authinfo, $c )
 
-Delegates to the store object. Will also re-delegate auto_create_user and
-auto_update_user at this time, if necessary.
+Retrieves the user given the authentication information provided.  This 
+is most often called from the credential.  The default realm class simply
+delegates this call the store object.  If enabled, auto-creation and 
+auto-updating of users is also handled here.
 
-=head2 authenticate( )
+=head2 authenticate( $c, $authinfo)
 
-Delegates to the credential objects and sets the authenticated user on success.
+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( )
+=head save_user_in_session($c, $user)
 
-Delegates to the store object.
+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 from_session( )
+=head2 from_session($c, $frozenuser )
 
-Delegates to the store object.
+Triggers restoring of the user from data in the session. The default realm
+class simply delegates the call to $store->from_session($c, $frozenuser);
 
 =cut