File Coverage

blib/lib/Catalyst/Plugin/Authentication/CDBI.pm
Criterion Covered Total %
statement 6 82 7.3
branch 0 38 0.0
condition 0 16 0.0
subroutine 2 11 18.1
pod 9 9 100.0
total 17 156 10.9


line stmt bran cond sub pod time code
1             package Catalyst::Plugin::Authentication::CDBI;
2              
3 1     1   30017 use strict;
  1         2  
  1         29  
4 1     1   4233 use NEXT;
  1         5419  
  1         1565  
5              
6             our $VERSION = '0.10';
7              
8             =head1 NAME
9              
10             Catalyst::Plugin::Authentication::CDBI - CDBI Authentication for Catalyst
11              
12             =head1 SYNOPSIS
13              
14             use Catalyst 'Authentication::CDBI';
15             __PACKAGE__->config->{authentication} = {
16             user_class => 'PetStore::Model::CDBI::Customer',
17             user_field => 'email',
18             role_class => 'PetStore::Model::CDBI::Role',
19             user_role_class => 'PetStore::Model::CDBI::CustomerRole',
20             user_role_user_field => 'customer'
21             };
22             $c->login( $user, $password );
23             $c->logout;
24             $c->session_login( $user, $password );
25             $c->session_logout;
26             $c->roles(qw/customer admin/);
27              
28             CREATE TABLE customer (
29             id INTEGER PRIMARY KEY,
30             email TEXT,
31             password TEXT
32             );
33              
34             CREATE TABLE role (
35             id INTEGER PRIMARY KEY,
36             name TEXT
37             );
38              
39             CREATE TABLE customer_role (
40             id INTEGER PRIMARY KEY,
41             customer INTEGER REFERENCES customer,
42             role INTEGER REFERENCES role
43             );
44              
45             =head1 DESCRIPTION
46              
47             This plugin allows you to authenticate your web users using database
48             tables accessed through C<Class::DBI> classes.
49              
50             Note that this plugin requires a session plugin such as
51             C<Catalyst::Plugin::Session::FastMmap>.
52              
53             This module is now well past the teatime of it's lifespan, and
54             no new features will be added. For new applications, you probably
55             want to look at L<Catalyst::Plugin::Authentication> and friends
56             instead
57              
58             =head1 CONFIGURATION
59              
60             This plugin is configured by passing an "authentication" hash
61             reference to your application's config method. The following keys are
62             supported:
63              
64             =over 4
65              
66             =item user_class
67              
68             the name of the class that represents a user object (no default)
69              
70             =item user_field
71              
72             the name of the column holding the user identifier (defaults to "C<user>")
73              
74             =item password_field
75              
76             the name of the column holding the user's password (defaults to "C<password>")
77              
78             =item password_hash
79              
80             specifies the hashing method for password values; one of: C<SHA> or
81             C<MD5> (the values are not case-sensitive and the default is empty,
82             i.e. no hashing).
83              
84             =item role_class
85              
86             the name of the role class
87              
88             =item role_field
89              
90             name of the role field
91              
92              
93             =item user_role_class
94              
95              
96             =item user_role_user_field
97              
98             (defaults to "C<uer>")
99              
100             =item user_role_role_field
101              
102             (defaults to "C<role>")
103              
104             =back
105              
106              
107             =head2 METHODS
108              
109             =over 4
110              
111             =item login
112              
113             Attempt to authenticate a user. Takes username/password as arguments,
114              
115             $c->login( $user, $password );
116              
117             The user remains authenticated until end of request. See
118             C<session_login> for persistent login.
119              
120             =cut
121              
122             sub login {
123 0     0 1   my ( $c, $user, $password ) = @_;
124 0 0         return 1 if $c->request->{user};
125 0           my $user_class = $c->config->{authentication}->{user_class};
126 0   0       my $user_field = $c->config->{authentication}->{user_field} || 'user';
127 0   0       my $password_field = $c->config->{authentication}->{password_field}
128             || 'password';
129 0   0       my $password_hash = $c->config->{authentication}->{password_hash} || '';
130 0 0         if ( $password_hash =~ /sha/i ) {
    0          
131 0           require Digest::SHA;
132 0           $password = Digest::SHA::sha1_hex($password);
133             }
134             elsif ( $password_hash =~ /md5/i ) {
135 0           require Digest::MD5;
136 0           $password = Digest::MD5::md5_hex($password);
137             }
138 0 0         if (
139             my $user_obj=$user_class->search(
140             { $user_field => $user, $password_field => $password }
141             )->next
142             )
143             {
144 0           $c->request->{user} = $user;
145 0           $c->request->{user_id} = $user_obj->id;
146 0           return 1;
147             }
148 0           return 0;
149             }
150              
151             =item logout
152              
153             Log out the user. will not clear the session, so user will still remain
154             logged in at next request unless session_logout is called.
155              
156             =cut
157              
158             sub logout {
159 0     0 1   my $c = shift;
160 0           $c->request->{user} = undef;
161 0           $c->request->{user_id} = undef;
162             }
163              
164             =item process_permission
165              
166             check for permissions. used by the 'roles' function.
167              
168             =cut
169              
170             sub process_permission {
171 0     0 1   my ( $c, $roles ) = @_;
172 0 0         if ($roles) {
173 0 0         return 1 if $#$roles < 0;
174 0           my $string = join ' ', @$roles;
175 0 0         if ( $c->process_roles($roles) ) {
176 0 0         $c->log->debug(qq/Permission granted "$string"/) if $c->debug;
177             }
178             else {
179 0 0         $c->log->debug(qq/Permission denied "$string"/) if $c->debug;
180 0           return 0;
181             }
182             }
183 0           return 1;
184             }
185              
186             =item roles
187              
188             Check permissions for roles and return true or false.
189              
190             $c->roles(qw/foo bar/);
191              
192             Returns an arrayref containing the verified roles.
193              
194             my @roles = @{ $c->roles };
195              
196             =cut
197              
198             sub roles {
199 0     0 1   my $c = shift;
200 0   0       $c->{roles} ||= [];
201 0 0         my $roles = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
202 0 0         if ( $_[0] ) {
203 0           my @roles;
204 0           foreach my $role (@$roles) {
205 0 0         push @roles, $role unless grep $_ eq $role, @{ $c->{roles} };
  0            
206             }
207 0 0         return 1 unless @roles;
208 0 0         if ( $c->process_permission( \@roles ) ) {
209 0           $c->{roles} = [ @{ $c->{roles} }, @roles ];
  0            
210 0           return 1;
211             }
212 0           else { return 0 }
213             }
214 0           return $c->{roles};
215             }
216              
217             =item session_login
218              
219             Persistently login the user. The user will remain logged in
220             until he clears the session himself, or session_logout is
221             called.
222              
223             $c->session_login( $user, $password );
224              
225             =cut
226              
227             sub session_login {
228 0     0 1   my ( $c, $user, $password ) = @_;
229 0 0         return 0 unless $c->login( $user, $password );
230 0           $c->session->{user} = $c->req->{user};
231 0           $c->session->{user_id} = $c->req->{user_id};
232 0           return 1;
233             }
234              
235             =item session_logout
236              
237             Session logout. will delete the user object from the session.
238              
239             =cut
240              
241             sub session_logout {
242 0     0 1   my $c = shift;
243 0           $c->logout;
244 0           $c->session->{user} = undef;
245 0           $c->session->{user_id} = undef;
246             }
247              
248             =back
249              
250             =head2 EXTENDED METHODS
251              
252             =over 4
253              
254             =item prepare_action
255              
256             sets $c->request->{user} from session.
257              
258             =cut
259              
260             sub prepare_action {
261 0     0 1   my $c = shift;
262 0           $c->NEXT::prepare_action(@_);
263 0           $c->request->{user} = $c->session->{user};
264 0           $c->request->{user_id} = $c->session->{user_id};
265             }
266              
267             =item setup
268              
269             sets up $c->config->{authentication}.
270              
271             =cut
272              
273             sub setup {
274 0     0 1   my $c = shift;
275 0           my $conf = $c->config->{authentication};
276 0 0         $conf = ref $conf eq 'ARRAY' ? {@$conf} : $conf;
277 0           $c->config->{authentication} = $conf;
278 0           return $c->NEXT::setup(@_);
279             }
280              
281             =back
282              
283             =head2 OVERLOADED METHODS
284              
285             =over 4
286              
287             =item process_roles
288              
289             Takes an arrayref of roles and checks if user has the supplied roles.
290             Returns 1/0.
291              
292             =cut
293              
294             sub process_roles {
295 0     0 1   my ( $c, $roles ) = @_;
296 0           my $user_class = $c->config->{authentication}->{user_class};
297 0   0       my $user_field = $c->config->{authentication}->{user_field} || 'user';
298 0           my $role_class = $c->config->{authentication}->{role_class};
299 0   0       my $role_field = $c->config->{authentication}->{role_field} || 'name';
300 0           my $user_role_class = $c->config->{authentication}->{user_role_class};
301 0   0       my $user_role_user_field =
302             $c->config->{authentication}->{user_role_user_field} || 'user';
303 0   0       my $user_role_role_field =
304             $c->config->{authentication}->{user_role_role_field} || 'role';
305              
306 0 0         if ( my $user =
307             $user_class->search( { $user_field => $c->request->{user} } )->first )
308             {
309 0           for my $role (@$roles) {
310 0 0         if ( my $role =
311             $role_class->search( { $role_field => $role } )->first )
312             {
313 0 0         return 0
314             unless $user_role_class->search(
315             {
316             $user_role_user_field => $user->id,
317             $user_role_role_field => $role->id
318             }
319             );
320             }
321 0           else { return 0 }
322             }
323             }
324 0           else { return 0 }
325 0           return 1;
326             }
327              
328             =back
329              
330              
331             =head1 SEE ALSO
332              
333             L<Catalyst>, L<Catalyst::Plugin::Session::FastMmap>
334              
335             =head1 AUTHOR
336              
337             Sebastian Riedel <sri@cpan.org>,
338             Marcus Ramberg <mramberg@cpan.org>,
339             Andrew Ford <a.ford@ford-mason.co.uk>
340              
341             =head1 COPYRIGHT
342              
343             This program is free software, you can redistribute it and/or modify it under
344             the same terms as Perl itself.
345              
346             =cut
347              
348             1;