[Catalyst-commits] r6962 - in trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin: . Authentication Authentication/Credential Authentication/Realm

jayk at dev.catalyst.perl.org jayk at dev.catalyst.perl.org
Sun Oct 7 05:06:33 GMT 2007


Author: jayk
Date: 2007-10-07 05:06:33 +0100 (Sun, 07 Oct 2007)
New Revision: 6962

Added:
   trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Realm.pm
   trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Realm/
   trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Realm/Compatibility.pm
Modified:
   trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication.pm
   trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Credential/Password.pm
Log:
Making Realm a bonafide object.  No change to docs yet, but passes all
tests I throw at it (including those from Store::DBIx::Class) so I think we are good.


Modified: trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Credential/Password.pm
===================================================================
--- trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Credential/Password.pm	2007-10-05 21:49:12 UTC (rev 6961)
+++ trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Credential/Password.pm	2007-10-07 04:06:33 UTC (rev 6962)
@@ -9,15 +9,17 @@
 use Digest              ();
 
 BEGIN {
-    __PACKAGE__->mk_accessors(qw/_config/);
+    __PACKAGE__->mk_accessors(qw/_config realm/);
 }
 
 sub new {
-    my ($class, $config, $app) = @_;
+    my ($class, $config, $app, $realm) = @_;
     
     my $self = { _config => $config };
     bless $self, $class;
     
+    $self->realm($realm);
+    
     $self->_config->{'password_field'} ||= 'password';
     $self->_config->{'password_type'}  ||= 'clear';
     $self->_config->{'password_hash_type'} ||= 'SHA-1';
@@ -30,7 +32,7 @@
 }
 
 sub authenticate {
-    my ( $self, $c, $authstore, $authinfo ) = @_;
+    my ( $self, $c, $realm, $authinfo ) = @_;
 
     ## because passwords may be in a hashed format, we have to make sure that we remove the 
     ## password_field before we pass it to the user routine, as some auth modules use 
@@ -38,7 +40,7 @@
     my $userfindauthinfo = {%{$authinfo}};
     delete($userfindauthinfo->{$self->_config->{'password_field'}});
     
-    my $user_obj = $authstore->find_user($userfindauthinfo, $c);
+    my $user_obj = $realm->find_user($userfindauthinfo, $c);
     if (ref($user_obj)) {
         if ($self->check_password($user_obj, $authinfo)) {
             return $user_obj;

Added: trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Realm/Compatibility.pm
===================================================================
--- trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Realm/Compatibility.pm	                        (rev 0)
+++ trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Realm/Compatibility.pm	2007-10-07 04:06:33 UTC (rev 6962)
@@ -0,0 +1,24 @@
+package Catalyst::Plugin::Authentication::Realm::Compatibility;
+
+use strict;
+use warnings;
+use base qw/Catalyst::Plugin::Authentication::Realm/;
+
+
+## very funky - the problem here is that we can't do real realm initialization
+## but we need a real realm object to function.  So - we kinda fake it - we 
+## create an empty object - 
+sub new {
+    my ($class, $realmname, $config, $app) = @_;
+    
+    my $self = { config => $config };
+    bless $self, $class;
+    
+    $self->name($realmname);
+    
+    return $self;
+}
+
+__PACKAGE__;
+
+__END__
\ No newline at end of file

Added: trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Realm.pm
===================================================================
--- trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Realm.pm	                        (rev 0)
+++ trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication/Realm.pm	2007-10-07 04:06:33 UTC (rev 6962)
@@ -0,0 +1,134 @@
+package Catalyst::Plugin::Authentication::Realm;
+
+use strict;
+use warnings;
+use base qw/Class::Accessor::Fast/;
+
+BEGIN {
+    __PACKAGE__->mk_accessors(qw/store credential name config/);
+};
+
+sub new {
+    my ($class, $realmname, $config, $app) = @_;
+
+    my $self = { config => $config };
+    bless $self, $class;
+    
+    $self->name($realmname);
+    
+    $app->log->debug("Setting up auth realm $realmname") if $app->debug;
+    if (!exists($config->{'store'}{'class'})) {
+        Carp::croak "Couldn't setup the authentication realm named '$realmname', no class defined";
+    } 
+        
+    $config->{store}{class} ||= '+Catalyst::Plugin::Authentication::Store::Null';
+    
+    # use the 
+    my $storeclass = $config->{'store'}{'class'};
+    
+    ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
+    ## taken to mean C::P::A::Store::(specifiedclass)
+    if ($storeclass !~ /^\+(.*)$/ ) {
+        $storeclass = "Catalyst::Plugin::Authentication::Store::${storeclass}";
+    } else {
+        $storeclass = $1;
+    }
+    
+
+    # a little niceness - since most systems seem to use the password credential class, 
+    # if no credential class is specified we use password.
+    $config->{credential}{class} ||= '+Catalyst::Plugin::Authentication::Credential::Password';
+
+    my $credentialclass = $config->{'credential'}{'class'};
+    
+    ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
+    ## taken to mean C::P::A::Credential::(specifiedclass)
+    if ($credentialclass !~ /^\+(.*)$/ ) {
+        $credentialclass = "Catalyst::Plugin::Authentication::Credential::${credentialclass}";
+    } else {
+        $credentialclass = $1;
+    }
+    
+    # if we made it here - we have what we need to load the classes;
+    Catalyst::Utils::ensure_class_loaded( $credentialclass );
+    Catalyst::Utils::ensure_class_loaded( $storeclass );
+    
+    # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms 
+    # of get_user and add it to the class.  this is because the auth routines use find_user, 
+    # and rely on it being present. (this avoids per-call checks)
+    if (!$storeclass->can('find_user')) {
+        no strict 'refs';
+        *{"${storeclass}::find_user"} = sub {
+                                                my ($self, $info) = @_;
+                                                my @rest = @{$info->{rest}} if exists($info->{rest});
+                                                $self->get_user($info->{id}, @rest);
+                                            };
+    }
+    
+    ## a little cruft to stay compatible with some poorly written stores / credentials
+    ## we'll remove this soon.
+    if ($storeclass->can('new')) {
+        $self->store($storeclass->new($config->{'store'}, $app, $self));
+    } else {
+        $app->log->error("THIS IS DEPRECATED: $storeclass has no new() method - Attempting to use uninstantiated");
+        $self->store($storeclass);
+    }
+    if ($credentialclass->can('new')) {
+        $self->credential($credentialclass->new($config->{'credential'}, $app, $self));
+    } else {
+        $app->log->error("THIS IS DEPRECATED: $credentialclass has no new() method - Attempting to use uninstantiated");
+        $self->credential($credentialclass);
+    }
+    
+    return $self;
+}
+
+sub find_user {
+    my ( $self, $authinfo, $c ) = @_;
+
+    my $res = $self->store->find_user($authinfo, $c);
+    
+    if (!$res && $self->config->{'auto_create'} ) {
+        $res = $self->store->auto_create($authinfo, $c);
+    }
+    
+    return $res;
+}
+
+sub authenticate {
+     my ($self, $c, $authinfo) = @_;
+
+     my $user = $self->credential->authenticate($c, $self, $authinfo);
+     if (ref($user)) {
+         $c->set_authenticated($user, $self->name);
+         return $user;
+     } else {
+         return undef;
+     }
+}
+
+sub save_user_in_session {
+    my ( $self, $c, $user ) = @_;
+
+    $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;
+    }
+}
+
+sub from_session {
+    my ($self, $c, $frozen_user) = @_;
+    
+    return $self->store->from_session($c, $frozen_user);
+}
+
+
+__PACKAGE__;
+
+__END__
\ No newline at end of file

Modified: trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication.pm
===================================================================
--- trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication.pm	2007-10-05 21:49:12 UTC (rev 6961)
+++ trunk/Catalyst-Plugin-Authentication/lib/Catalyst/Plugin/Authentication.pm	2007-10-07 04:06:33 UTC (rev 6962)
@@ -11,6 +11,7 @@
 
 use Tie::RefHash;
 use Class::Inspector;
+use Catalyst::Plugin::Authentication::Realm;
 
 # this optimization breaks under Template::Toolkit
 # use user_exists instead
@@ -30,14 +31,20 @@
     if (!$realmname) {
         $realmname = 'default';
     }
+    my $realm = $c->get_auth_realm($realmname);
     
+    if (!$realm) {
+        Catalyst::Exception->throw(
+                "set_authenticated called with nonexistant realm: '$realmname'.");
+    }
+    
     if (    $c->isa("Catalyst::Plugin::Session")
         and $c->config->{authentication}{use_session}
         and $user->supports("session") )
     {
-        $c->save_user_in_session($user, $realmname);
+        $realm->save_user_in_session($c, $user);
     }
-    $user->auth_realm($realmname);
+    $user->auth_realm($realm->name);
     
     $c->NEXT::set_authenticated($user, $realmname);
 }
@@ -77,7 +84,7 @@
     }
 }
 
