fix use_roles enabled if explicitly disabled
[catagits/Catalyst-Authentication-Store-LDAP.git] / t / 10-roles-mock.t
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use Catalyst::Exception;
6
7 use Test::More;
8 use Test::MockObject::Extends;
9 use Test::Exception;
10 use Net::LDAP::Entry;
11 use lib 't/lib';
12
13 eval "use Catalyst::Model::LDAP";
14 plan skip_all => "Catalyst::Model::LDAP not installed" if $@;
15
16 use_ok("Catalyst::Authentication::Store::LDAP::Backend");
17
18
19 my $back_without_use_roles = Catalyst::Authentication::Store::LDAP::Backend->new({
20     ldap_server => 'ldap://127.0.0.1:555',
21     binddn      => 'anonymous',
22     bindpw      => 'dontcarehow',
23     user_basedn => 'ou=foobar',
24     user_filter => '(&(objectClass=inetOrgPerson)(uid=%s))',
25     user_scope  => 'one',
26     user_field  => 'uid',
27 });
28 is $back_without_use_roles->use_roles, 1, 'use_roles enabled be default';
29
30 my $back_with_use_roles_disabled = Catalyst::Authentication::Store::LDAP::Backend->new({
31     ldap_server => 'ldap://127.0.0.1:555',
32     binddn      => 'anonymous',
33     bindpw      => 'dontcarehow',
34     user_basedn => 'ou=foobar',
35     user_filter => '(&(objectClass=inetOrgPerson)(uid=%s))',
36     user_scope  => 'one',
37     user_field  => 'uid',
38     use_roles   => 0,
39 });
40 is $back_with_use_roles_disabled->use_roles, 0, 'use_roles disabled when set
41 to 0';
42
43 my $back_with_use_roles_enabled = Catalyst::Authentication::Store::LDAP::Backend->new({
44     ldap_server => 'ldap://127.0.0.1:555',
45     binddn      => 'anonymous',
46     bindpw      => 'dontcarehow',
47     user_basedn => 'ou=foobar',
48     user_filter => '(&(objectClass=inetOrgPerson)(uid=%s))',
49     user_scope  => 'one',
50     user_field  => 'uid',
51     use_roles   => 1,
52 });
53 is $back_with_use_roles_enabled->use_roles, 1, 'use_roles enabled when set to
54 1';
55
56 my (@searches, @binds);
57 for my $i (0..1) {
58
59     my $back = Catalyst::Authentication::Store::LDAP::Backend->new({
60         'ldap_server' => 'ldap://127.0.0.1:555',
61         'binddn'      => 'anonymous',
62         'bindpw'      => 'dontcarehow',
63         'start_tls'   => 0,
64         'user_basedn' => 'ou=foobar',
65         'user_filter' => '(&(objectClass=inetOrgPerson)(uid=%s))',
66         'user_scope'  => 'one',
67         'user_field'  => 'uid',
68         'use_roles'   => 1,
69         'role_basedn' => 'ou=roles',
70         'role_filter' => '(&(objectClass=posixGroup)(memberUid=%s))',
71         'role_scope'  => 'one',
72         'role_field'  => 'userinrole',
73         'role_value'  => 'cn',
74         'role_search_as_user' => $i,
75     });
76     $back = Test::MockObject::Extends->new($back);
77     my $bind_msg = Test::MockObject->new;
78     $bind_msg->mock(is_error => sub {}); # Cause bind call to always succeed
79     my $ldap = Test::MockObject->new;
80     $ldap->mock('bind', sub { shift; push (@binds, [@_]); return $bind_msg});
81     $ldap->mock('unbind' => sub {});
82     $ldap->mock('disconnect' => sub {});
83     my $search_res = Test::MockObject->new();
84     my $search_is_error = 0;
85     $search_res->mock(is_error => sub { $search_is_error });
86     $search_res->mock(entries => sub {
87         return map 
88             {   my $id = $_; 
89                 Test::MockObject->new->mock(
90                     get_value => sub { "quux$id" }
91                 ) 
92             }
93             qw/one two/
94     });
95     my @user_entries;
96     $search_res->mock(pop_entry => sub { return pop @user_entries });
97     $ldap->mock('search', sub { shift; push(@searches, [@_]); return $search_res; });
98     $back->mock('ldap_connect' => sub { $ldap });
99     my $user_entry = Net::LDAP::Entry->new;
100     push(@user_entries, $user_entry);
101     $user_entry->dn('ou=foobar');
102     $user_entry->add(
103         uid => 'somebody',
104         cn => 'test',
105     );
106     my $user = $back->find_user( { username => 'somebody' } );
107     isa_ok( $user, "Catalyst::Authentication::Store::LDAP::User" );
108     $user->check_password('password');
109     is_deeply( [sort $user->roles], 
110                [sort qw/quuxone quuxtwo/], 
111                 "User has the expected set of roles" );
112
113     $search_is_error = 1;
114     lives_ok {
115         ok !$back->find_user( { username => 'doesnotexist' } ),
116             'Nonexistent user returns undef';
117     } 'No exception thrown for nonexistent user';
118
119 }
120 is_deeply(\@searches, [ 
121     ['base', 'ou=foobar', 'filter', '(&(objectClass=inetOrgPerson)(uid=somebody))', 'scope', 'one'],
122     ['base', 'ou=roles', 'filter', '(&(objectClass=posixGroup)(memberUid=test))', 'scope', 'one', 'attrs', [ 'userinrole' ]],
123     ['base', 'ou=foobar', 'filter', '(&(objectClass=inetOrgPerson)(uid=doesnotexist))', 'scope', 'one'],
124     ['base', 'ou=foobar', 'filter', '(&(objectClass=inetOrgPerson)(uid=somebody))', 'scope', 'one'],
125     ['base', 'ou=roles', 'filter', '(&(objectClass=posixGroup)(memberUid=test))', 'scope', 'one', 'attrs', [ 'userinrole' ]],
126     ['base', 'ou=foobar', 'filter', '(&(objectClass=inetOrgPerson)(uid=doesnotexist))', 'scope', 'one'],
127 ], 'User searches as expected');
128 is_deeply(\@binds, [
129     [ undef ], # First user search
130     [
131         'ou=foobar',
132         'password',
133         'password'
134     ], # Rebind to confirm user
135     [
136         undef
137     ], # Rebind with initial credentials to find roles
138     [ undef ], # Second user search
139     # 2nd pass round main loop
140     [  undef ], # First user search
141     [
142         'ou=foobar',
143         'password',
144         'password'
145     ], # Rebind to confirm user
146     [
147         'ou=foobar',
148         'password',
149         'password'
150     ], # Rebind with user credentials to find roles
151     [ undef ], # Second user search
152 ], 'Binds as expected');
153
154 done_testing;