LDAP authentication support (#815)
This commit is contained in:
50
tests/Ldap/FormLoginLdapFactoryTest.php
Normal file
50
tests/Ldap/FormLoginLdapFactoryTest.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Ldap;
|
||||
|
||||
use App\Ldap\FormLoginLdapFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* @covers \App\Ldap\FormLoginLdapFactory
|
||||
*/
|
||||
class FormLoginLdapFactoryTest extends TestCase
|
||||
{
|
||||
public function testStaticValues()
|
||||
{
|
||||
$sut = new FormLoginLdapFactory();
|
||||
self::assertEquals('kimai_ldap', $sut->getKey());
|
||||
self::assertEquals('pre_auth', $sut->getPosition());
|
||||
}
|
||||
|
||||
public function testCreate()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$sut = new FormLoginLdapFactory();
|
||||
$result = $sut->create($container, 'test', ['foo' => 'bar'], 'fosuserbundle', 'secured_area');
|
||||
|
||||
self::assertEquals([
|
||||
'kimai_ldap.security.authentication.provider.test',
|
||||
'security.authentication.listener.form.test',
|
||||
'secured_area'
|
||||
], $result);
|
||||
|
||||
$definition = $container->getDefinition('kimai_ldap.security.authentication.provider.test');
|
||||
self::assertInstanceOf(ChildDefinition::class, $definition);
|
||||
self::assertEquals('test', $definition->getArguments()['index_1']);
|
||||
|
||||
$definition = $container->getDefinition('security.authentication.listener.form.test');
|
||||
self::assertInstanceOf(ChildDefinition::class, $definition);
|
||||
self::assertEquals('test', $definition->getArguments()['index_4']);
|
||||
self::assertEquals(['foo' => 'bar'], $definition->getArguments()['index_5']);
|
||||
}
|
||||
}
|
||||
238
tests/Ldap/LdapAuthenticationProviderTest.php
Normal file
238
tests/Ldap/LdapAuthenticationProviderTest.php
Normal file
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Ldap;
|
||||
|
||||
use App\Configuration\LdapConfiguration;
|
||||
use App\Entity\User;
|
||||
use App\Ldap\LdapAuthenticationProvider;
|
||||
use App\Ldap\LdapManager;
|
||||
use App\Ldap\LdapUserProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\UserChecker;
|
||||
|
||||
/**
|
||||
* @covers \App\Ldap\LdapAuthenticationProvider
|
||||
*/
|
||||
class LdapAuthenticationProviderTest extends TestCase
|
||||
{
|
||||
public function testDeactivatedSupports()
|
||||
{
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration(['active' => false]);
|
||||
$userProvider = new LdapUserProvider($manager, $config);
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$token = new UsernamePasswordToken('foo', 'bar', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$result = $sut->supports($token);
|
||||
self::assertFalse($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
|
||||
* @expectedExceptionMessage The token is not supported by this authentication provider.
|
||||
*/
|
||||
public function testDeactivatedAuthenticate()
|
||||
{
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration(['active' => false]);
|
||||
$userProvider = new LdapUserProvider($manager, $config);
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$token = new UsernamePasswordToken('foo', 'bar', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$sut->authenticate($token);
|
||||
}
|
||||
|
||||
public function testSupports()
|
||||
{
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
$userProvider = new LdapUserProvider($manager, $config);
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$token = new UsernamePasswordToken('foo', 'bar', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$result = $sut->supports($token);
|
||||
self::assertTrue($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||
* @expectedExceptionMessage The password in the token is empty. Check `erase_credentials` in your `security.yaml`
|
||||
*/
|
||||
public function testAuthenticateWithTokenUserButEnptyPasswordThrowsException()
|
||||
{
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
$userProvider = new LdapUserProvider($manager, $config);
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$user = (new User())->setUsername('foo')->setEnabled(true);
|
||||
$token = new UsernamePasswordToken($user, '', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$actual = $sut->authenticate($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||
* @expectedExceptionMessage The presented password cannot be empty.
|
||||
*/
|
||||
public function testAuthenticateWithUsernameReturnsUser()
|
||||
{
|
||||
$user = (new User())->setUsername('foo')->setEnabled(true);
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->setMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->once())->method('loadUserByUsername')->willReturn($user);
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$token = new UsernamePasswordToken('foo', '', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$actual = $sut->authenticate($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||
* @expectedExceptionMessage The presented password is invalid.
|
||||
*/
|
||||
public function testAuthenticateWithUsernameThrowsExceptionOnFailedBind()
|
||||
{
|
||||
$user = (new User())->setUsername('foo')->setEnabled(true);
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->setMethods(['bind'])->getMock();
|
||||
$manager->expects($this->once())->method('bind')->willReturn(false);
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->setMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->once())->method('loadUserByUsername')->willReturn($user);
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$token = new UsernamePasswordToken('foo', 'sdfsdf', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$actual = $sut->authenticate($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||
* @expectedExceptionMessage The credentials were changed from another session.
|
||||
*/
|
||||
public function testAuthenticateWithUserThrowsExceptionOnFailedBind()
|
||||
{
|
||||
$user = (new User())->setUsername('foo')->setEnabled(true);
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->setMethods(['bind'])->getMock();
|
||||
$manager->expects($this->once())->method('bind')->willReturn(false);
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->setMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->never())->method('loadUserByUsername');
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$token = new UsernamePasswordToken($user, 'sdfsdf', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$actual = $sut->authenticate($token);
|
||||
}
|
||||
|
||||
public function testAuthenticateWithUsernameReturnsUserAndBinds()
|
||||
{
|
||||
$user = (new User())->setUsername('foo')->setEnabled(true);
|
||||
$user->setPreferenceValue('ldap.dn', 'blub');
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->setMethods(['bind', 'updateUser'])->getMock();
|
||||
$manager->expects($this->once())->method('bind')->willReturn(true);
|
||||
$manager->expects($this->once())->method('updateUser')->willReturnCallback(function ($updateUser) use ($user) {
|
||||
self::assertSame($updateUser, $user);
|
||||
});
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->setMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->once())->method('loadUserByUsername')->willReturn($user);
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$token = new UsernamePasswordToken('foo', 'test', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$token = $sut->authenticate($token);
|
||||
self::assertSame($token->getUser(), $user);
|
||||
}
|
||||
|
||||
public function testAuthenticateWithUserReturnsUserAndBinds()
|
||||
{
|
||||
$user = (new User())->setUsername('foo')->setEnabled(true);
|
||||
$user->setPreferenceValue('ldap.dn', 'blub');
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->setMethods(['bind', 'updateUser'])->getMock();
|
||||
$manager->expects($this->once())->method('bind')->willReturn(true);
|
||||
$manager->expects($this->once())->method('updateUser')->willReturnCallback(function ($updateUser) use ($user) {
|
||||
self::assertSame($updateUser, $user);
|
||||
});
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->setMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->never())->method('loadUserByUsername');
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$token = new UsernamePasswordToken($user, 'test', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$token = $sut->authenticate($token);
|
||||
self::assertSame($token->getUser(), $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
|
||||
* @expectedExceptionMessage blub foo bar
|
||||
*/
|
||||
public function testAuthenticateThrowsExceptionOnLdapNotFound()
|
||||
{
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->setMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->once())->method('loadUserByUsername')->willThrowException(new UsernameNotFoundException('blub foo bar'));
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$token = new UsernamePasswordToken('foo', 'test', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$sut->authenticate($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException
|
||||
* @expectedExceptionMessage server away
|
||||
* @expectedExceptionCode 1234
|
||||
*/
|
||||
public function testAuthenticateThrowsExceptionOnLdapDown()
|
||||
{
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->setMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->once())->method('loadUserByUsername')->willThrowException(new \Exception('server away', 1234));
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
|
||||
$token = new UsernamePasswordToken('foo', 'test', $providerKey);
|
||||
|
||||
$sut = new LdapAuthenticationProvider($userChecker, $providerKey, $userProvider, $manager, $config, false);
|
||||
$sut->authenticate($token);
|
||||
}
|
||||
}
|
||||
28
tests/Ldap/LdapDriverExceptionTest.php
Normal file
28
tests/Ldap/LdapDriverExceptionTest.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Ldap;
|
||||
|
||||
use App\Ldap\LdapDriverException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Ldap\LdapDriverException
|
||||
*/
|
||||
class LdapDriverExceptionTest extends TestCase
|
||||
{
|
||||
public function testConstruct()
|
||||
{
|
||||
$sut = new LdapDriverException('Whooops');
|
||||
|
||||
self::assertInstanceOf(\Exception::class, $sut);
|
||||
|
||||
self::assertEquals('Whooops', $sut->getMessage());
|
||||
}
|
||||
}
|
||||
71
tests/Ldap/LdapDriverTest.php
Normal file
71
tests/Ldap/LdapDriverTest.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Ldap;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Ldap\LdapDriver;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Zend\Ldap\Exception\LdapException;
|
||||
use Zend\Ldap\Ldap;
|
||||
|
||||
/**
|
||||
* @covers \App\Ldap\LdapDriver
|
||||
*/
|
||||
class LdapDriverTest extends TestCase
|
||||
{
|
||||
public function testBindSuccess()
|
||||
{
|
||||
$zendLdap = $this->getMockBuilder(Ldap::class)->disableOriginalConstructor()->setMethods(['bind'])->getMock();
|
||||
$zendLdap->expects($this->once())->method('bind')->willReturnSelf();
|
||||
|
||||
$user = new User();
|
||||
$sut = new LdapDriver($zendLdap);
|
||||
$result = $sut->bind($user, 'test123');
|
||||
self::assertTrue($result);
|
||||
}
|
||||
|
||||
public function testBindException()
|
||||
{
|
||||
$zendLdap = $this->getMockBuilder(Ldap::class)->disableOriginalConstructor()->setMethods(['bind'])->getMock();
|
||||
$zendLdap->expects($this->once())->method('bind')->willThrowException(new LdapException());
|
||||
|
||||
$user = new User();
|
||||
$sut = new LdapDriver($zendLdap);
|
||||
$result = $sut->bind($user, 'test123');
|
||||
self::assertFalse($result);
|
||||
}
|
||||
|
||||
public function testSearchSuccess()
|
||||
{
|
||||
$zendLdap = $this->getMockBuilder(Ldap::class)->disableOriginalConstructor()->setMethods(['bind', 'searchEntries'])->getMock();
|
||||
$zendLdap->expects($this->once())->method('bind');
|
||||
$zendLdap->expects($this->once())->method('searchEntries')->willReturn([1, 2, 3]);
|
||||
|
||||
$sut = new LdapDriver($zendLdap);
|
||||
$result = $sut->search('', '', []);
|
||||
self::assertEquals(['count' => 3, 1, 2, 3], $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \App\Ldap\LdapDriverException
|
||||
* @expectedExceptionMessage An error occurred with the search operation.
|
||||
*/
|
||||
public function testSearchException()
|
||||
{
|
||||
$zendLdap = $this->getMockBuilder(Ldap::class)->disableOriginalConstructor()->setMethods(['bind', 'searchEntries'])->getMock();
|
||||
$zendLdap->expects($this->once())->method('bind');
|
||||
$zendLdap->expects($this->once())->method('searchEntries')->willThrowException(
|
||||
new LdapException($zendLdap, '', LdapException::LDAP_SERVER_DOWN)
|
||||
);
|
||||
|
||||
$sut = new LdapDriver($zendLdap);
|
||||
$sut->search('', '', []);
|
||||
}
|
||||
}
|
||||
454
tests/Ldap/LdapManagerTest.php
Normal file
454
tests/Ldap/LdapManagerTest.php
Normal file
@@ -0,0 +1,454 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Ldap;
|
||||
|
||||
use App\Configuration\LdapConfiguration;
|
||||
use App\Entity\User;
|
||||
use App\Ldap\LdapDriver;
|
||||
use App\Ldap\LdapManager;
|
||||
use App\Ldap\LdapUserHydrator;
|
||||
use App\Security\RoleService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Ldap\LdapManager
|
||||
*/
|
||||
class LdapManagerTest extends TestCase
|
||||
{
|
||||
protected function getLdapManager(LdapDriver $driver, $roleConfig = null)
|
||||
{
|
||||
if (null === $roleConfig) {
|
||||
$roleConfig = [
|
||||
'baseDn' => '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'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$config = new LdapConfiguration([
|
||||
'user' => [
|
||||
'attributes' => [],
|
||||
'filter' => '(&(objectClass=inetOrgPerson))',
|
||||
'usernameAttribute' => 'uid',
|
||||
'baseDn' => 'ou=users, dc=kimai, dc=org',
|
||||
],
|
||||
'role' => $roleConfig,
|
||||
]);
|
||||
|
||||
$hydrator = new LdapUserHydrator($config, new RoleService([
|
||||
'ROLE_TEAMLEAD' => ['ROLE_USER'],
|
||||
'ROLE_ADMIN' => ['ROLE_TEAMLEAD'],
|
||||
'ROLE_SUPER_ADMIN' => ['ROLE_ADMIN']
|
||||
]));
|
||||
|
||||
return new LdapManager($driver, $hydrator, $config);
|
||||
}
|
||||
|
||||
public function testFindUserByUsernameOnZeroResults()
|
||||
{
|
||||
$expected = [
|
||||
'count' => 0
|
||||
];
|
||||
|
||||
$driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->setMethods(['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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \App\Ldap\LdapDriverException
|
||||
* @expectedExceptionMessage This search must only return a single user
|
||||
*/
|
||||
public function testFindUserByUsernameOnMultiResults()
|
||||
{
|
||||
$expected = [
|
||||
'count' => 3
|
||||
];
|
||||
|
||||
$driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->setMethods(['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()
|
||||
{
|
||||
$expected = [
|
||||
0 => ['dn' => 'foo'],
|
||||
'count' => 1,
|
||||
];
|
||||
|
||||
$driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->setMethods(['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()
|
||||
{
|
||||
$expected = [
|
||||
'count' => 0
|
||||
];
|
||||
|
||||
$driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->setMethods(['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->findUserBy(['uid' => 'foo']);
|
||||
self::assertNull($actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \App\Ldap\LdapDriverException
|
||||
* @expectedExceptionMessage This search must only return a single user
|
||||
*/
|
||||
public function testFindUserByOnMultiResults()
|
||||
{
|
||||
$expected = [
|
||||
'count' => 3
|
||||
];
|
||||
|
||||
$driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->setMethods(['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->findUserBy(['uid' => 'foo']);
|
||||
}
|
||||
|
||||
public function testFindUserByOnValidResult()
|
||||
{
|
||||
$expected = [
|
||||
0 => ['dn' => 'foo'],
|
||||
'count' => 1,
|
||||
];
|
||||
|
||||
$driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->setMethods(['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))(träl=alß#\\\aa=XY\5cZ0)(test=fu=n))', $filter);
|
||||
|
||||
return $expected;
|
||||
});
|
||||
|
||||
$sut = $this->getLdapManager($driver);
|
||||
$actual = $sut->findUserBy(['träl=alß#\\\aa' => 'XY\Z0', 'test' => 'fu=n']);
|
||||
self::assertInstanceOf(User::class, $actual);
|
||||
}
|
||||
|
||||
public function testBind()
|
||||
{
|
||||
$user = (new User())->setUsername('foobar');
|
||||
|
||||
$driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->setMethods(['bind'])->getMock();
|
||||
$driver->expects($this->once())->method('bind')->willReturnCallback(function ($bindUser, $password) use ($user) {
|
||||
self::assertSame($user, $bindUser);
|
||||
self::assertEquals('a-very-secret-secret', $password);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
$sut = $this->getLdapManager($driver);
|
||||
$actual = $sut->bind($user, 'a-very-secret-secret');
|
||||
self::assertTrue($actual);
|
||||
}
|
||||
|
||||
public function testUpdateUserOnZeroResults()
|
||||
{
|
||||
$user = (new User())->setUsername('foobar');
|
||||
$user->setPreferenceValue('ldap.dn', 'fooooooooooo');
|
||||
$expected = [
|
||||
[
|
||||
0 => ['dn' => 'blub'],
|
||||
'count' => 1,
|
||||
],
|
||||
[
|
||||
'count' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
$driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->setMethods(['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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \App\Ldap\LdapDriverException
|
||||
* @expectedExceptionMessage This search must only return a single user
|
||||
*/
|
||||
public function testUpdateUserOnMultiResults()
|
||||
{
|
||||
$user = (new User())->setUsername('foobar');
|
||||
$user->setPreferenceValue('ldap.dn', 'xxxxxxx');
|
||||
|
||||
$expected = [
|
||||
[
|
||||
0 => ['dn' => 'blub'],
|
||||
'count' => 1,
|
||||
],
|
||||
[
|
||||
'count' => 3,
|
||||
],
|
||||
];
|
||||
|
||||
$driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->setMethods(['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()
|
||||
{
|
||||
$user = (new User())->setUsername('foobar');
|
||||
$user->setPreferenceValue('ldap.dn', 'sssssss');
|
||||
|
||||
$expected = [
|
||||
[
|
||||
0 => ['dn' => 'blub'],
|
||||
'count' => 1,
|
||||
],
|
||||
[
|
||||
0 => ['dn' => 'blub-updated'],
|
||||
'count' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
$driver = $this->getMockBuilder(LdapDriver::class)->disableOriginalConstructor()->setMethods(['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'), $user);
|
||||
self::assertEquals($user->getPreferenceValue('ldap.dn'), 'blub-updated');
|
||||
}
|
||||
|
||||
public 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' => ['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' => '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=dfsdfsdf))'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getValidConfigsTestData
|
||||
*/
|
||||
public function testUpdateUserOnValidResultWithRolesResult(array $expectedUsers, array $groupConfig, string $expectedGroupQuery)
|
||||
{
|
||||
$expected = [
|
||||
0 => ['dn' => '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()->setMethods(['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())->setUsername('Karl-Heinz');
|
||||
$user->setPreferenceValue('ldap.dn', 'blub');
|
||||
$userOrig = clone $user;
|
||||
$userOrig->setEmail('Karl-Heinz')->setRoles(['ROLE_TEAMLEAD', 'ROLE_ADMIN']);
|
||||
|
||||
$sut->updateUser($user);
|
||||
self::assertEquals($userOrig, $user);
|
||||
self::assertEquals(['ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_USER'], $user->getRoles());
|
||||
}
|
||||
}
|
||||
189
tests/Ldap/LdapUserHydratorTest.php
Normal file
189
tests/Ldap/LdapUserHydratorTest.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Ldap;
|
||||
|
||||
use App\Configuration\LdapConfiguration;
|
||||
use App\Entity\User;
|
||||
use App\Ldap\LdapUserHydrator;
|
||||
use App\Security\RoleService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Ldap\LdapUserHydrator
|
||||
*/
|
||||
class LdapUserHydratorTest extends TestCase
|
||||
{
|
||||
public function testEmptyHydrate()
|
||||
{
|
||||
$config = new LdapConfiguration([
|
||||
'active' => false,
|
||||
'connection' => [
|
||||
'host' => '1.1.1.1'
|
||||
],
|
||||
'user' => [
|
||||
'usernameAttribute' => 'foo',
|
||||
'attributes' => []
|
||||
],
|
||||
'role' => [],
|
||||
]);
|
||||
|
||||
$sut = new LdapUserHydrator($config, new RoleService([]));
|
||||
$user = $sut->hydrate(['dn' => 'blub']);
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
self::assertEmpty($user->getUsername());
|
||||
self::assertEmpty($user->getEmail());
|
||||
}
|
||||
|
||||
public function testHydrate()
|
||||
{
|
||||
$config = new LdapConfiguration([
|
||||
'active' => false,
|
||||
'connection' => [
|
||||
'host' => '1.1.1.1'
|
||||
],
|
||||
'user' => [
|
||||
'usernameAttribute' => 'foo',
|
||||
'attributes' => [
|
||||
['ldap_attr' => 'uid', 'user_method' => 'setUsername'],
|
||||
['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' => [],
|
||||
]);
|
||||
|
||||
$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 LdapUserHydrator($config, new RoleService([]));
|
||||
$user = $sut->hydrate($ldapEntry);
|
||||
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
self::assertEquals('Karl-Heinz', $user->getUsername());
|
||||
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()
|
||||
{
|
||||
$config = new LdapConfiguration([
|
||||
'active' => false,
|
||||
'connection' => [
|
||||
'host' => '1.1.1.1'
|
||||
],
|
||||
'user' => [
|
||||
'usernameAttribute' => 'foo',
|
||||
'attributes' => [
|
||||
['ldap_attr' => 'uid', 'user_method' => 'setUsername'],
|
||||
['ldap_attr' => 'foo', 'user_method' => 'setAlias'],
|
||||
['ldap_attr' => 'bar', 'user_method' => 'setTitle'],
|
||||
['ldap_attr' => 'xxxxxxxx', 'user_method' => 'setAvatar'],
|
||||
]
|
||||
],
|
||||
'role' => [],
|
||||
]);
|
||||
|
||||
$ldapEntry = [
|
||||
'uid' => ['Karl-Heinz'],
|
||||
'blub' => ['dfsdfsdf'],
|
||||
'foo' => ['bar'],
|
||||
'bar' => ['foo'],
|
||||
'xxxxxxxx' => ['https://www.example.com'],
|
||||
'blub1' => ['dfsdfsdf'],
|
||||
'dn' => 'blub',
|
||||
];
|
||||
|
||||
$sut = new LdapUserHydrator($config, new RoleService([]));
|
||||
$user = new User();
|
||||
$user->setPassword('foobar');
|
||||
$sut->hydrateUser($user, $ldapEntry);
|
||||
self::assertEquals('Karl-Heinz', $user->getUsername());
|
||||
self::assertEquals('bar', $user->getAlias());
|
||||
self::assertEquals('foo', $user->getTitle());
|
||||
self::assertEquals('https://www.example.com', $user->getAvatar());
|
||||
self::assertEquals('Karl-Heinz', $user->getEmail());
|
||||
|
||||
// make sure that the password was resetted in hydrate
|
||||
$pwdCheck = clone $user;
|
||||
$pwdCheck->setPassword('');
|
||||
self::assertEquals($pwdCheck, $user);
|
||||
}
|
||||
|
||||
public function testHydrateRoles()
|
||||
{
|
||||
$config = new LdapConfiguration([
|
||||
'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'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$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
|
||||
];
|
||||
|
||||
$sut = new LdapUserHydrator($config, new RoleService([
|
||||
'ROLE_TEAMLEAD' => ['ROLE_USER'],
|
||||
'ROLE_ADMIN' => ['ROLE_TEAMLEAD'],
|
||||
'ROLE_SUPER_ADMIN' => ['ROLE_ADMIN']
|
||||
]));
|
||||
$user = new User();
|
||||
$sut->hydrateRoles($user, $ldapGroups);
|
||||
self::assertEquals(['ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_USER'], $user->getRoles());
|
||||
}
|
||||
}
|
||||
102
tests/Ldap/LdapUserProviderTest.php
Normal file
102
tests/Ldap/LdapUserProviderTest.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Ldap;
|
||||
|
||||
use App\Configuration\LdapConfiguration;
|
||||
use App\Entity\User;
|
||||
use App\Ldap\LdapManager;
|
||||
use App\Ldap\LdapUserProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Ldap\LdapUserProvider
|
||||
*/
|
||||
class LdapUserProviderTest extends TestCase
|
||||
{
|
||||
public function testDeactivatedSupportsClass()
|
||||
{
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration(['active' => false]);
|
||||
|
||||
$sut = new LdapUserProvider($manager, $config);
|
||||
self::assertFalse($sut->supportsClass(User::class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
|
||||
* @expectedExceptionMessage LDAP is deactivated, user "test" not searched
|
||||
*/
|
||||
public function testDeactivatedLoadUserByUsername()
|
||||
{
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration(['active' => false]);
|
||||
|
||||
$sut = new LdapUserProvider($manager, $config);
|
||||
$sut->loadUserByUsername('test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\UnsupportedUserException
|
||||
* @expectedExceptionMessage Instances of "App\Entity\User" are not supported.
|
||||
*/
|
||||
public function testDeactivatedRefreshUser()
|
||||
{
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration(['active' => false]);
|
||||
|
||||
$sut = new LdapUserProvider($manager, $config);
|
||||
$sut->refreshUser(new User());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
|
||||
* @expectedExceptionMessage User "test" not found
|
||||
*/
|
||||
public function testLoadUserByUsernameReturnsNull()
|
||||
{
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->setMethods(['findUserByUsername'])->getMock();
|
||||
$manager->expects($this->once())->method('findUserByUsername')->willReturn(null);
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
|
||||
$sut = new LdapUserProvider($manager, $config);
|
||||
$sut->loadUserByUsername('test');
|
||||
}
|
||||
|
||||
public function testLoadUserByUsernameReturnsUser()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setUsername('foobar');
|
||||
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->setMethods(['findUserByUsername'])->getMock();
|
||||
$manager->expects($this->once())->method('findUserByUsername')->willReturn($user);
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
|
||||
$sut = new LdapUserProvider($manager, $config);
|
||||
$actual = $sut->loadUserByUsername('test');
|
||||
self::assertInstanceOf(User::class, $actual);
|
||||
self::assertSame($user, $actual);
|
||||
}
|
||||
|
||||
public function testRefreshUserReturnsUser()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setUsername('foobar');
|
||||
$user->setPreferenceValue('ldap.dn', 'sdfdsf');
|
||||
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->setMethods(['updateUser'])->getMock();
|
||||
$config = new LdapConfiguration(['active' => true]);
|
||||
|
||||
$sut = new LdapUserProvider($manager, $config);
|
||||
$actual = $sut->refreshUser($user);
|
||||
|
||||
self::assertInstanceOf(User::class, $actual);
|
||||
self::assertSame($user, $actual);
|
||||
}
|
||||
}
|
||||
31
tests/Ldap/SanitizingExceptionTest.php
Normal file
31
tests/Ldap/SanitizingExceptionTest.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Ldap;
|
||||
|
||||
use App\Ldap\SanitizingException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Ldap\SanitizingException
|
||||
*/
|
||||
class SanitizingExceptionTest extends TestCase
|
||||
{
|
||||
public function testMessagesAreSanitized()
|
||||
{
|
||||
$ex = new \Exception('Could not find user foo with password bar in your LDAP');
|
||||
$sut = new SanitizingException($ex, 'bar');
|
||||
|
||||
self::assertInstanceOf(\Exception::class, $sut);
|
||||
|
||||
self::assertNotContains('bar', $sut->getMessage());
|
||||
self::assertNotContains('bar', (string) $sut);
|
||||
self::assertEquals('Could not find user foo with password **** in your LDAP', $sut->getMessage());
|
||||
}
|
||||
}
|
||||
48
tests/Ldap/ZendLdapTest.php
Normal file
48
tests/Ldap/ZendLdapTest.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Ldap;
|
||||
|
||||
use App\Configuration\LdapConfiguration;
|
||||
use App\Ldap\ZendLdap;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Ldap\ZendLdap
|
||||
*/
|
||||
class ZendLdapTest extends TestCase
|
||||
{
|
||||
public function testConstructDeactivated()
|
||||
{
|
||||
$config = new LdapConfiguration([
|
||||
'active' => false,
|
||||
'connection' => [
|
||||
'host' => '1.1.1.1'
|
||||
]
|
||||
]);
|
||||
|
||||
$sut = new ZendLdap($config);
|
||||
$options = $sut->getOptions();
|
||||
self::assertNull($options['host']);
|
||||
}
|
||||
|
||||
public function testConstructActivatedPassesOptions()
|
||||
{
|
||||
$config = new LdapConfiguration([
|
||||
'active' => true,
|
||||
'connection' => [
|
||||
'host' => '1.1.1.1'
|
||||
]
|
||||
]);
|
||||
|
||||
$sut = new ZendLdap($config);
|
||||
$options = $sut->getOptions();
|
||||
self::assertEquals('1.1.1.1', $options['host']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user