'ou=groups, dc=kimai, dc=org', 'nameAttribute' => 'cn', 'userDnAttribute' => 'member', 'groups' => [ ['ldap_value' => 'group1', 'role' => 'ROLE_TEAMLEAD'], ['ldap_value' => 'group2', 'role' => 'ROLE_ADMIN'], ['ldap_value' => 'group3', 'role' => 'ROLE_CUSTOMER'], // not existing! ['ldap_value' => 'group4', 'role' => 'ROLE_SUPER_ADMIN'], ], ]; } $conf = [ 'user' => [ 'attributes' => [], 'filter' => '(&(objectClass=inetOrgPerson))', 'usernameAttribute' => 'uid', 'attributesFilter' => '(objectClass=*)', 'baseDn' => 'ou=users, dc=kimai, dc=org', ], 'role' => $roleConfig, ]; $systemConfig = SystemConfigurationFactory::create(new TestConfigLoader([]), ['ldap' => $conf]); $config = new LdapConfiguration($systemConfig); $roles = [ 'ROLE_USER', 'ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_SUPER_ADMIN', ]; return new LdapManager($driver, $config, (new RoleServiceFactory($this))->create($roles)); } public function testFindUserByUsernameOnZeroResults(): void { $expected = [ 'count' => 0 ]; $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['search'])->getMock(); $driver->expects($this->once())->method('search')->willReturnCallback(function ($baseDn, $filter) use ($expected) { self::assertEquals('ou=users, dc=kimai, dc=org', $baseDn); self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=foo))', $filter); return $expected; }); $sut = $this->getLdapManager($driver); $actual = $sut->findUserByUsername('foo'); self::assertNull($actual); } public function testFindUserByUsernameOnMultiResults(): void { $this->expectException(LdapDriverException::class); $this->expectExceptionMessage('This search must only return a single user'); $expected = [ 'count' => 3 ]; $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['search'])->getMock(); $driver->expects($this->once())->method('search')->willReturnCallback(function ($baseDn, $filter) use ($expected) { self::assertEquals('ou=users, dc=kimai, dc=org', $baseDn); self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=foo))', $filter); return $expected; }); $sut = $this->getLdapManager($driver); $sut->findUserByUsername('foo'); } public function testFindUserByUsernameOnValidResult(): void { $expected = [ 0 => ['dn' => 'foo', 'uid' => ['foo']], 'count' => 1, ]; $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['search'])->getMock(); $driver->expects($this->once())->method('search')->willReturnCallback(function ($baseDn, $filter) use ($expected) { self::assertEquals('ou=users, dc=kimai, dc=org', $baseDn); self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=foo))', $filter); return $expected; }); $sut = $this->getLdapManager($driver); $actual = $sut->findUserByUsername('foo'); self::assertInstanceOf(User::class, $actual); } public function testFindUserByOnZeroResults(): void { $expected = [ 'count' => 0 ]; $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['search'])->getMock(); $driver->expects($this->once())->method('search')->willReturnCallback(function ($baseDn, $filter) use ($expected) { self::assertEquals('ou=users, dc=kimai, dc=org', $baseDn); self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=foo))', $filter); return $expected; }); $sut = $this->getLdapManager($driver); $actual = $sut->findUserByUsername('foo'); self::assertNull($actual); } public function testFindUserByOnMultiResults(): void { $this->expectException(LdapDriverException::class); $this->expectExceptionMessage('This search must only return a single user'); $expected = [ 'count' => 3 ]; $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['search'])->getMock(); $driver->expects($this->once())->method('search')->willReturnCallback(function ($baseDn, $filter) use ($expected) { self::assertEquals('ou=users, dc=kimai, dc=org', $baseDn); self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=foo))', $filter); return $expected; }); $sut = $this->getLdapManager($driver); $sut->findUserByUsername('foo'); } public function testFindUserByOnValidResult(): void { $expected = [ 0 => ['dn' => 'foo', 'uid' => ['foo']], 'count' => 1, ]; $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['search'])->getMock(); $driver->expects($this->once())->method('search')->willReturnCallback(function ($baseDn, $filter) use ($expected) { self::assertEquals('ou=users, dc=kimai, dc=org', $baseDn); self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=trä\5cl=alß#aa=XY\5cZ0))', $filter); return $expected; }); $sut = $this->getLdapManager($driver); $actual = $sut->findUserByUsername('trä\l=alß#aa=XY\Z0'); self::assertInstanceOf(User::class, $actual); } public function testBind(): void { $user = new User(); $user->setUserIdentifier('foobar'); $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['bind'])->getMock(); $driver->expects($this->once())->method('bind')->willReturnCallback(function ($bindUser, $password) { self::assertEquals('foobar', $bindUser); self::assertEquals('a-very-secret-secret', $password); return true; }); $sut = $this->getLdapManager($driver); $actual = $sut->bind($user->getUserIdentifier(), 'a-very-secret-secret'); self::assertTrue($actual); } public function testUpdateUserOnZeroResults(): void { $user = new User(); $user->setUserIdentifier('foobar'); $user->setPreferenceValue('ldap_dn', 'fooooooooooo'); $expected = [ [ 0 => ['dn' => 'blub', 'uid' => ['blub']], 'count' => 1, ], [ 'count' => 0, ], ]; $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['search'])->getMock(); $driver->expects($this->exactly(2))->method('search')->willReturnCallback(function ($baseDn, $filter) use ($expected) { if ($baseDn === 'ou=users, dc=kimai, dc=org') { self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=foobar))', $filter); return $expected[0]; } elseif ($baseDn === 'blub') { self::assertEquals('(objectClass=*)', $filter); return $expected[1]; } $this->fail(\sprintf('Unexpected search with baseDn %s', $baseDn)); }); $sut = $this->getLdapManager($driver); $userOrig = clone $user; $sut->updateUser($user); self::assertEquals($userOrig, $user); } public function testUpdateUserOnMultiResults(): void { $this->expectException(LdapDriverException::class); $this->expectExceptionMessage('This search must only return a single user'); $user = new User(); $user->setUserIdentifier('foobar'); $user->setPreferenceValue('ldap_dn', 'xxxxxxx'); $expected = [ [ 0 => ['dn' => 'blub', 'uid' => ['blub']], 'count' => 1, ], [ 'count' => 3, ], ]; $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['search'])->getMock(); $driver->expects($this->exactly(2))->method('search')->willReturnCallback(function ($baseDn, $filter) use ($expected) { if ($baseDn === 'ou=users, dc=kimai, dc=org') { self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=foobar))', $filter); return $expected[0]; } elseif ($baseDn === 'blub') { self::assertEquals('(objectClass=*)', $filter); return $expected[1]; } $this->fail(\sprintf('Unexpected search with baseDn %s', $baseDn)); }); $sut = $this->getLdapManager($driver); $sut->updateUser($user); } public function testUpdateUserOnValidResultWithEmptyRoleBaseDn(): void { $user = new User(); $user->setUserIdentifier('foobar'); $user->setPreferenceValue('ldap_dn', 'sssssss'); $expected = [ [ 0 => ['dn' => 'blub', 'uid' => ['blub']], 'count' => 1, ], [ 0 => ['dn' => 'blub-updated', 'uid' => ['foobar']], 'count' => 1, ], ]; $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['search'])->getMock(); $driver->expects($this->exactly(2))->method('search')->willReturnCallback(function ($baseDn, $filter) use ($expected) { if ($baseDn === 'ou=users, dc=kimai, dc=org') { self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=foobar))', $filter); return $expected[0]; } elseif ($baseDn === 'blub') { self::assertEquals('(objectClass=*)', $filter); return $expected[1]; } $this->fail(\sprintf('Unexpected search with baseDn %s', $baseDn)); }); $sut = $this->getLdapManager($driver, [ 'baseDn' => null, 'nameAttribute' => 'cn', 'userDnAttribute' => 'member', 'groups' => [ ['ldap_value' => 'group1', 'role' => 'ROLE_TEAMLEAD'], ['ldap_value' => 'group2', 'role' => 'ROLE_ADMIN'], ['ldap_value' => 'group3', 'role' => 'ROLE_CUSTOMER'], // not existing! ['ldap_value' => 'group4', 'role' => 'ROLE_SUPER_ADMIN'], ], ]); $userOrig = clone $user; $sut->updateUser($user); self::assertEquals($userOrig->setEmail('foobar')->setAuth(User::AUTH_LDAP), $user); self::assertEquals($user->getPreferenceValue('ldap_dn'), 'blub-updated'); } public static function getValidConfigsTestData() { return [ [ [ 0 => [ 'dn' => 'blub', 'uid' => ['Karl-Heinz'], // just some rubbish data 'blub' => ['dfsdfsdf'], 'foo' => ['count' => 1, 'bar'], 'bar' => ['count' => 1, 'foo', 'xxx'], 'xxxxxxxx' => ['https://www.example.com'], 'blub1' => ['dfsdfsdf'], ], 'count' => 1, ], [ 'baseDn' => 'ou=groups, dc=kimai, dc=org', 'nameAttribute' => 'cn', 'usernameAttribute' => 'cn', // test that "cn" is not set and fallback to "dn" happens 'userDnAttribute' => 'member', 'groups' => [ ['ldap_value' => 'group1', 'role' => 'ROLE_TEAMLEAD'], ['ldap_value' => 'group2', 'role' => 'ROLE_ADMIN'], ['ldap_value' => 'group3', 'role' => 'ROLE_CUSTOMER'], // not existing! ['ldap_value' => 'group4', 'role' => 'ROLE_SUPER_ADMIN'], ], ], '(&(member=blub))' ], [ [ 0 => [ 'dn' => 'blub', 'uid' => ['Karl-Heinz'], // just some rubbish data 'blub' => ['foo'], 'foo' => ['count' => 1, 'bar'], 'bar' => ['count' => 1, 'foo', 'xxx'], 'xxxxxxxx' => ['https://www.example.com'], 'blub1' => ['foo(bar)'], ], 'count' => 1, ], [ 'baseDn' => 'ou=groups, dc=kimai, dc=org', 'nameAttribute' => 'cn', 'usernameAttribute' => 'blub1', 'userDnAttribute' => 'memberuid', 'groups' => [ ['ldap_value' => 'group1', 'role' => 'ROLE_TEAMLEAD'], ['ldap_value' => 'group2', 'role' => 'ROLE_ADMIN'], ['ldap_value' => 'group3', 'role' => 'ROLE_CUSTOMER'], // not existing! ['ldap_value' => 'group4', 'role' => 'ROLE_SUPER_ADMIN'], ], ], '(&(memberuid=foo\28bar\29))' ], ]; } #[DataProvider('getValidConfigsTestData')] public function testUpdateUserOnValidResultWithRolesResult(array $expectedUsers, array $groupConfig, string $expectedGroupQuery): void { $expected = [ 0 => ['dn' => 'blub', 'uid' => ['blub']], 'count' => 1, ]; $expectedGroups = [ // ROLE_TEAMLEAD 0 => [ 'cn' => [0 => 'group1'], 'member' => [0 => 'uid=user1,ou=users,dc=kimai,dc=org', 1 => 'uid=user2,ou=users,dc=kimai,dc=org'], ], // ROLE_ADMIN 1 => [ 'cn' => [0 => 'admin'], 'member' => [0 => 'uid=user2,ou=users,dc=kimai,dc=org', 1 => 'uid=user3,ou=users,dc=kimai,dc=org'], ], // will be ignored: unknown group 2 => [ 'cn' => [0 => 'kimai_admin'], 'member' => [0 => 'uid=user2,ou=users,dc=kimai,dc=org', 1 => 'uid=user3,ou=users,dc=kimai,dc=org'], ], // will be ignored: unknown group 3 => [ 'cn' => [0 => 'group3'], 'member' => [0 => 'uid=user2,ou=users,dc=kimai,dc=org', 1 => 'uid=user3,ou=users,dc=kimai,dc=org'], ], // will be ignored: the counter below does not announce this group! 4 => [ 'cn' => [0 => 'group4'], 'member' => [0 => 'uid=user2,ou=users,dc=kimai,dc=org', 1 => 'uid=user3,ou=users,dc=kimai,dc=org'], ], 'count' => 4 ]; $driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->onlyMethods(['search'])->getMock(); $driver->expects($this->exactly(3))->method('search')->willReturnCallback(function ($baseDn, $filter, $attributes) use ($expectedUsers, $expectedGroups, $expectedGroupQuery, $expected) { if ($baseDn === 'ou=users, dc=kimai, dc=org') { self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=Karl-Heinz))', $filter); return $expected; } elseif ($baseDn === 'blub') { // user attributes search self::assertEquals('(objectClass=*)', $filter); return $expectedUsers; } elseif ($baseDn === 'ou=groups, dc=kimai, dc=org') { // roles search self::assertEquals($expectedGroupQuery, $filter); self::assertEquals([0 => 'cn'], $attributes); return $expectedGroups; } $this->fail(\sprintf('Unexpected search with baseDn %s', $baseDn)); }); $sut = $this->getLdapManager($driver, $groupConfig); $user = new User(); $user->setUserIdentifier('Karl-Heinz'); $user->setPreferenceValue('ldap_dn', 'blub'); $userOrig = clone $user; $userOrig->setEmail('Karl-Heinz')->setRoles(['ROLE_TEAMLEAD', 'ROLE_ADMIN'])->setAuth(User::AUTH_LDAP); $sut->updateUser($user); self::assertEquals($userOrig, $user); self::assertEquals(['ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_USER'], $user->getRoles()); } public function testEmptyHydrate(): void { $ldapConfig = [ 'activate' => true, 'connection' => [ 'host' => '1.1.1.1' ], 'user' => [ 'usernameAttribute' => 'foo', 'attributes' => [] ], 'role' => [], ]; $systemConfig = SystemConfigurationFactory::create(new TestConfigLoader([]), ['ldap' => $ldapConfig]); $config = new LdapConfiguration($systemConfig); $sut = new LdapManager($this->createMock(LdapDriver::class), $config, (new RoleServiceFactory($this))->create([])); $user = $sut->hydrate(['dn' => 'blub', 'foo' => ['blub']]); self::assertInstanceOf(User::class, $user); self::assertEquals('blub', $user->getUserIdentifier()); self::assertEquals('blub', $user->getUserIdentifier()); self::assertEquals('blub', $user->getEmail()); } public function testEmptyHydrateThrowsException(): void { $this->expectException(LdapDriverException::class); $this->expectExceptionMessage('Missing username in LDAP hydration'); $ldapConfig = [ 'activate' => true, 'connection' => [ 'host' => '1.1.1.1' ], 'user' => [ 'usernameAttribute' => 'foo', 'attributes' => [] ], 'role' => [], ]; $systemConfig = SystemConfigurationFactory::create(new TestConfigLoader([]), ['ldap' => $ldapConfig]); $config = new LdapConfiguration($systemConfig); $sut = new LdapManager($this->createMock(LdapDriver::class), $config, (new RoleServiceFactory($this))->create([])); $user = $sut->hydrate(['dn' => 'blub']); self::assertInstanceOf(User::class, $user); } public function testHydrate(): void { $ldapConfig = [ 'connection' => [ 'host' => '1.1.1.1' ], 'user' => [ 'usernameAttribute' => 'foo', 'attributes' => [ ['ldap_attr' => 'uid', 'user_method' => 'setUserIdentifier'], ['ldap_attr' => 'foo', 'user_method' => 'setAlias'], ['ldap_attr' => 'bar', 'user_method' => 'setTitle'], ['ldap_attr' => 'roles', 'user_method' => 'setRoles'], ['ldap_attr' => 'xxxxxxxx', 'user_method' => 'setAvatar'], ['ldap_attr' => 'blubXX', 'user_method' => 'setAvatar'], ] ], 'role' => [], ]; $systemConfig = SystemConfigurationFactory::create(new TestConfigLoader([]), ['ldap' => $ldapConfig]); $config = new LdapConfiguration($systemConfig); $ldapEntry = [ 'uid' => ['Karl-Heinz'], 'blub' => ['dfsdfsdf'], 'foo' => ['count' => 1, 0 => 'bar'], 'bar' => ['foo'], 'roles' => ['count' => 2, 0 => 'ROLE_TEAMLEAD', 1 => 'ROLE_ADMIN'], 'xxxxxxxx' => ['https://www.example.com'], 'blub1' => ['dfsdfsdf'], 'dn' => 'blub', ]; $sut = new LdapManager($this->createMock(LdapDriver::class), $config, (new RoleServiceFactory($this))->create([])); $user = $sut->hydrate($ldapEntry); self::assertInstanceOf(User::class, $user); self::assertEquals('Karl-Heinz', $user->getUserIdentifier()); self::assertEquals('bar', $user->getAlias()); self::assertEquals('foo', $user->getTitle()); self::assertEquals(['ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_USER'], $user->getRoles()); self::assertEquals('https://www.example.com', $user->getAvatar()); self::assertEquals('Karl-Heinz', $user->getEmail()); } public function testThrowsOnMissingMethod(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Unknown mapping method: setAlias2'); $ldapConfig = [ 'connection' => [ 'host' => '1.1.1.1' ], 'user' => [ 'usernameAttribute' => 'foo', 'attributes' => [ ['ldap_attr' => 'foo', 'user_method' => 'setAlias2'], ] ], 'role' => [], ]; $systemConfig = SystemConfigurationFactory::create(new TestConfigLoader([]), ['ldap' => $ldapConfig]); $config = new LdapConfiguration($systemConfig); $ldapEntry = [ 'foo' => ['count' => 1, 0 => 'bar'], ]; $sut = new LdapManager($this->createMock(LdapDriver::class), $config, (new RoleServiceFactory($this))->create([])); $user = $sut->hydrate($ldapEntry); } #[Group('legacy')] public function testHydrateWithDepercatedSetter(): void { $ldapConfig = [ 'connection' => [ 'host' => '1.1.1.1' ], 'user' => [ 'usernameAttribute' => 'foo', 'attributes' => [ ['ldap_attr' => 'uid', 'user_method' => 'setUsername'], // use setUsername here for BC reasons! ['ldap_attr' => 'foo', 'user_method' => 'setAlias'], ['ldap_attr' => 'bar', 'user_method' => 'setTitle'], ['ldap_attr' => 'roles', 'user_method' => 'setRoles'], ['ldap_attr' => 'xxxxxxxx', 'user_method' => 'setAvatar'], ['ldap_attr' => 'blubXX', 'user_method' => 'setAvatar'], ] ], 'role' => [], ]; $systemConfig = SystemConfigurationFactory::create(new TestConfigLoader([]), ['ldap' => $ldapConfig]); $config = new LdapConfiguration($systemConfig); $ldapEntry = [ 'uid' => ['Karl-Heinz'], 'blub' => ['dfsdfsdf'], 'foo' => ['count' => 1, 0 => 'bar'], 'bar' => ['foo'], 'roles' => ['count' => 2, 0 => 'ROLE_TEAMLEAD', 1 => 'ROLE_ADMIN'], 'xxxxxxxx' => ['https://www.example.com'], 'blub1' => ['dfsdfsdf'], 'dn' => 'blub', ]; $sut = new LdapManager($this->createMock(LdapDriver::class), $config, (new RoleServiceFactory($this))->create([])); $user = $sut->hydrate($ldapEntry); self::assertInstanceOf(User::class, $user); self::assertEquals('Karl-Heinz', $user->getUserIdentifier()); self::assertEquals('bar', $user->getAlias()); self::assertEquals('foo', $user->getTitle()); self::assertEquals(['ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_USER'], $user->getRoles()); self::assertEquals('https://www.example.com', $user->getAvatar()); self::assertEquals('Karl-Heinz', $user->getEmail()); } public function testHydrateUser(): void { $ldapConfig = [ 'connection' => [ 'host' => '1.1.1.1' ], 'user' => [ 'usernameAttribute' => 'foo', 'attributes' => [ ['ldap_attr' => 'uid', 'user_method' => 'setUserIdentifier'], ['ldap_attr' => 'email', 'user_method' => 'setEmail'], ['ldap_attr' => 'foo', 'user_method' => 'setAlias'], ['ldap_attr' => 'bar', 'user_method' => 'setTitle'], ['ldap_attr' => 'xxxxxxxx', 'user_method' => 'setAvatar'], ] ], 'role' => [], ]; $systemConfig = SystemConfigurationFactory::create(new TestConfigLoader([]), ['ldap' => $ldapConfig]); $config = new LdapConfiguration($systemConfig); $ldapEntry = [ 'uid' => ['Karl-Heinz'], 'email' => [['karl-heinz@example.com', 'foo@example.com', 'bar@example.com']], 'blub' => ['dfsdfsdf'], 'foo' => ['bar'], 'bar' => ['foo'], 'xxxxxxxx' => ['https://www.example.com'], 'blub1' => ['dfsdfsdf'], 'dn' => 'blub', ]; $sut = new LdapManager($this->createMock(LdapDriver::class), $config, (new RoleServiceFactory($this))->create([])); $user = new User(); $user->setPassword('foobar'); $sut->hydrateUser($user, $ldapEntry); self::assertEquals('Karl-Heinz', $user->getUserIdentifier()); self::assertEquals('bar', $user->getAlias()); self::assertEquals('foo', $user->getTitle()); self::assertEquals('https://www.example.com', $user->getAvatar()); self::assertEquals('karl-heinz@example.com', $user->getEmail()); // make sure that the password was resetted in hydrate $pwdCheck = clone $user; $pwdCheck->setPassword(''); self::assertEquals($pwdCheck, $user); } public function testHydrateRoles(): void { $ldapConfig = [ 'user' => [ 'attributes' => [] ], 'role' => [ 'nameAttribute' => 'cn', 'userDnAttribute' => 'member', 'groups' => [ ['ldap_value' => 'group1', 'role' => 'ROLE_TEAMLEAD'], ['ldap_value' => 'group2', 'role' => 'ROLE_ADMIN'], ['ldap_value' => 'group3', 'role' => 'ROLE_CUSTOMER'], // not existing! ['ldap_value' => 'group4', 'role' => 'ROLE_SUPER_ADMIN'], ], ], ]; $systemConfig = SystemConfigurationFactory::create(new TestConfigLoader([]), ['ldap' => $ldapConfig]); $config = new LdapConfiguration($systemConfig); $ldapGroups = [ // ROLE_TEAMLEAD 0 => [ 'cn' => [0 => 'group1'], 'member' => [0 => 'uid=user1,ou=users,dc=kimai,dc=org', 1 => 'uid=user2,ou=users,dc=kimai,dc=org'], ], // ROLE_ADMIN 1 => [ 'cn' => [0 => 'admin'], 'member' => [0 => 'uid=user2,ou=users,dc=kimai,dc=org', 1 => 'uid=user3,ou=users,dc=kimai,dc=org'], ], // will be ignored: unknown group 2 => [ 'cn' => [0 => 'kimai_admin'], 'member' => [0 => 'uid=user2,ou=users,dc=kimai,dc=org', 1 => 'uid=user3,ou=users,dc=kimai,dc=org'], ], // will be ignored: unknown group 3 => [ 'cn' => [0 => 'group3'], 'member' => [0 => 'uid=user2,ou=users,dc=kimai,dc=org', 1 => 'uid=user3,ou=users,dc=kimai,dc=org'], ], // will be ignored: the counter below does not announce this group! 4 => [ 'cn' => [0 => 'group4'], 'member' => [0 => 'uid=user2,ou=users,dc=kimai,dc=org', 1 => 'uid=user3,ou=users,dc=kimai,dc=org'], ], 'count' => 4 ]; $roles = [ 'ROLE_USER', 'ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_SUPER_ADMIN', ]; $sut = new LdapManager($this->createMock(LdapDriver::class), $config, (new RoleServiceFactory($this))->create($roles)); $user = new User(); $sut->hydrateRoles($user, $ldapGroups); self::assertEquals(['ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_USER'], $user->getRoles()); } }