release 0.1004
[catagits/Catalyst-Authentication-Store-LDAP.git] / t / 10-roles-mock.t
diff --git a/t/10-roles-mock.t b/t/10-roles-mock.t
new file mode 100644 (file)
index 0000000..d79a533
--- /dev/null
@@ -0,0 +1,101 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Catalyst::Exception;
+
+use Test::More tests => 7;
+use Test::MockObject::Extends;
+use Net::LDAP::Entry;
+use lib 't/lib';
+
+SKIP: {
+
+    eval "use Catalyst::Model::LDAP";
+    if ($@) {
+        skip "Catalyst::Model::LDAP not installed", 7;
+    }
+
+    use_ok("Catalyst::Authentication::Store::LDAP::Backend");
+
+    my (@searches, @binds);
+    for my $i (0..1) {
+
+        my $back = Catalyst::Authentication::Store::LDAP::Backend->new({
+            'ldap_server' => 'ldap://127.0.0.1:555',
+            'binddn'      => 'anonymous',
+            'bindpw'      => 'dontcarehow',
+            'start_tls'   => 0,
+            'user_basedn' => 'ou=foobar',
+            'user_filter' => '(&(objectClass=inetOrgPerson)(uid=%s))',
+            'user_scope'  => 'one',
+            'user_field'  => 'uid',
+            'use_roles'   => 1,
+            'role_basedn' => 'ou=roles',
+            'role_filter' => '(&(objectClass=posixGroup)(memberUid=%s))',
+            'role_scope'  => 'one',
+            'role_field'  => 'userinrole',
+            'role_value'  => 'cn',
+            'role_search_as_user' => $i,
+        });
+        $back = Test::MockObject::Extends->new($back);
+        my $bind_msg = Test::MockObject->new;
+        $bind_msg->mock(is_error => sub {}); # Cause bind call to always succeed
+        my $ldap = Test::MockObject->new;
+        $ldap->mock('bind', sub { shift; push (@binds, [@_]); return $bind_msg});
+        $ldap->mock('unbind' => sub {});
+        $ldap->mock('disconnect' => sub {});
+        my $search_res = Test::MockObject->new();
+        $search_res->mock(is_error => sub {}); # Never an error
+        $search_res->mock(entries => sub {
+            return map 
+                {   my $id = $_; 
+                    Test::MockObject->new->mock(
+                        get_value => sub { "quux$id" }
+                    ) 
+                }
+                qw/one two/
+        });
+        my @user_entries;
+        $search_res->mock(pop_entry => sub { return pop @user_entries });
+        $ldap->mock('search', sub { shift; push(@searches, [@_]); return $search_res; });
+        $back->mock('ldap_connect' => sub { $ldap });
+        my $user_entry = Net::LDAP::Entry->new;
+        push(@user_entries, $user_entry);
+        $user_entry->dn('ou=foobar');
+        $user_entry->add(
+            uid => 'somebody',
+            cn => 'test',
+        );
+        my $user = $back->find_user( { username => 'somebody' } );
+        isa_ok( $user, "Catalyst::Authentication::Store::LDAP::User" );
+        $user->check_password('password');
+        is_deeply( [sort $user->roles], 
+                   [sort qw/quuxone quuxtwo/], 
+                    "User has the expected set of roles" );
+    }
+    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=somebody))', 'scope', 'one'],
+        ['base', 'ou=roles', 'filter', '(&(objectClass=posixGroup)(memberUid=test))', 'scope', 'one', 'attrs', [ 'userinrole' ]],
+    ], 'User searches as expected');
+    is_deeply(\@binds, [
+        [ undef ], # First user search
+        [
+            'ou=foobar',
+            'password',
+            'password'
+        ], # Rebind to confirm user
+        [
+            undef
+        ], # Rebind with initial credentials to find roles
+        # 2nd pass round main loop
+        [  undef ], # First user search
+        [
+            'ou=foobar',
+            'password',
+            'password'
+        ] # Rebind to confirm user _and_ lookup roles;
+    ], 'Binds as expected');
+}