-sub save_user_in_session {
+sub __old_save_user_in_session {
     my ( $c, $user, $realmname ) = @_;
 
     $c->session->{__user_realm} = $realmname;
@@ -114,11 +121,12 @@
     
     $realmname ||= 'default';
     my $realm = $c->get_auth_realm($realmname);
-    if ( $realm->{'store'} ) {
-        return $realm->{'store'}->find_user($userinfo, $c);
-    } else {
-        $c->log->debug('find_user: unable to locate a store matching the requested realm');
+    
+    if (!$realm) {
+        Catalyst::Exception->throw(
+                "find_user called with nonexistant realm: '$realmname'.");
     }
+    return $realm->find_user($userinfo, $c);
 }
 
 
@@ -143,7 +151,7 @@
     return unless $realmname; # FIXME die unless? This is an internal inconsistency
 
     my $realm = $c->get_auth_realm($realmname);
-    $c->_user( my $user = $realm->{'store'}->from_session( $c, $frozen_user ) );
+    $c->_user( my $user = $realm->from_session( $c, $frozen_user ) );
     
     # this sets the realm the user originated in.
     $user->auth_realm($realmname);
@@ -179,7 +187,7 @@
         foreach my $realm (keys %{$cfg->{'realms'}}) {
             $app->setup_auth_realm($realm, $cfg->{'realms'}{$realm});
         }
-        #  if we have a 'default-realm' in the config hash and we don't already 
+        #  if we have a 'default_realm' in the config hash and we don't already 
         # have a realm called 'default', we point default at the realm specified
         if (exists($cfg->{'default_realm'}) && !$app->get_auth_realm('default')) {
             $app->_set_default_auth_realm($cfg->{'default_realm'});
@@ -210,67 +218,18 @@
 sub setup_auth_realm {
     my ($app, $realmname, $config) = @_;
     
-    $app->log->debug("Setting up auth realm $realmname") if $app->debug;
-    if (!exists($config->{'store'}{'class'})) {
-        Carp::croak "Couldn't setup the authentication realm named '$realmname', no class defined";
-    } 
-        
-    # use the 
-    my $storeclass = $config->{'store'}{'class'};
-    
-    ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
-    ## taken to mean C::P::A::Store::(specifiedclass)
-    if ($storeclass !~ /^\+(.*)$/ ) {
-        $storeclass = "Catalyst::Plugin::Authentication::Store::${storeclass}";
-    } else {
-        $storeclass = $1;
+    my $realmclass = 'Catalyst::Plugin::Authentication::Realm';
+    if (defined($config->{'class'})) {
+        $realmclass = $config->{'class'};
+        Catalyst::Utils::ensure_class_loaded( $realmclass );
     }
-    
-
-    # a little niceness - since most systems seem to use the password credential class, 
-    # if no credential class is specified we use password.
-    $config->{credential}{class} ||= '+Catalyst::Plugin::Authentication::Credential::Password';
-
-    my $credentialclass = $config->{'credential'}{'class'};
-    
-    ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
-    ## taken to mean C::P::A::Credential::(specifiedclass)
-    if ($credentialclass !~ /^\+(.*)$/ ) {
-        $credentialclass = "Catalyst::Plugin::Authentication::Credential::${credentialclass}";
+    my $realm = $realmclass->new($realmname, $config, $app);
+    if ($realm) {
+        $app->auth_realms->{$realmname} = $realm;
     } else {
-        $credentialclass = $1;
+        $app->log->debug("realm initialization for '$realmname' failed.");
     }
-    
-    # if we made it here - we have what we need to load the classes;
-    Catalyst::Utils::ensure_class_loaded( $credentialclass );
-    Catalyst::Utils::ensure_class_loaded( $storeclass );
-    
-    # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms 
-    # of get_user and add it to the class.  this is because the auth routines use find_user, 
-    # and rely on it being present. (this avoids per-call checks)
-    if (!$storeclass->can('find_user')) {
-        no strict 'refs';
-        *{"${storeclass}::find_user"} = sub {
-                                                my ($self, $info) = @_;
-                                                my @rest = @{$info->{rest}} if exists($info->{rest});
-                                                $self->get_user($info->{id}, @rest);
-                                            };
-    }
-    
-    ## a little cruft to stay compatible with some poorly written stores / credentials
-    ## we'll remove this soon.
-    if ($storeclass->can('new')) {
-        $app->auth_realms->{$realmname}{'store'} = $storeclass->new($config->{'store'}, $app);
-    } else {
-        $app->log->error("THIS IS DEPRECATED: $storeclass has no new() method - Attempting to use uninstantiated");
-        $app->auth_realms->{$realmname}{'store'} = $storeclass;
-    }
-    if ($credentialclass->can('new')) {
-        $app->auth_realms->{$realmname}{'credential'} = $credentialclass->new($config->{'credential'}, $app);
-    } else {
-        $app->log->error("THIS IS DEPRECATED: $credentialclass has no new() method - Attempting to use uninstantiated");
-        $app->auth_realms->{$realmname}{'credential'} = $credentialclass;
-    }
+    return $realm;
 }
 
 sub auth_realms {
@@ -309,15 +268,12 @@
     
     ## note to self - make authenticate throw an exception if realm is invalid.
     
-    if ($realm && exists($realm->{'credential'})) {
-        my $user = $realm->{'credential'}->authenticate($app, $realm->{store}, $userinfo);
-        if (ref($user)) {
-            $app->set_authenticated($user, $realmname);
-            return $user;
-        }
+    if ($realm) {
+        return $realm->authenticate($app, $userinfo);
     } else {
-        $app->log->debug("The realm requested, '$realmname' does not exist," .
-                         " or there is no credential associated with it.")
+        Catalyst::Exception->throw(
+                "authenticate called with nonexistant realm: '$realmname'.");
+
     }
     return undef;
 }
@@ -349,8 +305,12 @@
 sub default_auth_store {
     my $self = shift;
 
+    my $realm = $self->get_auth_realm('default');
+    if (!$realm) {
+        $realm = $self->setup_auth_realm('default', { class => "Catalyst::Plugin::Authentication::Realm::Compatibility" });
+    }
     if ( my $new = shift ) {
-        $self->auth_realms->{'default'}{'store'} = $new;
+        $realm->store($new);
         
         my $storeclass;
         if (ref($new)) {
@@ -372,7 +332,7 @@
         }
     }
 
-    return $self->get_auth_realm('default')->{'store'};
+    return $self->get_auth_realm('default')->store;
 }
 
 ## BACKWARDS COMPATIBILITY
@@ -381,7 +341,7 @@
 sub auth_store_names {
     my $self = shift;
 
-    my %hash = (  $self->get_auth_realm('default')->{'store'} => 'default' );
+    my %hash = (  $self->get_auth_realm('default')->store => 'default' );
 }
 
 sub get_auth_store {
@@ -403,7 +363,7 @@
 sub auth_stores {
     my $self = shift;
 
-    my %hash = ( 'default' => $self->get_auth_realm('default')->{'store'});
+    my %hash = ( 'default' => $self->get_auth_realm('default')->store);
 }
 
 __PACKAGE__;




More information about the Catalyst-commits mailing list