[Maypole] using the Authentication::Abstract plugin

Seth Gordon sethg@ropine.com
Wed, 08 Dec 2004 16:49:52 -0500


I'm trying to add a very simple login/logout feature to my application, 
using Authentication::Abstract.  Since I only want my wife and I to have 
login access, I didn't bother creating a separate database table of 
users, and I just created a class:

package JeevesLibrary::User;
use base qw(Class::Accessor);
__PACKAGE__->mk_ro_accessors(qw/id/);

sub search {
     my ($class, %params) = @_;
     my $user = $params{'user'};
     my $password = $params{'password'};
     print STDERR "about to create a user obj in search\n";
     if (($user eq 'sethg' or $user eq 'jen') and $password eq 'xxx') {
         return $class->new(id => $user);
     } else {
         return ();
     }
}

sub retrieve {
     my ($class, $user) = @_;
     if ($user eq 'sethg' or $user eq 'jen') {
         print STDERR "about to create a user obj in retrieve\n";
         return __PACKAGE__->new(id => $user);
     } else {
         return undef;
     }
}

I added some code to my main application class to handle logging in and out:

package JeevesLibrary;
use strict;
use Maypole::Application qw(-Debug Authentication::Abstract);
use Data::Dumper;
use Maypole::Constants;

# ...

sub authenticate {
     my $r = shift;
     $r->private;
     $r->{template_args}{user} = $r->user->id if $r->user;
     return OK;
}

sub additional_data {
     my $r = shift;
     $r->logout if $r->params->{logout};
     ## ...
     ## Set up the default order and the page title...
     ## this is old code that has nothing to do with authentication.
     ## ...
}

I added some code to a custom template to provide a login/logout form 
and to pass along error messages.

Results: When I load a page as usual, there's a login form where I 
expect it to be and everything else works fine.  When I type a username 
and an *incorrect* password, I get a "Bad username or password" error 
message at the top of the page, and the rest of the page loads normally, 
just as I would expect.  But when I enter the *correct* password, I get 
a blank page in the browser, and I get the following in my Apache error log:

about to create a user obj in search
caught authenticate error: Can't use string ("id") as a HASH ref while 
"strict refs" in use at 
/usr/local/libdata/perl5/site_perl/Class/Accessor.pm line 136.
Can't use string ("id") as a HASH ref while "strict refs" in use at 
/usr/local/libdata/perl5/site_perl/Class/Accessor.pm line 136.
         ...caught at 
/usr/local/libdata/perl5/site_perl/Maypole/View/Base.pm line 74.
Use of uninitialized value in concatenation (.) or string at 
/usr/local/libdata/perl5/site_perl/Apache/MVC.pm line 45.
Use of uninitialized value in length at 
/usr/local/libdata/perl5/site_perl/Apache/MVC.pm line 50.
Use of uninitialized value in subroutine entry at 
/usr/local/libdata/perl5/site_perl/Apache/MVC.pm line 52.

When I comment out the Class::Accessor stuff and use a regular blessed 
hash instead, I don't get the error message and I do get the "Hello, 
[%user%]" message when I log in.  The message doesn't persist when I 
follow a link or reload the page; I assume that's because I'm not using 
Apache::Session or some such to persist the fact that I logged in.

So my questions for the assembled multitude are:

(1) What's wrong with my use of Class::Accessor?

(2) What's the simplest way to convert my JeevesLibrary::User class into 
something that persists appropriately?

-- 
"If John Kerry was the last best hope for the Republic ... then maybe
  it wasn't worth saving in the first place.  I don't believe that,
  though. And neither do you." --Dan Layman-Kennedy
// seth gordon // sethg@ropine.com // http://dynamic.ropine.com/yo/ //