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 );
51 use Scalar::Util qw/refaddr/;
54 our $VERSION = '1.015';
56 BEGIN { __PACKAGE__->mk_accessors(qw/user store/) }
58 use overload '""' => sub { shift->stringify }, fallback => 1;
60 my %_ldap_connection_passwords; # Store inside-out so that they don't show up
65 =head2 new($store, $user, $c)
67 Takes a L<Catalyst::Authentication::Store::LDAP::Backend> object
68 as $store, and the data structure returned by that class's "get_user"
69 method as $user. The final argument is an instance of your application,
70 which is passed along for those wanting to subclass User and perhaps use
71 models for fetching data.
73 Returns a L<Catalyst::Authentication::Store::LDAP::User> object.
78 my ( $class, $store, $user, $c, $roles ) = @_;
82 bless { store => $store, user => $user, _roles => $roles }, $class;
87 Returns the results of the "stringify" method.
93 return $self->stringify;
98 Uses the "user_field" configuration option to determine what the "username"
99 of this object is, and returns it.
101 If you use the special value "dn" for user_field, it will return the DN
102 of the L<Net::LDAP::Entry> object.
108 my $userfield = $self->store->user_field;
109 $userfield = $$userfield[0] if ref $userfield eq 'ARRAY';
110 if ( $userfield eq "dn" ) {
111 my ($string) = $self->user->ldap_entry->dn;
115 my $val = $self->$userfield;
116 return ref($val) eq 'ARRAY' ? $val->[0] : $val;
120 =head2 supported_features
122 Returns hashref of features that this Authentication::User subclass supports.
126 sub supported_features {
128 password => { self_check => 1, },
130 roles => { self_check => 0, },
134 =head2 check_password($password)
136 Bind's to the directory as the DN of the internal L<Net::LDAP::Entry> object,
137 using the bind password supplied in $password. Returns 1 on a successful
143 my ( $self, $password ) = @_;
144 if ( $self->store->ldap_auth($self->ldap_entry->dn, $password) ) {
145 # Stash a closure which can be used to retrieve the connection in the users context later.
146 $_ldap_connection_passwords{refaddr($self)} = $password;
156 Returns the results of L<Catalyst::Authentication::Store::LDAP::Backend>'s "lookup_roles" method, an array of roles that are valid for this user.
162 $self->{_roles} ||= [$self->store->lookup_roles($self)];
163 return @{$self->{_roles}};
168 Returns the user for persistence in the session depending on the
169 persist_in_session config option.
176 if ( $self->store->persist_in_session eq 'all' ) {
177 # use the roles accessor to ensure the roles are fetched
178 return { user => $self->user, _roles => [ $self->roles ] };
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 ( $attribute eq "username" ) {
230 return $self->user->{'attributes'}->{$self->store->user_field};
232 elsif ( exists( $self->user->{'attributes'}->{$attribute} ) ) {
233 return $self->user->{'attributes'}->{$attribute};
242 A simple wrapper around has_attribute() to satisfy the Catalyst::Authentication::User API.
246 sub get { return shift->has_attribute(@_) }
250 Satisfies the Catalyst::Authentication::User API and returns the contents of the user()
255 sub get_object { return shift->user }
257 =head2 ldap_connection
259 Re-binds to the auth store with the credentials of the user you logged in
260 as, and returns a L<Net::LDAP> object which you can use to do further queries.
264 sub ldap_connection {
266 $self->store->ldap_bind( undef, $self->ldap_entry->dn,
267 $_ldap_connection_passwords{refaddr($self)} );
270 =head2 AUTOLOADed methods
272 We automatically map the attributes of the underlying L<Net::LDAP::Entry>
273 object to read-only accessor methods. So, if you have an entry that looks
276 dn: cn=adam,ou=users,dc=yourcompany,dc=com
279 homeDirectory: /home/adam
283 mail: adam@yourcompany.com
287 objectClass: inetOrgPerson
288 objectClass: organizationalPerson
291 objectClass: posixAccount
295 $c->user->homedirectory
297 And you'll get the value of the "homeDirectory" attribute. Note that
298 all the AUTOLOADed methods are automatically lower-cased.
300 =head2 Special Keywords
302 The highly useful and common method "username" will map to the configured
303 value of user_field (uid by default.)
305 $c->user->username == $c->user->uid
311 # Don't leak passwords..
312 delete $_ldap_connection_passwords{refaddr($self)};
316 my ($self, $method) = @_;
318 return $self->SUPER::can($method) || do {
319 return unless $self->has_attribute($method);
320 return sub { $_[0]->has_attribute($method) };
327 ( my $method ) = ( our $AUTOLOAD =~ /([^:]+)$/ );
329 if ( $method eq "DESTROY" ) {
333 if ( my $attribute = $self->has_attribute($method) ) {
337 Catalyst::Exception->throw(
338 "No attribute $method for User " . $self->stringify );
348 Adam Jacob <holoway@cpan.org>
350 Some parts stolen shamelessly and entirely from
351 L<Catalyst::Plugin::Authentication::Store::Htpasswd>.
353 Currently maintained by Peter Karman <karman@cpan.org>.
357 To nothingmuch, ghenry, castaway and the rest of #catalyst for the help. :)
361 L<Catalyst::Authentication::Store::LDAP>, L<Catalyst::Authentication::Store::LDAP::Backend>, L<Catalyst::Plugin::Authentication>, L<Net::LDAP>
363 =head1 COPYRIGHT & LICENSE
365 Copyright (c) 2005 the aforementioned authors. All rights
366 reserved. This program is free software; you can redistribute
367 it and/or modify it under the same terms as Perl itself.