File Coverage

blib/lib/CGI/Builder/Auth/Context.pm
Criterion Covered Total %
statement 72 83 86.7
branch 24 44 54.5
condition 2 8 25.0
subroutine 21 22 95.4
pod 14 17 82.3
total 133 174 76.4


line stmt bran cond sub pod time code
1             package CGI::Builder::Auth::Context
2              
3             # This file uses the "Perlish" coding style
4             # please read http://perl.4pro.net/perlish_coding_style.html
5              
6             ; use strict
7              
8 1     1   30874 ; our $VERSION = '0.04'
  1         2  
  1         45  
9              
10             ; use File::Spec
11              
12 1     1   5 ; use Class::constr { init => [ qw/ load_token / ] }
  1         2  
  1         21  
  1         8  
13              
14 1     1   680 ; use Object::props
  1         763  
15             ( { name => 'user'
16 2         1020 , default => sub { $_[0]->User_factory->anonymous }
17             }
18             , { name => 'realm'
19             , default => 'main'
20             }
21             , { name => 'owner'
22             }
23             , { name => 'session'
24             , default => sub
25 6 50 33     352 { ref($_[0]->owner) && $_[0]->owner->can('cs')
26             ? $_[0]->owner->cs
27             : undef
28             }
29             }
30             )
31 1     1   1031 ; use Class::groups
  1         2383  
  1         18  
32 1         17 ( { name => 'config'
33             , props =>
34             [ { name => 'magic_string'
35             , default => 'This is the default magic string, change it to
36             something unique for your application'
37             }
38             , { name => 'User_factory'
39             , default => 'CGI::Builder::Auth::User'
40             , validation => \&load_factory
41             }
42             , { name => 'Group_factory'
43             , default => 'CGI::Builder::Auth::Group'
44             , validation => \&load_factory
45             }
46             ]
47             }
48             )
49            
50 1     1 1 1087 ; sub user_list { $_[0]->User_factory->list }
  1     3   1206  
  3         1692  
