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.
171 Stores the persist_in_session setting so it can be used to revive the user
172 even if the setting has been changed.
179 if ( $self->store->persist_in_session eq 'all' ) {
180 # use the roles accessor to ensure the roles are fetched
182 # store the persistance setting in the session to know how to
184 persist_in_session => $self->store->persist_in_session,
186 _roles => [ $self->roles ],
190 return $self->stringify;
195 Returns the raw ldap_entry.
201 return $self->user->{'ldap_entry'};
204 =head2 attributes($type)
206 Returns an array of attributes present for this user. If $type is "ashash",
207 it will return a hash with the attribute names as keys. (And the values of
208 those attributes as, well, the values of the hash)
213 my ( $self, $type ) = @_;
214 if ( $type eq "ashash" ) {
215 return $self->user->{'attributes'};
218 return keys( %{ $self->user->{'attributes'} } );
224 Returns the values for an attribute, or undef if that attribute is not present.
225 The safest way to get at an attribute.
230 my ( $self, $attribute ) = @_;
231 if ( !defined($attribute) ) {
232 Catalyst::Exception->throw(
233 "You must provide an attribute to has_attribute!");
235 if ( $attribute eq "dn" ) {
236 return $self->ldap_entry->dn;
238 elsif ( $attribute eq "username" ) {
239 return $self->user->{'attributes'}->{$self->store->user_field};
241 elsif ( exists( $self->user->{'attributes'}->{$attribute} ) ) {
242 return $self->user->{'attributes'}->{$attribute};
251 A simple wrapper around has_attribute() to satisfy the Catalyst::Authentication::User API.
255 sub get { return shift->has_attribute(@_) }
259 Satisfies the Catalyst::Authentication::User API and returns the contents of the user()
264 sub get_object { return shift->user }
266 =head2 ldap_connection
268 Re-binds to the auth store with the credentials of the user you logged in
269 as, and returns a L<Net::LDAP> object which you can use to do further queries.
273 sub ldap_connection {
275 $self->store->ldap_bind( undef, $self->ldap_entry->dn,
276 $_ldap_connection_passwords{refaddr($self)} );
279 =head2 AUTOLOADed methods
281 We automatically map the attributes of the underlying L<Net::LDAP::Entry>
282 object to read-only accessor methods. So, if you have an entry that looks
285 dn: cn=adam,ou=users,dc=yourcompany,dc=com
288 homeDirectory: /home/adam
292 mail: adam@yourcompany.com
296 objectClass: inetOrgPerson
297 objectClass: organizationalPerson
300 objectClass: posixAccount
304 $c->user->homedirectory
306 And you'll get the value of the "homeDirectory" attribute. Note that
307 all the AUTOLOADed methods are automatically lower-cased.
309 =head2 Special Keywords
311 The highly useful and common method "username" will map to the configured
312 value of user_field (uid by default.)
314 $c->user->username == $c->user->uid
320 # Don't leak passwords..
321 delete $_ldap_connection_passwords{refaddr($self)};
325 my ($self, $method) = @_;
327 return $self->SUPER::can($method) || do {
328 return unless $self->has_attribute($method);
329 return sub { $_[0]->has_attribute($method) };
336 ( my $method ) = ( our $AUTOLOAD =~ /([^:]+)$/ );
338 if ( $method eq "DESTROY" ) {
342 if ( my $attribute = $self->has_attribute($method) ) {
346 Catalyst::Exception->throw(
347 "No attribute $method for User " . $self->stringify );
357 Adam Jacob <holoway@cpan.org>
359 Some parts stolen shamelessly and entirely from
360 L<Catalyst::Plugin::Authentication::Store::Htpasswd>.
362 Currently maintained by Peter Karman <karman@cpan.org>.
366 To nothingmuch, ghenry, castaway and the rest of #catalyst for the help. :)
370 L<Catalyst::Authentication::Store::LDAP>, L<Catalyst::Authentication::Store::LDAP::Backend>, L<Catalyst::Plugin::Authentication>, L<Net::LDAP>
372 =head1 COPYRIGHT & LICENSE
374 Copyright (c) 2005 the aforementioned authors. All rights
375 reserved. This program is free software; you can redistribute
376 it and/or modify it under the same terms as Perl itself.