Skip Menu |

This queue is for tickets about the Catalyst-Authentication-Store-LDAP CPAN distribution.

Report information
The Basics
Id: 43397
Status: resolved
Priority: 0/
Queue: Catalyst-Authentication-Store-LDAP

People
Owner: Nobody in particular
Requestors: bobtfish [...] bobtfish.net
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.1004
Fixed in: (no value)



Subject: Should not throw an exception when user cannot be found
Hiya When a user cannot be found in your store, you should return undef rather than throwing an exception. If you throw an exception, it ripples up and has to be caught by the caller who called $c->authenticate, whereas usually you just use the truth of the return value to determine a user logged in. Currently the behavior isn't documented or tested, so I've attached a which corrects the behavior and adds tests / docs.
Subject: Catalyst-Authentication-Store-LDAP-noexception.diff
diff -ur Catalyst-Authentication-Store-LDAP-0.1004/Changes Catalyst-Authentication-Store-LDAP-0.1004.t0m/Changes --- Catalyst-Authentication-Store-LDAP-0.1004/Changes 2008-10-22 02:54:50.000000000 +0100 +++ Catalyst-Authentication-Store-LDAP-0.1004.t0m/Changes 2009-02-18 15:06:14.000000000 +0000 @@ -1,3 +1,8 @@ +0.1005 UNRELEASED + - Stop throwing an exception when the lookup_user method fails + to find a user and instead return undef. (t0m) + - Add tests for this (t0m) + 0.1004 21 Oct 2008 - Add the ability to have the user inflated into a custom user class with the user_class option (t0m) diff -ur Catalyst-Authentication-Store-LDAP-0.1004/lib/Catalyst/Authentication/Store/LDAP/Backend.pm Catalyst-Authentication-Store-LDAP-0.1004.t0m/lib/Catalyst/Authentication/Store/LDAP/Backend.pm --- Catalyst-Authentication-Store-LDAP-0.1004/lib/Catalyst/Authentication/Store/LDAP/Backend.pm 2008-10-22 02:46:27.000000000 +0100 +++ Catalyst-Authentication-Store-LDAP-0.1004.t0m/lib/Catalyst/Authentication/Store/LDAP/Backend.pm 2009-02-18 15:17:57.000000000 +0000 @@ -80,7 +80,7 @@ use strict; use warnings; -our $VERSION = '0.1004'; +our $VERSION = '0.1005'; use Catalyst::Authentication::Store::LDAP::User; use Net::LDAP; @@ -263,11 +263,12 @@ A) Bind to the directory using the configured binddn and bindpw B) Perform a search for the User Object in the directory, using user_basedn, user_filter, and user_scope. - C) Assuming we found the object, we will walk it's attributes + C) Assuming we found the object, we will walk it's attributes using L<Net::LDAP::Entry>'s get_value method. We store the - results in a hashref. - D) Return a hashref that looks like: - + results in a hashref. If we do not find the object, then + undef is returned. + D) Return a hashref that looks like: + $results = { 'ldap_entry' => $entry, # The Net::LDAP::Entry object 'attributes' => $attributes, @@ -300,10 +301,9 @@ push( @searchopts, %{ $self->user_search_options } ); } my $usersearch = $ldap->search(@searchopts); - if ( $usersearch->is_error ) { - Catalyst::Exception->throw( - "LDAP Error while searching for user: " . $usersearch->error ); - } + + return if ( $usersearch->is_error ); + my $userentry; my $user_field = $self->user_field; my $results_filter = $self->user_results_filter; diff -ur Catalyst-Authentication-Store-LDAP-0.1004/lib/Catalyst/Authentication/Store/LDAP/User.pm Catalyst-Authentication-Store-LDAP-0.1004.t0m/lib/Catalyst/Authentication/Store/LDAP/User.pm --- Catalyst-Authentication-Store-LDAP-0.1004/lib/Catalyst/Authentication/Store/LDAP/User.pm 2008-10-22 02:46:27.000000000 +0100 +++ Catalyst-Authentication-Store-LDAP-0.1004.t0m/lib/Catalyst/Authentication/Store/LDAP/User.pm 2009-02-18 15:06:40.000000000 +0000 @@ -46,7 +46,7 @@ use strict; use warnings; -our $VERSION = '0.1004'; +our $VERSION = '0.1005'; BEGIN { __PACKAGE__->mk_accessors(qw/user store/) } diff -ur Catalyst-Authentication-Store-LDAP-0.1004/lib/Catalyst/Authentication/Store/LDAP.pm Catalyst-Authentication-Store-LDAP-0.1004.t0m/lib/Catalyst/Authentication/Store/LDAP.pm --- Catalyst-Authentication-Store-LDAP-0.1004/lib/Catalyst/Authentication/Store/LDAP.pm 2008-10-22 02:46:27.000000000 +0100 +++ Catalyst-Authentication-Store-LDAP-0.1004.t0m/lib/Catalyst/Authentication/Store/LDAP.pm 2009-02-18 15:06:23.000000000 +0000 @@ -3,7 +3,7 @@ use strict; use warnings; -our $VERSION = '0.1004'; +our $VERSION = '0.1005'; use Catalyst::Authentication::Store::LDAP::Backend; diff -ur Catalyst-Authentication-Store-LDAP-0.1004/Makefile.PL Catalyst-Authentication-Store-LDAP-0.1004.t0m/Makefile.PL --- Catalyst-Authentication-Store-LDAP-0.1004/Makefile.PL 2008-10-22 02:45:33.000000000 +0100 +++ Catalyst-Authentication-Store-LDAP-0.1004.t0m/Makefile.PL 2009-02-18 15:04:36.000000000 +0000 @@ -13,6 +13,7 @@ build_requires('Net::LDAP::Server::Test' => '0.07'); build_requires('Test::More'); build_requires('Test::MockObject'); +build_required('Test::Exception'); auto_install(); diff -ur Catalyst-Authentication-Store-LDAP-0.1004/t/10-roles-mock.t Catalyst-Authentication-Store-LDAP-0.1004.t0m/t/10-roles-mock.t --- Catalyst-Authentication-Store-LDAP-0.1004/t/10-roles-mock.t 2008-10-22 02:44:50.000000000 +0100 +++ Catalyst-Authentication-Store-LDAP-0.1004.t0m/t/10-roles-mock.t 2009-02-18 15:22:20.000000000 +0000 @@ -4,8 +4,9 @@ use warnings; use Catalyst::Exception; -use Test::More tests => 7; +use Test::More tests => 11; use Test::MockObject::Extends; +use Test::Exception; use Net::LDAP::Entry; use lib 't/lib'; @@ -46,7 +47,8 @@ $ldap->mock('unbind' => sub {}); $ldap->mock('disconnect' => sub {}); my $search_res = Test::MockObject->new(); - $search_res->mock(is_error => sub {}); # Never an error + my $search_is_error = 0; + $search_res->mock(is_error => sub { $search_is_error }); $search_res->mock(entries => sub { return map { my $id = $_; @@ -73,12 +75,21 @@ is_deeply( [sort $user->roles], [sort qw/quuxone quuxtwo/], "User has the expected set of roles" ); + + $search_is_error = 1; + lives_ok { + ok !$back->find_user( { username => 'doesnotexist' } ), + 'Nonexistent user returns undef'; + } 'No exception thrown for nonexistent user'; + } is_deeply(\@searches, [ ['base', 'ou=foobar', 'filter', '(&(objectClass=inetOrgPerson)(uid=somebody))', 'scope', 'one'], ['base', 'ou=roles', 'filter', '(&(objectClass=posixGroup)(memberUid=test))', 'scope', 'one', 'attrs', [ 'userinrole' ]], + ['base', 'ou=foobar', 'filter', '(&(objectClass=inetOrgPerson)(uid=doesnotexist))', 'scope', 'one'], ['base', 'ou=foobar', 'filter', '(&(objectClass=inetOrgPerson)(uid=somebody))', 'scope', 'one'], ['base', 'ou=roles', 'filter', '(&(objectClass=posixGroup)(memberUid=test))', 'scope', 'one', 'attrs', [ 'userinrole' ]], + ['base', 'ou=foobar', 'filter', '(&(objectClass=inetOrgPerson)(uid=doesnotexist))', 'scope', 'one'], ], 'User searches as expected'); is_deeply(\@binds, [ [ undef ], # First user search @@ -90,12 +101,14 @@ [ undef ], # Rebind with initial credentials to find roles + [ undef ], # Second user search # 2nd pass round main loop [ undef ], # First user search [ 'ou=foobar', 'password', 'password' - ] # Rebind to confirm user _and_ lookup roles; + ], # Rebind to confirm user _and_ lookup roles; + [ undef ], # Second user search ], 'Binds as expected'); }
<cough> You may also want to update the number of tests skipped in 10-roles-mock.t, which I forgot in that patch.
thanks. 0.1005 just uploaded.