@@ -43,22 +43,22 @@ protected function setUp(): void
4343 $ this ->mockUser = User::factory ()->make ();
4444 }
4545
46- protected function runFailedAuthLogin ()
46+ protected function runFailedAuthLogin (): void
4747 {
4848 $ this ->commonLdapMocks (1 , 1 , 1 , 1 , 1 );
4949 $ this ->mockLdap ->shouldReceive ('searchAndGetEntries ' )->times (1 )
5050 ->andReturn (['count ' => 0 ]);
5151 $ this ->post ('/login ' , ['username ' => 'timmyjenkins ' , 'password ' => 'cattreedog ' ]);
5252 }
5353
54- protected function mockEscapes ($ times = 1 )
54+ protected function mockEscapes ($ times = 1 ): void
5555 {
5656 $ this ->mockLdap ->shouldReceive ('escape ' )->times ($ times )->andReturnUsing (function ($ val ) {
5757 return ldap_escape ($ val );
5858 });
5959 }
6060
61- protected function mockExplodes ($ times = 1 )
61+ protected function mockExplodes ($ times = 1 ): void
6262 {
6363 $ this ->mockLdap ->shouldReceive ('explodeDn ' )->times ($ times )->andReturnUsing (function ($ dn , $ withAttrib ) {
6464 return ldap_explode_dn ($ dn , $ withAttrib );
@@ -76,7 +76,7 @@ protected function mockUserLogin(?string $email = null): TestResponse
7676 /**
7777 * Set LDAP method mocks for things we commonly call without altering.
7878 */
79- protected function commonLdapMocks (int $ connects = 1 , int $ versions = 1 , int $ options = 2 , int $ binds = 4 , int $ escapes = 2 , int $ explodes = 0 , int $ groups = 0 )
79+ protected function commonLdapMocks (int $ connects = 1 , int $ versions = 1 , int $ options = 2 , int $ binds = 4 , int $ escapes = 2 , int $ explodes = 0 , int $ groups = 0 ): void
8080 {
8181 $ this ->mockLdap ->shouldReceive ('connect ' )->times ($ connects )->andReturn ($ this ->resourceId );
8282 $ this ->mockLdap ->shouldReceive ('setVersion ' )->times ($ versions );
@@ -364,7 +364,7 @@ public function test_login_maps_roles_and_retains_existing_roles()
364364 'services.ldap.remove_from_groups ' => false ,
365365 ]);
366366
367- $ this ->commonLdapMocks (1 , 1 , 4 , 5 , 2 , 2 , 2 );
367+ $ this ->commonLdapMocks (1 , 1 , 4 , 5 , 2 , 4 , 2 );
368368 $ this ->mockLdap ->shouldReceive ('searchAndGetEntries ' )->times (2 )
369369 ->with ($ this ->resourceId , config ('services.ldap.base_dn ' ), \Mockery::type ('string ' ), \Mockery::type ('array ' ))
370370 ->andReturn (['count ' => 1 , 0 => [
@@ -409,7 +409,7 @@ public function test_login_maps_roles_and_removes_old_roles_if_set()
409409 'services.ldap.remove_from_groups ' => true ,
410410 ]);
411411
412- $ this ->commonLdapMocks (1 , 1 , 3 , 4 , 2 , 1 , 1 );
412+ $ this ->commonLdapMocks (1 , 1 , 3 , 4 , 2 , 2 , 1 );
413413 $ this ->mockLdap ->shouldReceive ('searchAndGetEntries ' )->times (2 )
414414 ->with ($ this ->resourceId , config ('services.ldap.base_dn ' ), \Mockery::type ('string ' ), \Mockery::type ('array ' ))
415415 ->andReturn (['count ' => 1 , 0 => [
@@ -451,7 +451,7 @@ public function test_dump_user_groups_shows_group_related_details_as_json()
451451 'dn ' => 'dc=test, ' . config ('services.ldap.base_dn ' ),
452452 'mail ' => [$ this ->mockUser ->email ],
453453 ]];
454- $ this ->commonLdapMocks (1 , 1 , 4 , 5 , 2 , 2 , 0 );
454+ $ this ->commonLdapMocks (1 , 1 , 4 , 5 , 2 , 4 , 0 );
455455 $ this ->mockLdap ->shouldReceive ('searchAndGetEntries ' )->times (2 )
456456 ->with ($ this ->resourceId , config ('services.ldap.base_dn ' ), \Mockery::type ('string ' ), \Mockery::type ('array ' ))
457457 ->andReturn ($ userResp , ['count ' => 1 ,
@@ -523,7 +523,7 @@ public function test_recursive_group_search_queries_via_full_dn()
523523 ],
524524 ];
525525
526- $ this ->commonLdapMocks (1 , 1 , 3 , 4 , 2 , 1 );
526+ $ this ->commonLdapMocks (1 , 1 , 3 , 4 , 2 , 2 );
527527
528528 $ escapedName = ldap_escape ($ this ->mockUser ->name );
529529 $ this ->mockLdap ->shouldReceive ('searchAndGetEntries ' )->twice ()
@@ -559,7 +559,7 @@ public function test_login_maps_roles_using_external_auth_ids_if_set()
559559 'services.ldap.remove_from_groups ' => true ,
560560 ]);
561561
562- $ this ->commonLdapMocks (1 , 1 , 3 , 4 , 2 , 1 , 1 );
562+ $ this ->commonLdapMocks (1 , 1 , 3 , 4 , 2 , 2 , 1 );
563563 $ this ->mockLdap ->shouldReceive ('searchAndGetEntries ' )->times (2 )
564564 ->with ($ this ->resourceId , config ('services.ldap.base_dn ' ), \Mockery::type ('string ' ), \Mockery::type ('array ' ))
565565 ->andReturn (['count ' => 1 , 0 => [
@@ -600,7 +600,7 @@ public function test_login_group_mapping_does_not_conflict_with_default_role()
600600 'services.ldap.remove_from_groups ' => true ,
601601 ]);
602602
603- $ this ->commonLdapMocks (1 , 1 , 4 , 5 , 2 , 2 , 2 );
603+ $ this ->commonLdapMocks (1 , 1 , 4 , 5 , 2 , 4 , 2 );
604604 $ this ->mockLdap ->shouldReceive ('searchAndGetEntries ' )->times (2 )
605605 ->with ($ this ->resourceId , config ('services.ldap.base_dn ' ), \Mockery::type ('string ' ), \Mockery::type ('array ' ))
606606 ->andReturn (['count ' => 1 , 0 => [
@@ -628,6 +628,44 @@ public function test_login_group_mapping_does_not_conflict_with_default_role()
628628 ]);
629629 }
630630
631+ public function test_login_group_mapping_gracefully_handles_utf8_and_invalid_group_dns ()
632+ {
633+ $ invalidRole = Role::factory ()->create (['display_name ' => 'LdapTester ' ]);
634+ $ invalidRole2 = Role::factory ()->create (['display_name ' => 'beans ' ]);
635+ $ roleToReceive2 = Role::factory ()->create (['display_name ' => 'ldapper ' ]);
636+ $ this ->mockUser ->forceFill (['external_auth_id ' => $ this ->mockUser ->name ])->save ();
637+
638+ app ('config ' )->set ([
639+ 'services.ldap.user_to_groups ' => true ,
640+ 'services.ldap.group_attribute ' => 'memberOf ' ,
641+ 'services.ldap.remove_from_groups ' => true ,
642+ ]);
643+
644+ $ this ->commonLdapMocks (1 , 1 , 4 , 5 , 2 , 6 , 2 );
645+ $ this ->mockLdap ->shouldReceive ('searchAndGetEntries ' )->times (2 )
646+ ->with ($ this ->resourceId , config ('services.ldap.base_dn ' ), \Mockery::type ('string ' ), \Mockery::type ('array ' ))
647+ ->andReturn (['count ' => 1 , 0 => [
648+ 'uid ' => [$ this ->mockUser ->name ],
649+ 'cn ' => [$ this ->mockUser ->name ],
650+ 'dn ' => 'dc=test ' . config ('services.ldap.base_dn ' ),
651+ 'mail ' => [$ this ->mockUser ->email ],
652+ 'memberof ' => [
653+ 'count ' => 4 ,
654+ 0 => 'cn=ldaptëstër,ou=groups,dc=ëxamplë,dc=com ' ,
655+ 1 => 'cn=ldapper,ou=groups,dc=example,dc=com ' ,
656+ 2 => 'bëans ' ,
657+ 3 => '' ,
658+ ],
659+ ]]);
660+
661+ $ this ->mockUserLogin ()->assertRedirect ('/ ' );
662+
663+ $ user = User::query ()->where ('email ' , $ this ->mockUser ->email )->first ();
664+ $ this ->assertDatabaseMissing ('role_user ' , ['user_id ' => $ user ->id , 'role_id ' => $ invalidRole ->id ]);
665+ $ this ->assertDatabaseMissing ('role_user ' , ['user_id ' => $ user ->id , 'role_id ' => $ invalidRole2 ->id ]);
666+ $ this ->assertDatabaseHas ('role_user ' , ['user_id ' => $ user ->id , 'role_id ' => $ roleToReceive2 ->id ]);
667+ }
668+
631669 public function test_login_uses_specified_display_name_attribute ()
632670 {
633671 app ('config ' )->set ([
@@ -867,7 +905,7 @@ public function test_login_with_email_confirmation_required_maps_groups_but_show
867905 'services.ldap.remove_from_groups ' => true ,
868906 ]);
869907
870- $ this ->commonLdapMocks (1 , 1 , 6 , 8 , 4 , 2 , 2 );
908+ $ this ->commonLdapMocks (1 , 1 , 6 , 8 , 4 , 4 , 2 );
871909 $ this ->mockLdap ->shouldReceive ('searchAndGetEntries ' )
872910 ->times (4 )
873911 ->andReturn (['count ' => 1 , 0 => [
0 commit comments