+++ /dev/null
-use strict;
-use Module::Build;
-
-my $build = Module::Build->new(
- create_makefile_pl => 'traditional',
- license => 'perl',
- create_readme => 1,
-
- module_name => 'Catalyst::Plugin::Authentication::Store::Htpasswd',
- requires => {
- 'Catalyst::Plugin::Authentication' => '0.01',
- 'Authen::Htpasswd' => '0.13',
- },
-
- dist_author => 'David Kamholz <dkamholz@cpan.org>',
-);
-$build->create_build_script;
-
+0.03 XXX XXX x XX:XX:XX GMT 2008
+ - Change from Module::Build to Module::Install
+
0.02 Wed Feb 8 01:18:17 CET 2006
- work properly again with roles
- fix condition where $user is false and still gets a method call on it
--- /dev/null
+Changes
+inc/Module/Install.pm
+inc/Module/Install/Base.pm
+inc/Module/Install/Can.pm
+inc/Module/Install/Fetch.pm
+inc/Module/Install/Makefile.pm
+inc/Module/Install/Metadata.pm
+inc/Module/Install/Win32.pm
+inc/Module/Install/WriteAll.pm
+lib/Catalyst/Authentication/Store/Htpasswd.pm
+lib/Catalyst/Authentication/Store/Htpasswd/User.pm
+Makefile.PL
+MANIFEST This list of files
+META.yml
+t/00-load.t
+t/backend.t
+t/backend_md5.t
+t/kwalitee.t
+t/lib/script/testapp_server.pl
+t/lib/script/testapp_test.pl
+t/lib/TestApp.pm
+t/lib/TestApp/Controller/Root.pm
+t/lib/TestApp/htpasswd
+t/lib/TestApp/Model/Tangram.pm
+t/live-test.t
+t/pod-coverage.t
+t/pod.t
+Todo
--- /dev/null
+use strict;
+use inc::Module::Install;
+
+name 'Catalyst-Authenticaton-Store-Htpasswd';
+all_from 'lib/Catalyst/Authentication/Store/Htpasswd.pm';
+
+requires 'Catalyst::Plugin::Authentication' => '0.10006';
+requires 'Authen::Htpasswd' => '0.13';
+requires 'Class::Accessor::Fast';
+requires 'Crypt::PasswdMD5';
+
+WriteAll;
--- /dev/null
+NAME
+ Catalyst::Authentication::Store::Htpasswd - Authen::Htpasswd based user
+ storage/authentication.
+
+SYNOPSIS
+ use Catalyst qw/
+ Authentication
+ /;
+
+ __PACKAGE__->config(
+ authentication => {
+ default_realm => 'test',
+ realms => {
+ test => {
+ credential => {
+ class => 'Password',
+ password_field => 'password',
+ password_type => 'self_check',
+ },
+ store => {
+ class => 'Htpasswd',
+ file => 'htpasswd',
+ },
+ },
+ },
+ },
+ );
+
+ sub login : Global {
+ my ( $self, $c ) = @_;
+
+ $c->authenticate({ username => $c->req->param("login"), password => $c->req->param("password") });
+ }
+
+DESCRIPTION
+ This plugin uses "Authen::Htpasswd" to let your application use
+ ".htpasswd" files for it's authentication storage.
+
+METHODS
+ new
+ Simple constructor, dies if the htpassword file can't be found
+
+ find_user
+ Looks up the user, and returns a
+ Catalyst::Authentication::Store::Htpasswd::User object.
+
+ user_supports
+ Delegates to
+ Catalyst::Authentication::Store::Htpasswd::User-user_supports|Catalyst::
+ Authentication::Store::Htpasswd::User#user_supports>
+
+ from_session
+ Delegates the user lookup to " find_user "
+
+CONFIGURATION
+ file
+ The path to the htpasswd file, this is taken from the application root.
+
+AUTHORS
+ Yuval Kogman "nothingmuch@woobling.org"
+
+ David Kamholz "dkamholz@cpan.org"
+
+ Tomas Doran "bobtfish@bobtfish.net"
+
+SEE ALSO
+ Authen::Htpasswd.
+
+COPYRIGHT & LICENSE
+ Copyright (c) 2005-2008 the aforementioned authors. All rights
+ reserved. This program is free software; you can redistribute
+ it and/or modify it under the same terms as Perl itself.
+
--- /dev/null
+. Paths to htpasswd which start with / should be taken from root, not the app root
--- /dev/null
+#!/usr/bin/perl
+
+package Catalyst::Authentication::Store::Htpasswd;
+use base qw/Class::Accessor::Fast/;
+use strict;
+use warnings;
+
+use Authen::Htpasswd;
+use Catalyst::Authentication::Store::Htpasswd::User;
+use Scalar::Util qw/blessed/;
+
+our $VERSION = '0.03';
+
+BEGIN { __PACKAGE__->mk_accessors(qw/file/) }
+
+sub new {
+ my ($class, $config, $app, $realm) = @_;
+
+ my $file = delete $config->{file};
+ unless (ref $file) { # FIXME - file not in app..
+ my $filename = $app->path_to($file)->stringify;
+ die("Cannot find htpasswd file: $filename\n") unless (-r $filename);
+ $file = Authen::Htpasswd->new($filename);
+ }
+ $config->{file} = $file;
+
+ bless { %$config }, $class;
+}
+
+sub find_user {
+ my ($self, $authinfo, $c) = @_;
+ # FIXME - change username
+ my $htpasswd_user = $self->file->lookup_user($authinfo->{username});
+ Catalyst::Authentication::Store::Htpasswd::User->new( $self, $htpasswd_user );
+}
+
+sub user_supports {
+ my $self = shift;
+
+ # this can work as a class method
+ Catalyst::Authentication::Store::Htpasswd::User->supports(@_);
+}
+
+sub from_session {
+ my ( $self, $c, $id ) = @_;
+ $self->find_user( { username => $id } );
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+Catalyst::Authentication::Store::Htpasswd - L<Authen::Htpasswd> based
+user storage/authentication.
+
+=head1 SYNOPSIS
+
+ use Catalyst qw/
+ Authentication
+ /;
+
+ __PACKAGE__->config(
+ authentication => {
+ default_realm => 'test',
+ realms => {
+ test => {
+ credential => {
+ class => 'Password',
+ password_field => 'password',
+ password_type => 'self_check',
+ },
+ store => {
+ class => 'Htpasswd',
+ file => 'htpasswd',
+ },
+ },
+ },
+ },
+ );
+
+ sub login : Global {
+ my ( $self, $c ) = @_;
+
+ $c->authenticate({ username => $c->req->param("login"), password => $c->req->param("password") });
+ }
+
+=head1 DESCRIPTION
+
+This plugin uses C<Authen::Htpasswd> to let your application use C<.htpasswd>
+files for it's authentication storage.
+
+=head1 METHODS
+
+=head2 new
+
+Simple constructor, dies if the htpassword file can't be found
+
+=head2 find_user
+
+Looks up the user, and returns a Catalyst::Authentication::Store::Htpasswd::User object.
+
+=head2 user_supports
+
+Delegates to L<Catalyst::Authentication::Store::Htpasswd::User->user_supports|Catalyst::Authentication::Store::Htpasswd::User#user_supports>
+
+=head2 from_session
+
+Delegates the user lookup to C< find_user >
+
+=head1 CONFIGURATION
+
+=head2 file
+
+The path to the htpasswd file, this is taken from the application root.
+
+=head1 AUTHORS
+
+Yuval Kogman C<nothingmuch@woobling.org>
+
+David Kamholz C<dkamholz@cpan.org>
+
+Tomas Doran C<bobtfish@bobtfish.net>
+
+=head1 SEE ALSO
+
+L<Authen::Htpasswd>.
+
+=head1 COPYRIGHT & LICENSE
+
+ Copyright (c) 2005-2008 the aforementioned authors. All rights
+ reserved. This program is free software; you can redistribute
+ it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+
#!/usr/bin/perl
-package Catalyst::Plugin::Authentication::Store::Htpasswd::User;
-use base qw/Catalyst::Plugin::Authentication::User Class::Accessor::Fast/;
+package Catalyst::Authentication::Store::Htpasswd::User;
+use base qw/Catalyst::Authentication::User Class::Accessor::Fast/;
use strict;
use warnings;
$self->user->$method;
}
-__PACKAGE__;
+1;
__END__
=head1 NAME
-Catalyst::Plugin::Authentication::Store::Htpasswd::User - A user object
+Catalyst::Authentication::Store::Htpasswd::User - A user object
representing an entry in an htpasswd file.
=head1 DESCRIPTION
This object wraps an L<Authen::Htpasswd::User> object. An instance of it will be returned
-by C<< $c->user >> when using L<Catalyst::Plugin::Authentication::Store::Htpasswd>. Methods
+by C<< $c->user >> when using L<Catalyst::Authentication::Store::Htpasswd>. Methods
not defined in this module are passed through to the L<Authen::Htpasswd::User> object. The
object stringifies to the username.
=head2 new($store,$user)
Creates a new object from a store object, normally an instance of
-L<Catalyst::Plugin::Authentication::Store::Htpasswd::Backend>, and a user object,
+L<Catalyst::Authentication::Store::Htpasswd::Backend>, and a user object,
normally an instance of L<Authen::Htpasswd::User>.
=head2 id
Returns an array of roles, which is extracted from a comma-separated list in the
third field of the htpasswd file.
+=head2 for_session
+
+Returns the username, which is then stored in the session.
+
+=head2 supported_features
+
+Returns data about which featurs this user module supports.
+
+=head1 AUTHORS
+
+Yuval Kogman C<nothingmuch@woobling.org>
+
+David Kamholz C<dkamholz@cpan.org>
+
+Tomas Doran C<bobtfish@bobtfish.net>
+
=head1 COPYRIGHT & LICENSE
Copyright (c) 2005 the aforementioned authors. All rights
+++ /dev/null
-#!/usr/bin/perl
-
-package Catalyst::Plugin::Authentication::Store::Htpasswd;
-
-use strict;
-use warnings;
-
-our $VERSION = '0.02';
-
-use Catalyst::Plugin::Authentication::Store::Htpasswd::Backend;
-
-sub setup {
- my $c = shift;
-
- $c->default_auth_store(
- Catalyst::Plugin::Authentication::Store::Htpasswd::Backend->new(
- $c->config->{authentication}{htpasswd}
- )
- );
-
- $c->NEXT::setup(@_);
-}
-
-__PACKAGE__;
-
-__END__
-
-=pod
-
-=head1 NAME
-
-Catalyst::Plugin::Authentication::Store::Htpasswd - L<Authen::Htpasswd> based
-user storage/authentication.
-
-=head1 SYNOPSIS
-
- use Catalyst qw/
- Authentication
- Authentication::Store::Htpasswd
- Authentication::Credential::Password
- /;
-
- __PACKAGE__->config->{authentication}{htpasswd} = "passwdfile";
-
- sub login : Global {
- my ( $self, $c ) = @_;
-
- $c->login( $c->req->param("login"), $c->req->param("password"), );
- }
-
-=head1 DESCRIPTION
-
-This plugin uses C<Authen::Htpasswd> to let your application use C<.htpasswd>
-files for it's authentication storage.
-
-=head1 METHODS
-
-=head2 setup
-
-This method will popultate C<< $c->config->{authentication}{store} >> so that
-L<Catalyst::Plugin::Authentication/default_auth_store> can use it.
-
-=head1 CONFIGURATION
-
-=head2 $c->config->{authentication}{htpasswd}
-
-The path to the htpasswd file.
-
-=head1 AUTHORS
-
-Yuval Kogman C<nothingmuch@woobling.org>
-
-David Kamholz C<dkamholz@cpan.org>
-
-=head1 SEE ALSO
-
-L<Authen::Htpasswd>.
-
-=head1 COPYRIGHT & LICENSE
-
- Copyright (c) 2005 the aforementioned authors. All rights
- reserved. This program is free software; you can redistribute
- it and/or modify it under the same terms as Perl itself.
-
-=cut
-
-
--- /dev/null
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use Test::More tests => 2;
+use ok 'Catalyst::Authentication::Store::Htpasswd';
+use ok 'Catalyst::Authentication::Store::Htpasswd::User';
+
use File::Temp qw/tempfile/;
-my $m; BEGIN { use_ok($m = "Catalyst::Plugin::Authentication::Store::Htpasswd::Backend") }
+my $m; BEGIN { use_ok($m = "Catalyst::Authentication::Store::Htpasswd") }
(undef, my $tmp) = tempfile();
$passwd->add_user("user", "s3cr3t");
can_ok($m, "new");
-isa_ok(my $o = $m->new( $passwd ), $m);
+isa_ok(my $o = $m->new( { file => $passwd } ), $m);
can_ok($m, "file");
isa_ok( $o->file, "Authen::Htpasswd");
can_ok( $m, "user_supports");
ok( $m->user_supports(qw/password self_check/), "user_supports self check" );
-can_ok($m, "get_user");
-isa_ok( my $u = $o->get_user("user"), "Catalyst::Plugin::Authentication::Store::Htpasswd::User");
-isa_ok( $u, "Catalyst::Plugin::Authentication::User");
+can_ok($m, "find_user");
+isa_ok( my $u = $o->find_user({ username => "user"}), "Catalyst::Authentication::Store::Htpasswd::User");
+isa_ok( $u, "Catalyst::Authentication::User");
can_ok( $u, "supports");
ok( $u->supports(qw/password self_check/), "htpasswd users check their own passwords");
use strict;
use warnings;
-use Test::More;
-
-BEGIN {
- eval { require Crypt::PasswdMD5 };
- plan skip_all => "This test requires Crypt::PasswdMD5 to be installed" if $@;
- plan tests => 12;
-}
+use Test::More tests => 12;
use File::Temp qw/tempfile/;
-my $m; BEGIN { use_ok($m = "Catalyst::Plugin::Authentication::Store::Htpasswd::Backend") }
+my $m; BEGIN { use_ok($m = "Catalyst::Authentication::Store::Htpasswd") }
(undef, my $tmp) = tempfile();
$passwd->add_user("user", "s3cr3t");
can_ok($m, "new");
-isa_ok(my $o = $m->new( $passwd ), $m);
+isa_ok(my $o = $m->new( { file => $passwd } ), $m);
can_ok($m, "file");
isa_ok( $o->file, "Authen::Htpasswd");
can_ok( $m, "user_supports");
ok( $m->user_supports(qw/password self_check/), "user_supports self check" );
-can_ok($m, "get_user");
-isa_ok( my $u = $o->get_user("user"), "Catalyst::Plugin::Authentication::Store::Htpasswd::User");
-isa_ok( $u, "Catalyst::Plugin::Authentication::User");
+can_ok($m, "find_user");
+isa_ok( my $u = $o->find_user({username => "user"}), "Catalyst::Authentication::Store::Htpasswd::User");
+isa_ok( $u, "Catalyst::Authentication::User");
can_ok( $u, "check_password");
ok( $u->check_password( "s3cr3t" ), "password is s3cr3t");
--- /dev/null
+#!/usr/bin/env perl
+use Test::More;
+
+eval { require Test::Kwalitee; Test::Kwalitee->import() };
+
+plan( skip_all => 'Test::Kwalitee not installed; skipping' ) if $@;
--- /dev/null
+package TestApp;
+use strict;
+use warnings;
+
+use Catalyst qw/
+ Authentication
+/;
+
+__PACKAGE__->config(
+ authentication => {
+ default_realm => 'test',
+ realms => {
+ test => {
+ credential => {
+ class => 'Password',
+ password_field => 'password',
+ password_type => 'self_check',
+ },
+ store => {
+ class => 'Htpasswd',
+ file => 'htpasswd',
+ },
+ },
+ },
+ },
+);
+
+__PACKAGE__->setup;
+
+1;
--- /dev/null
+package TestApp::Controller::Root;
+use strict;
+use warnings;
+
+__PACKAGE__->config(namespace => q{});
+
+use base 'Catalyst::Controller';
+
+# your actions replace this one
+sub default : Private {
+ my ($self, $c) = @_;
+ my $body = '';
+ if ($c->authenticate({ username => 'mufasa', password => 'Circle of Life'})) {
+ $body .= "Authenticated:";
+ $body .= $c->user->id;
+ }
+ $c->res->body($body);
+}
+
+1;
--- /dev/null
+package Users;
+use strict;
+use warnings;
+use base qw/Class::Accessor/;
+
+__PACKAGE__->mk_accessors(qw/username password/);
+
+sub new {
+ my ($class, %p) = @_;
+ bless { %p }, $class;
+}
+
+package TestApp::Model::Tangram;
+use strict;
+use warnings;
+use base qw/Catalyst::Model/;
+use DBI;
+use Tangram::Relational;
+use Tangram::Storage;
+use Tangram::Type::String;
+use Class::C3;
+use File::Temp qw/tempfile/;
+
+BEGIN {
+ __PACKAGE__->mk_accessors(qw/storage schema _sqlite_file/);
+}
+
+sub COMPONENT {
+ my ($class, $app, @rest) = @_;
+ my $self = $class->next::method($app, @rest);
+ my ($fh, $fn) = tempfile;
+ close($fh);
+ $self->{_sqlite_file} = $fn;
+ my @dsn = ("DBI:SQLite:dbname=$fn", '', '');
+ my $dbh = DBI->connect(@dsn);
+ $self->{schema} = Tangram::Relational->schema( {
+ classes => [
+ Users => {
+ fields => {
+ string => [qw/username password/],
+ },
+ },
+ ],
+ });
+ Tangram::Relational->deploy($self->schema, $dbh);
+ $dbh->disconnect;
+ $self->{storage} = Tangram::Relational->connect(
+ $self->schema, @dsn
+ );
+ my $test_user = Users->new(username => 'testuser', password => 'testpass');
+ $self->storage->insert($test_user);
+ return $self;
+}
+
+sub DESTROY {
+ my ($self) = @_;
+ $self->storage->disconnect if $self->storage;
+ unlink $self->{_sqlite_file};
+}
+
+1;
+
--- /dev/null
+mufasa:Y7hn4ncIVPOuI
--- /dev/null
+#!/usr/bin/env perl
+
+BEGIN {
+ $ENV{CATALYST_ENGINE} ||= 'HTTP';
+ $ENV{CATALYST_SCRIPT_GEN} = 31;
+ require Catalyst::Engine::HTTP;
+}
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Pod::Usage;
+use FindBin;
+use lib "$FindBin::Bin/..";
+
+my $debug = 0;
+my $fork = 0;
+my $help = 0;
+my $host = undef;
+my $port = 3000;
+my $keepalive = 0;
+my $restart = 0;
+my $restart_delay = 1;
+my $restart_regex = '\.yml$|\.yaml$|\.pm$';
+my $restart_directory = undef;
+my $background = 0;
+my $pidfile = "/tmp/testapp.pid";
+
+my @argv = @ARGV;
+
+GetOptions(
+ 'debug|d' => \$debug,
+ 'fork' => \$fork,
+ 'help|?' => \$help,
+ 'host=s' => \$host,
+ 'port=s' => \$port,
+ 'keepalive|k' => \$keepalive,
+ 'restart|r' => \$restart,
+ 'restartdelay|rd=s' => \$restart_delay,
+ 'restartregex|rr=s' => \$restart_regex,
+ 'restartdirectory=s' => \$restart_directory,
+ 'daemon' => \$background,
+ 'pidfile=s' => \$pidfile,
+);
+
+pod2usage(1) if $help;
+
+if ( $restart ) {
+ $ENV{CATALYST_ENGINE} = 'HTTP::Restarter';
+}
+if ( $debug ) {
+ $ENV{CATALYST_DEBUG} = 1;
+}
+
+# This is require instead of use so that the above environment
+# variables can be set at runtime.
+require TestApp;
+
+TestApp->run( $port, $host, {
+ argv => \@argv,
+ 'fork' => $fork,
+ keepalive => $keepalive,
+ restart => $restart,
+ restart_delay => $restart_delay,
+ restart_regex => qr/$restart_regex/,
+ restart_directory => $restart_directory,
+ background => $background,
+ pidfile => $pidfile,
+} );
+
+1;
+
+=head1 NAME
+
+testapp_server.pl - Catalyst Testserver
+
+=head1 SYNOPSIS
+
+testapp_server.pl [options]
+
+ Options:
+ -d -debug force debug mode
+ -f -fork handle each request in a new process
+ (defaults to false)
+ -? -help display this help and exits
+ -host host (defaults to all)
+ -p -port port (defaults to 3000)
+ -k -keepalive enable keep-alive connections
+ -r -restart restart when files get modified
+ (defaults to false)
+ -rd -restartdelay delay between file checks
+ -rr -restartregex regex match files that trigger
+ a restart when modified
+ (defaults to '\.yml$|\.yaml$|\.pm$')
+ -restartdirectory the directory to search for
+ modified files
+ (defaults to '../')
+
+ -daemon background the server
+ -pidfile=filename store the pid if the server in filename, if
+ daemonizing
+
+ See also:
+ perldoc Catalyst::Manual
+ perldoc Catalyst::Manual::Intro
+
+=head1 DESCRIPTION
+
+Run a Catalyst Testserver for this application.
+
+=head1 AUTHOR
+
+Sebastian Riedel, C<sri@oook.de>
+Maintained by the Catalyst Core Team.
+
+=head1 COPYRIGHT
+
+This library is free software, you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
--- /dev/null
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin/..";
+use Catalyst::Test 'TestApp';
+
+print request($ARGV[0])->content . "\n";
+
+1;
--- /dev/null
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use Test::More tests => 3;
+
+# setup library path
+use FindBin qw($Bin);
+use lib "$Bin/lib";
+
+# make sure testapp works
+use ok 'TestApp';
+
+# a live test against TestApp, the test application
+use Test::WWW::Mechanize::Catalyst 'TestApp';
+my $mech = Test::WWW::Mechanize::Catalyst->new;
+$mech->get_ok('http://localhost/', 'get main page');
+$mech->content_like(qr/^Authenticated:mufasa$/i, 'see if it has our text');
+
--- /dev/null
+#!perl -T
+
+use Test::More;
+eval "use Test::Pod::Coverage 1.04";
+plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@;
+all_pod_coverage_ok();
--- /dev/null
+#!perl -T
+
+use Test::More;
+eval "use Test::Pod 1.14";
+plan skip_all => "Test::Pod 1.14 required for testing POD" if $@;
+all_pod_files_ok();