dzilified this dist
[catagits/Catalyst-Authentication-Store-Htpasswd.git] / lib / Catalyst / Authentication / Store / Htpasswd.pm
1 #!/usr/bin/perl
2
3 package Catalyst::Authentication::Store::Htpasswd;
4 # ABSTRACT: Authen::Htpasswd based user storage/authentication
5
6 use base qw/Class::Accessor::Fast/;
7 use strict;
8 use warnings;
9
10 use Authen::Htpasswd 0.13;
11 use Catalyst::Authentication::Store::Htpasswd::User;
12 use Scalar::Util qw/blessed/;
13
14 our $VERSION = '1.005';
15
16 BEGIN { __PACKAGE__->mk_accessors(qw/file user_field user_class/) }
17
18 sub new {
19     my ($class, $config, $app, $realm) = @_;
20     
21     my $file = delete $config->{file};
22     unless (ref $file) {
23         my $filename = ($file =~ m|^/|) ? $file : $app->path_to($file)->stringify;
24         die("Cannot find htpasswd file: $filename\n") unless (-r $filename);
25         $file = Authen::Htpasswd->new($filename);
26     }
27     $config->{file} = $file;
28     $config->{user_class} ||= __PACKAGE__ . '::User';
29     $config->{user_field} ||= 'username';
30     
31     bless { %$config }, $class;
32 }
33
34 sub find_user {
35     my ($self, $authinfo, $c) = @_;
36     my $htpasswd_user = $self->file->lookup_user($authinfo->{$self->user_field});
37     $self->user_class->new( $self, $htpasswd_user );
38 }
39
40 sub user_supports {
41     my $self = shift;
42
43     # this can work as a class method, but in that case you can't have 
44     # a custom user class
45     ref($self) ? $self->user_class->supports(@_)
46         : Catalyst::Authentication::Store::Htpasswd::User->supports(@_);
47 }
48
49 sub from_session {
50         my ( $self, $c, $id ) = @_;
51         $self->find_user( { username => $id } );
52 }
53
54 1;
55
56 __END__
57
58 =pod
59
60 =head1 SYNOPSIS
61
62     use Catalyst qw/
63       Authentication
64     /;
65
66     __PACKAGE__->config(
67         authentication => {
68             default_realm => 'test',
69             realms => {
70                 test => {
71                     credential => {
72                         class          => 'Password',
73                         password_field => 'password',
74                         password_type  => 'self_check',
75                     },
76                     store => {
77                         class => 'Htpasswd',
78                         file => 'htpasswd',
79                     },
80                 },
81             },
82         },   
83     );
84
85     sub login : Global {
86         my ( $self, $c ) = @_;
87
88         $c->authenticate({ username => $c->req->param("login"), password => $c->req->param("password") });
89     }
90
91 =head1 DESCRIPTION
92
93 This plugin uses L<Authen::Htpasswd> to let your application use C<<.htpasswd>>
94 files for it's authentication storage.
95
96 =head1 METHODS
97
98 =head2 new
99
100 Simple constructor, dies if the htpassword file can't be found
101
102 =head2 find_user
103
104 Looks up the user, and returns a Catalyst::Authentication::Store::Htpasswd::User object.
105
106 =head2 user_supports
107
108 Delegates to L<Catalyst::Authentication::Store::Htpasswd::User->user_supports|Catalyst::Authentication::Store::Htpasswd::User#user_supports>
109
110 =head2 from_session
111
112 Delegates the user lookup to C<< find_user >>
113
114 =head1 CONFIGURATION
115
116 =head2 file
117
118 The path to the htpasswd file. If the path starts with a slash, then it is assumed to be a fully
119 qualified path, otherwise the path is fed through C<< $c->path_to >> and so normalised to the 
120 application root.
121
122 Alternatively, it is possible to pass in an L<Authen::Htpasswd> object here, and this will be
123 used as the htpasswd file.
124
125 =head2 user_class
126
127 Change the user class which this store returns. Defaults to L<Catalyst::Authentication::Store::Htpasswd::User>.
128 This can be used to add additional functionality to the user class by sub-classing it, but will not normally be
129 needed.
130
131 =head2 user_field
132
133 Change the field that the username is found in in the information passed into the call to C<< $c->authenticate() >>.
134
135 This defaults to I< username >, and generally you should be able to use the module as shown in the synopsis, however
136 if you need a different field name then this setting can change the default.
137
138 Example:
139
140     __PACKAGE__->config( authentication => { realms => { test => {
141                     store => {
142                         class => 'Htpasswd',
143                         user_field => 'email_address',
144                     },
145     }}});
146     # Later in your code
147     $c->authenticate({ email_address => $c->req->param("email"), password => $c->req->param("password") });
148
149 =head1 SEE ALSO
150
151 L<Authen::Htpasswd>.
152
153 =cut