51 4     4 1 1115 ; sub group_list { $_[0]->Group_factory->list }
52              
53 2     2 1 21 ; sub add_user { shift()->User_factory->add(@_) }
54 1     1 1 4 ; sub add_group { shift()->Group_factory->add(@_) }
55              
56             ; sub delete_user
57 2     2 1 6 { my ($self,$user) = @_;
58 2 50       14 ; ref($user) or $user = $self->User_factory->load(id => $user)
59 2 50       19 ; return $user ? $user->delete : undef
60             }
61             ; sub delete_group
62 1     1 1 443 { my ($self,$group) = @_;
63 1 50       7 ; ref($group) or $group = $self->Group_factory->load(id => $group)
64 1 50       9 ; return $group ? $group->delete : undef
65             }
66              
67             ; sub add_member
68 2     2 1 9 { my ($self, $group, @users) = @_
69 2 50       37 ; ref($group) or $group = $self->Group_factory->load(id => $group)
70 2 50       26 ; return unless defined($group)
71 2         8 ; for (@users) { $group->add_member($_) }
  2         11  
72 2         11 ; 1
73             }
74             ; sub remove_member
75 1     1 1 975 { my ($self, $group, @users) = @_
76 1 50       20 ; ref($group) or $group = $self->Group_factory->load(id => $group)
77 1 50       10 ; return unless defined($group)
78 1         3 ; for (@users) { $group->remove_member($_) }
  2         9  
79 1         6 ; 1
80             }
81             ; sub group_members
82 1     1 1 2 { my ($self,$group) = @_
83 1 50       7 ; ref($group) or $group = $self->Group_factory->load(id => $group)
84 1 50       11 ; return unless defined($group)
85 1         4 ; $group->member_list
86             }
87              
88             ; sub login
89 2     2 1 5 { my ($self,$username,$pass) = @_
90 2 50       10 ; my $user = $self->User_factory->load(id => $username) or return
91              
92 2 100       48 ; if ($user->password_matches($pass) )
93 1         61 { $self->user($user)
94 1 50       5 ; if ( $self->session )
95 0         0 { $self->session->param('CBA_Token',
96             $self->mk_token($username,$self->session->id) )
97             }
98 1         29 ; return $user
99             }
100 1         49 else { return }
101             }
102              
103             ; sub logout
104 1     1 1 441 { my ($self) = @_
105 1 50       5 ; if ($self->session) { $self->session->clear(['CBA_Token']) }
  0         0  
106 1         29 ; $self->user( undef )
107 1         3 ; 1
108             }
109              
110 3     3 1 1800 ; sub require_valid_user { $_[0]->user ne 'anonymous' }
111              
112             ; sub require_user
113 3     3 1 7 { my ($self, @users) = @_
114 3         4 ; my $match = 0
115 3 100       6 ; for (@users) { $match++,last if $self->user eq $_ }
  3         7  
116 3         91 ; return $match
117             }
118              
119             ; sub require_group
120 4     4 1 822 { my ($self, @groups) = @_
121 4         9 ; my $match = 0
122 4         9 ; GROUP: for my $g (@groups)
123 4 50       23 { ref($g) or $g = $self->Group_factory->load(id => $g)
124 4 100       34 ; next GROUP unless defined($g)
125 3         19 ; for ( $g->member_list )
126 1 50       5 { $match++,last GROUP if $_ eq $self->user
127             }
128             }
129 4         71 ; return $match
130             }
131              
132              
133             ; sub mk_token
134 0     0 0 0 { my ($self,$user,$sid) = @_;
135             ; require Digest::MD5
136 0         0 ; my $time = time
  0         0  
137 0         0 ; my $hash = Digest::MD5::md5_hex(join ":", $sid, $time, $user, $self->magic_string)
138 0         0 ; return join ":", $hash, $sid, $time, $user
139             }
140              
141              
142             ; sub load_token
143 1     1 0 56 { my ($self, $token) = @_
144 1 50 33     7 ; if ($self->session and $token = $self->session->param('CBA_Token') )
145             { require Digest::MD5
146 0         0 ; my ($digest,$sid,$time,$username) = split /:/, $token, 4
  0         0  
147 0 0       0 ; if ($digest eq Digest::MD5::md5_hex(
148             join ":",, $sid, $time, $username, $self->magic_string
149             )
150             )
151 0   0     0 { $self->user( $self->User_factory->load(id => $username) || undef )
152             }
153             }
154             }
155              
156              
157             ; sub load_factory
158             { ref $_
159             ? 1
160 2 50   2 0 119 : eval { require File::Spec->catfile( split /::/ ) . ".pm"}
  2         1641  
161             }
162              
163             =head1 NAME
164              
165             CGI::Builder::Auth::Context - Encapsulate an authentication context for an application
166              
167             =head1 DESCRIPTION
168              
169             The Class provides an API for manipulating the User and Group tables.
170              
171             The context object keeps track of who the current user is and what groups that
172             user belongs to. The username 'anonymous' is used to indicate that a user is
173             not currently logged in. The name 'anonymous' is reserved and may not be used
174             in the real user database.
175              
176             When the context object is created, it checks the current session (if
177             available) for an authentication token, and restores the context to its
178             previous state based on this token. That is, it automatically logs in the user.
179              
180             =head1 CLASS METHODS
181              
182             =head2 Manipulate the User table ("htpasswd")
183              
184             =head3 C
185              
186             Returns a list of all users in the user table, as user objects.
187              
188              
189             =head3 C
190              
191             Adds the user to the table. Returns the user object on success, false on
192             failure. Will fail if a user already exists with that name.
193              
194             Required Attributes:
195              
196             =over
197              
198             =item * username
199              
200             =item * password
201              
202             =back
203              
204             Additional, customizable attributes may be supported in a future release.
205              
206              
207             =head3 C
208              
209             Deletes the named user from the table. The $user parameter may be a user object
210             or a string containing the username. Returns true on success, false on failure.
211              
212              
213             =head2 Manipulate the Group table ("htgroup")
214              
215             =head3 C
216              
217             Returns a list of all groups in the group table, as group objects.
218              
219              
220             =head3 C
221              
222             Adds the group to the table. Returns the group object on success, false on
223             failure. Will fail if a group already exists with that name.
224              
225              
226             =head3 C
227              
228             Deletes the named group from the table. The $group parameter may be a group
229             object or a string containing the groupname. Returns true on success, false on
230             failure.
231              
232              
233             =head3 C
234              
235             Make the @users members of the named $group. The $group parameter may be a
236             group object or a string containing the groupname. The @users parameter may
237             contain either user objects, strings containing usernames, or any combination.
238             Returns true on success, false on failure.
239              
240              
241             =head3 C
242              
243             Remove the @users from the named $group (without removing the user account
244             itself). The $group parameter may be a group object or a string containing the
245             groupname. The @users parameter may contain either user objects, strings
246             containing usernames, or any combination. Returns true on success, false on
247             failure.
248              
249              
250             =head3 C
251              
252             Returns a list of all users who are members of the group. The list will contain
253             user objects. The $group parameter may be a group object or a string containing
254             the groupname.
255              
256              
257             =head1 INSTANCE (OBJECT) METHODS
258              
259             =head3 C
260              
261             Returns the current user for this context (your application). Optionally sets
262             the current user to the value passed in $new_user, but normally you will use
263             C to set the user instead, because C validates the password and
264             then updates the session. This method does neither. If provided, $new_user
265             I be a user object, not a string.
266              
267             Defaults to the non-existent user 'anonymous'.
268              
269              
270             =head3 C
271              
272             If the password matches the one in the user database for the named user, sets
273             the current user for this context, saves an authentication token to the current
274             session (if available), and returns the user object. Otherwise, returns false
275             and does not change the context nor the session.
276              
277              
278             =head3 C
279              
280             Sets the current user to the anonymous user, and removes the authentication
281             token from the session (if available).
282              
283              
284             =head3 C
285              
286             Returns true if the current user for this context is a real user in the
287             database (rather than the default anonymous user).
288              
289              
290             =head3 C
291              
292             Returns true if the current user is a member of at least one of the @groups.
293             The @groups parameter may contain group objects, strings, or any combination.
294              
295              
296             =head3 C
297              
298             Returns true if the current user is one of the @users. The @users parameter may
299             contain either user objects, strings containing usernames, or any combination.
300              
301             =head1 SUPPORT
302              
303             Support for this module and all the modules of the CBF is via the mailing list.
304             The list is used for general support on the use of the CBF, announcements, bug
305             reports, patches, suggestions for improvements or new features. The API to the
306             CBF is stable, but if you use the CBF in a production environment, it's
307             probably a good idea to keep a watch on the list.
308              
309             You can join the CBF mailing list at this url:
310              
311             L
312              
313              
314             =head1 AUTHOR
315              
316             Vincent Veselosky
317              
318              
319             =head1 COPYRIGHT AND LICENSE
320              
321             Copyright 2004 by Vincent Veselosky
322              
323             This library is free software; you can redistribute it and/or modify
324             it under the same terms as Perl itself.
325              
326              
327             =cut
328            
329             "Copyright 2004 Vincent Veselosky [[http://control-escape.com]]";
330             # vim:expandtab:sw=3:ts=3:ft=perl: