File Coverage

blib/lib/Catalyst/Plugin/Authentication/Simple.pm
Criterion Covered Total %
statement 6 76 7.8
branch 0 40 0.0
condition 0 7 0.0
subroutine 2 11 18.1
pod 9 9 100.0
total 17 143 11.8


line stmt bran cond sub pod time code
1             package Catalyst::Plugin::Authentication::Simple;
2              
3 1     1   28713 use strict;
  1         2  
  1         35  
4 1     1   1044 use NEXT;
  1         6170  
  1         1178  
5              
6             our $VERSION = '1.00';
7              
8             =head1 NAME
9              
10             Catalyst::Plugin::Authentication::Simple
11              
12             $c->login( $user, $password );
13             $c->logout;
14             $c->session_login( $user, $password );
15             $c->session_logout;
16              
17             =head1 DESCRIPTION
18              
19             Note that this plugin requires a session plugin like
20             C<Catalyst::Plugin::Session::FastMmap>.
21              
22             =head2 METHODS
23              
24             =over 4
25              
26             =item login
27              
28             Attempt to authenticate a user. Takes username/password as arguments,
29              
30             $c->login( $user, $password );
31              
32             User remains authenticated until end of request.
33              
34             Format of user_file:
35             <username1>:<password1>:<role1>,<role2>,<role3>,...
36             <username2>:<password2>:<role1>,<role2>,<role3>,...
37              
38             OR array ref of those values in 'users' key
39              
40             Note: users_file will NOT get reloaded if you change it
41             BUT you CAN change the 'users' arrayref w/o a restart...
42              
43             =cut
44              
45             sub login {
46 0     0 1   my ( $c, $user, $password ) = @_;
47 0 0         return 1 if $c->request->{user};
48 0   0       my $password_hash = $c->config->{authentication}->{password_hash} || '';
49 0 0         if ( $password_hash =~ /sha/i ) {
    0          
50 0           require Digest::SHA;
51 0           $password = Digest::SHA::sha1_hex($password);
52             }
53             elsif ( $password_hash =~ /md5/i ) {
54 0           require Digest::MD5;
55 0           $password = Digest::MD5::md5_hex($password);
56             }
57              
58 0 0         unless ($c->config->{authentication}->{users}) {
59 0           my $user_file = $c->config->{authentication}->{user_file};
60 0 0         die "Must provide user_file!!" unless $user_file;
61 0 0         open(USERS, $user_file) || die "Can't open user_file $user_file: $!";
62 0           my @users = <USERS>;
63 0           close(USERS);
64 0           $c->config->{authentication}->{users} = [ @users ];
65             }
66              
67 0           foreach my $u_line (@{$c->config->{authentication}->{users}}) {
  0            
68 0           chomp $u_line;
69 0           my($f_user, $f_pass, $roles) = split /:/, $u_line;
70 0 0 0       if ($f_user eq $user && $f_pass eq $password) {
71 0           $c->request->{user} = $user;
72 0           $c->request->{user_roles} = { map { $_ => 1 } split /,/, $roles };
  0            
73 0           return 1;
74             }
75             }
76              
77 0           return 0;
78             }
79              
80             =item logout
81              
82             Log out the user. will not clear the session, so user will still remain
83             logged in at next request unless session_logout is called.
84              
85             =cut
86              
87             sub logout {
88 0     0 1   my $c = shift;
89 0           $c->request->{user} = undef;
90             }
91              
92             =item process_permission
93              
94             check for permissions. used by the 'roles' function.
95              
96             =cut
97              
98             sub process_permission {
99 0     0 1   my ( $c, $roles ) = @_;
100 0 0         if ($roles) {
101 0 0         return 1 if $#$roles < 0;
102 0           my $string = join ' ', @$roles;
103 0 0         if ( $c->process_roles($roles) ) {
104 0 0         $c->log->debug(qq/Permission granted "$string"/) if $c->debug;
105             }
106             else {
107 0 0         $c->log->debug(qq/Permission denied "$string"/) if $c->debug;
108 0           return 0;
109             }
110             }
111 0           return 1;
112             }
113              
114             =item roles
115              
116             Check permissions for roles and return true or false.
117              
118             $c->roles(qw/foo bar/);
119              
120             Returns an arrayref containing the verified roles.
121              
122             my @roles = @{ $c->roles };
123              
124             =cut
125              
126             sub roles {
127 0     0 1   my $c = shift;
128 0   0       $c->{roles} ||= [];
129 0 0         my $roles = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
130 0 0         if ( $_[0] ) {
131 0           my @roles;
132 0           foreach my $role (@$roles) {
133 0 0         push @roles, $role unless grep $_ eq $role, @{ $c->{roles} };
  0            
134             }
135 0 0         return 1 unless @roles;
136 0 0         if ( $c->process_permission( \@roles ) ) {
137 0           $c->{roles} = [ @{ $c->{roles} }, @roles ];
  0            
138 0           return 1;
139             }
140 0           else { return 0 }
141             }
142 0           return $c->{roles};
143             }
144              
145             =item session_login
146              
147             Persistently login the user. The user will remain logged in
148             until he clears the session himself, or session_logout is
149             called.
150              
151             $c->session_login( $user, $password );
152              
153             =cut
154              
155             sub session_login {
156 0     0 1   my ( $c, $user, $password ) = @_;
157 0 0         return 0 unless $c->login( $user, $password );
158 0           $c->session->{user} = $c->req->{user};
159 0           return 1;
160             }
161              
162             =item session_logout
163              
164             Session logout. will delete the user object from the session.
165              
166             =cut
167              
168             sub session_logout {
169 0     0 1   my $c = shift;
170 0           $c->logout;
171 0           $c->session->{user} = undef;
172             }
173              
174             =back
175              
176             =head2 EXTENDED METHODS
177              
178             =over 4
179              
180             =item prepare_action
181              
182             sets $c->request->{user} from session.
183              
184             =cut
185              
186             sub prepare_action {
187 0     0 1   my $c = shift;
188 0           $c->NEXT::prepare_action(@_);
189 0           $c->request->{user} = $c->session->{user};
190             }
191              
192             =item setup
193              
194             sets up $c->config->{authentication}.
195              
196             =cut
197              
198             sub setup {
199 0     0 1   my $c = shift;
200 0           my $conf = $c->config->{authentication};
201 0 0         $conf = ref $conf eq 'ARRAY' ? {@$conf} : $conf;
202 0           $c->config->{authentication} = $conf;
203 0           return $c->NEXT::setup(@_);
204             }
205              
206             =back
207              
208             =head2 OVERLOADED METHODS
209              
210             =over 4
211              
212             =item process_roles
213              
214             Takes an arrayref of roles and checks if user has the supplied roles.
215             Returns 1/0.
216              
217             =cut
218              
219             sub process_roles {
220 0     0 1   my ( $c, $roles ) = @_;
221              
222 0           for my $role (@$roles) {
223 0 0         return 0 unless $c->{user_roles}->{$role};
224             }
225 0           return 1;
226             }
227              
228             =back
229              
230             =head1 SEE ALSO
231              
232             L<Catalyst>.
233             L<Catalyst::Plugin::Authentication::CDBI>.
234             L<Catalyst::Plugin::Authentication::LDAP>.
235              
236             =head1 AUTHOR
237              
238             Mark Ethan Trostler, C<mark@zoo.com>
239              
240             =head1 COPYRIGHT
241              
242             This program is free software, you can redistribute it and/or modify it under
243             the same terms as Perl itself.
244              
245             =cut
246              
247             1;
248