6 Catalyst::Authentication::Store::LDAP::User
7 - A User object representing an LDAP object.
11 You should be creating these objects through L<Catalyst::Authentication::Store::LDAP::Backend>'s "get_user" method, or just letting $c->authenticate do
15 my ( $self, $c ) = @_;
17 id => $c->req->param(username),
18 password => $c->req->param(password)
20 $c->log->debug($c->user->username . "is really neat!");
23 If you access just $c->user in a scalar context, it will return the current
28 This wraps up an LDAP object and presents a simplified interface to it's
29 contents. It uses some AUTOLOAD magic to pass method calls it doesn't
30 understand through as simple read only accessors for the LDAP entries
33 It gets grumpy if you ask for an attribute via the AUTOLOAD mechanism
34 that it doesn't know about. Avoid that with using "has_attribute",
35 discussed in more detail below.
37 You can skip all that and just go straight to the L<Net::LDAP::Entry>
38 object through the "ldap_entry" method:
40 my $entry = $c->user->ldap_entry;
42 It also has support for Roles.
46 package Catalyst::Authentication::Store::LDAP::User;
47 use base qw( Catalyst::Authentication::User Class::Accessor::Fast );
52 our $VERSION = '0.1005';
54 BEGIN { __PACKAGE__->mk_accessors(qw/user store _ldap_connection_password/) }
56 use overload '""' => sub { shift->stringify }, fallback => 1;
60 =head2 new($store, $user, $c)
62 Takes a L<Catalyst::Authentication::Store::LDAP::Backend> object
63 as $store, and the data structure returned by that class's "get_user"
64 method as $user. The final argument is an instance of your application,
65 which is passed along for those wanting to subclass User and perhaps use
66 models for fetching data.
68 Returns a L<Catalyst::Authentication::Store::LDAP::User> object.
73 my ( $class, $store, $user, $c ) = @_;
77 bless { store => $store, user => $user, }, $class;
82 Returns the results of the "stringify" method.
88 return $self->stringify;
93 Uses the "user_field" configuration option to determine what the "username"
94 of this object is, and returns it.
96 If you use the special value "dn" for user_field, it will return the DN
97 of the L<Net::LDAP::Entry> object.
103 my $userfield = $self->store->user_field;
104 $userfield = $$userfield[0] if ref $userfield eq 'ARRAY';
105 if ( $userfield eq "dn" ) {
106 my ($string) = $self->user->ldap_entry->dn;
110 my ($string) = $self->$userfield;
115 =head2 supported_features
117 Returns hashref of features that this Authentication::User subclass supports.
121 sub supported_features {
123 password => { self_check => 1, },
125 roles => { self_check => 0, },
129 =head2 check_password($password)
131 Bind's to the directory as the DN of the internal L<Net::LDAP::Entry> object,
132 using the bind password supplied in $password. Returns 1 on a successful
138 my ( $self, $password ) = @_;
140 = $self->store->ldap_bind( undef, $self->ldap_entry->dn, $password,
142 if ( defined($ldap) ) {
143 if ($self->store->role_search_as_user) {
144 # FIXME - This can be removed and made to use the code below..
145 # Have to do the role lookup _now_, as this is the only time
146 # that we have the user's password/ldap bind..
149 # Stash a closure which can be used to retrieve the connection in the users context later.
150 $self->_ldap_connection_password( sub { $password } ); # Close over
151 # password to try to ensure it doesn't come out in debug dumps
152 # or get serialized into sessions etc..
162 Returns the results of L<Catalyst::Authentication::Store::LDAP::Backend>'s "lookup_roles" method, an array of roles that are valid for this user.
169 $self->{_roles} ||= [$self->store->lookup_roles($self, $ldap)];
170 return @{$self->{_roles}};
175 Returns the User object, stringified.
181 return $self->stringify;
186 Returns the raw ldap_entry.
192 return $self->user->{'ldap_entry'};
195 =head2 attributes($type)
197 Returns an array of attributes present for this user. If $type is "ashash",
198 it will return a hash with the attribute names as keys. (And the values of
199 those attributes as, well, the values of the hash)
204 my ( $self, $type ) = @_;
205 if ( $type eq "ashash" ) {
206 return $self->user->{'attributes'};
209 return keys( %{ $self->user->{'attributes'} } );
215 Returns the values for an attribute, or undef if that attribute is not present.
216 The safest way to get at an attribute.
221 my ( $self, $attribute ) = @_;
222 if ( !defined($attribute) ) {
223 Catalyst::Exception->throw(
224 "You must provide an attribute to has_attribute!");
226 if ( $attribute eq "dn" ) {
227 return $self->ldap_entry->dn;
229 elsif ( exists( $self->user->{'attributes'}->{$attribute} ) ) {
230 return $self->user->{'attributes'}->{$attribute};
237 =head2 ldap_connection
239 Re-binds to the auth store with the credentials of the user you logged in
240 as, and returns a L<Net::LDAP> object which you can use to do further queries.
244 sub ldap_connection {
246 my $msg = $self->store->ldap_bind( undef, $self->ldap_entry->dn,
247 $self->_ldap_connection_password->() );
248 $msg->code && die("Error whilst re-binding as " . $self->ldap_entry->dn
249 . " after auth: " . $msg->error . " (" . $msg->code . ")");
253 =head2 AUTOLOADed methods
255 We automatically map the attributes of the underlying L<Net::LDAP::Entry>
256 object to read-only accessor methods. So, if you have an entry that looks
259 dn: cn=adam,ou=users,dc=yourcompany,dc=com
262 homeDirectory: /home/adam
266 mail: adam@yourcompany.com
270 objectClass: inetOrgPerson
271 objectClass: organizationalPerson
274 objectClass: posixAccount
278 $c->user->homedirectory
280 And you'll get the value of the "homeDirectory" attribute. Note that
281 all the AUTOLOADed methods are automatically lower-cased.
283 =head2 Special Keywords
285 The highly useful and common method "username" will map to the configured
286 value of user_field (uid by default.)
288 $c->user->username == $c->user->uid
295 ( my $method ) = ( our $AUTOLOAD =~ /([^:]+)$/ );
297 if ( $method eq "DESTROY" ) {
300 if ( exists( $self->user->{'attributes'}->{$method} ) ) {
301 return $self->user->{'attributes'}->{$method};
303 elsif ( $method eq "username" ) {
304 my $userfield = $self->store->user_field;
305 my $username = $self->has_attribute($userfield);
310 Catalyst::Exception->throw( "User is missing the "
312 . " attribute, which should not be possible!" );
316 Catalyst::Exception->throw(
317 "No attribute $method for User " . $self->stringify );
327 Adam Jacob <holoway@cpan.org>
329 Some parts stolen shamelessly and entirely from
330 L<Catalyst::Plugin::Authentication::Store::Htpasswd>.
332 Currently maintained by Peter Karman <karman@cpan.org>.
336 To nothingmuch, ghenry, castaway and the rest of #catalyst for the help. :)
340 L<Catalyst::Authentication::Store::LDAP>, L<Catalyst::Authentication::Store::LDAP::Backend>, L<Catalyst::Plugin::Authentication>, L<Net::LDAP>
342 =head1 COPYRIGHT & LICENSE
344 Copyright (c) 2005 the aforementioned authors. All rights
345 reserved. This program is free software; you can redistribute
346 it and/or modify it under the same terms as Perl itself.