Next major version 2 with PHP 8.1, Symfony 6, Tabler UI, 2FA ... (#2902)

This commit is contained in:
Kevin Papst
2022-12-31 21:19:55 +01:00
committed by GitHub
parent 95e06746bd
commit 90a0fd8a22
2164 changed files with 83700 additions and 86426 deletions

View File

@@ -11,40 +11,17 @@ 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()
public function testConstruct(): void
{
$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([
'security.authentication.provider.kimai_ldap.test',
'security.authentication.listener.form.test',
'secured_area'
], $result);
$definition = $container->getDefinition('security.authentication.provider.kimai_ldap.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']);
self::assertEquals(-20, $sut->getPriority());
}
}

View File

@@ -1,238 +0,0 @@
<?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\Configuration\SystemConfiguration;
use App\Entity\User;
use App\Ldap\LdapAuthenticationProvider;
use App\Ldap\LdapManager;
use App\Ldap\LdapUserProvider;
use App\Tests\Configuration\TestConfigLoader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserChecker;
use Symfony\Component\Security\Core\User\UserProviderInterface;
/**
* @covers \App\Ldap\LdapAuthenticationProvider
*/
class LdapAuthenticationProviderTest extends TestCase
{
public const USER_PROVIDER_CLASS = LdapUserProvider::class;
private function getUserProvider(?User $user = null): UserProviderInterface
{
if ($user === null) {
return new LdapUserProvider($this->createMock(LdapManager::class));
}
$userProvider = $this->getMockBuilder(self::USER_PROVIDER_CLASS)->disableOriginalConstructor()->onlyMethods(['loadUserByUsername'])->getMock();
$userProvider->expects($this->once())->method('loadUserByUsername')->willReturn($user);
return $userProvider;
}
private function getConfiguration(bool $active = true): LdapConfiguration
{
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['ldap' => ['activate' => $active]]);
$config = new LdapConfiguration($systemConfig);
return $config;
}
public function testSupports()
{
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
$config = $this->getConfiguration(false);
$userProvider = $this->getUserProvider();
$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);
}
public function testSupportsActive()
{
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
$config = $this->getConfiguration(true);
$userProvider = $this->getUserProvider();
$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);
}
public function testAuthenticateWithTokenUserButEmptyPasswordThrowsException()
{
$this->expectException(BadCredentialsException::class);
$this->expectExceptionMessage('The password in the token is empty. Check `erase_credentials` in your `security.yaml`');
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
$config = $this->getConfiguration(true);
$userProvider = $this->getUserProvider();
$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);
}
public function testAuthenticateWithUsernameReturnsUser()
{
$this->expectException(BadCredentialsException::class);
$this->expectExceptionMessage('The presented password cannot be empty.');
$user = (new User())->setUsername('foo')->setEnabled(true);
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
$config = $this->getConfiguration(true);
$userProvider = $this->getUserProvider($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);
}
public function testAuthenticateWithUsernameThrowsExceptionOnFailedBind()
{
$this->expectException(BadCredentialsException::class);
$this->expectExceptionMessage('The presented password is invalid.');
$user = (new User())->setUsername('foo')->setEnabled(true);
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->onlyMethods(['bind'])->getMock();
$manager->expects($this->once())->method('bind')->willReturn(false);
$config = $this->getConfiguration(true);
$userProvider = $this->getUserProvider($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);
}
public function testAuthenticateWithUserThrowsExceptionOnFailedBind()
{
$this->expectException(BadCredentialsException::class);
$this->expectExceptionMessage('The credentials were changed from another session.');
$user = (new User())->setUsername('foo')->setEnabled(true);
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->onlyMethods(['bind'])->getMock();
$manager->expects($this->once())->method('bind')->willReturn(false);
$config = $this->getConfiguration(true);
$userProvider = $this->getMockBuilder(self::USER_PROVIDER_CLASS)->disableOriginalConstructor()->onlyMethods(['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()->onlyMethods(['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 = $this->getConfiguration(true);
$userProvider = $this->getUserProvider($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()->onlyMethods(['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 = $this->getConfiguration(true);
$userProvider = $this->getMockBuilder(self::USER_PROVIDER_CLASS)->disableOriginalConstructor()->onlyMethods(['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);
}
public function testAuthenticateThrowsExceptionOnLdapNotFound()
{
$this->expectException(UsernameNotFoundException::class);
$this->expectExceptionMessage('blub foo bar');
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
$config = $this->getConfiguration(true);
$userProvider = $this->getMockBuilder(self::USER_PROVIDER_CLASS)->disableOriginalConstructor()->onlyMethods(['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);
}
public function testAuthenticateThrowsExceptionOnLdapDown()
{
$this->expectException(AuthenticationServiceException::class);
$this->expectExceptionMessage('server away');
$this->expectExceptionCode('1234');
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
$config = $this->getConfiguration(true);
$userProvider = $this->getMockBuilder(self::USER_PROVIDER_CLASS)->disableOriginalConstructor()->onlyMethods(['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);
}
}

View File

@@ -9,8 +9,10 @@
namespace App\Tests\Ldap;
use App\Configuration\LdapConfiguration;
use App\Entity\User;
use App\Ldap\LdapDriver;
use App\Tests\Mocks\SystemConfigurationFactory;
use Laminas\Ldap\Exception\LdapException;
use Laminas\Ldap\Ldap;
use PHPUnit\Framework\TestCase;
@@ -28,14 +30,26 @@ class LdapDriverTest extends TestCase
}
}
private function getTestLdapDriver(Ldap $ldap): TestLdapDriver
{
$config = SystemConfigurationFactory::createStub(['ldap' => [
'role' => [],
'user' => [],
'connection' => [],
]]);
return new TestLdapDriver(new LdapConfiguration($config), $ldap);
}
public function testBindSuccess()
{
$zendLdap = $this->getMockBuilder(Ldap::class)->disableOriginalConstructor()->onlyMethods(['bind'])->getMock();
$zendLdap->expects($this->once())->method('bind')->willReturnSelf();
$user = new User();
$sut = new TestLdapDriver($zendLdap);
$result = $sut->bind($user, 'test123');
$user->setUserIdentifier('foo');
$sut = $this->getTestLdapDriver($zendLdap);
$result = $sut->bind($user->getUserIdentifier(), 'test123');
self::assertTrue($result);
}
@@ -45,8 +59,9 @@ class LdapDriverTest extends TestCase
$zendLdap->expects($this->once())->method('bind')->willThrowException(new LdapException());
$user = new User();
$sut = new TestLdapDriver($zendLdap);
$result = $sut->bind($user, 'test123');
$user->setUserIdentifier('foo');
$sut = $this->getTestLdapDriver($zendLdap);
$result = $sut->bind($user->getUserIdentifier(), 'test123');
self::assertFalse($result);
}
@@ -56,7 +71,7 @@ class LdapDriverTest extends TestCase
$zendLdap->expects($this->once())->method('bind');
$zendLdap->expects($this->once())->method('searchEntries')->willReturn([1, 2, 3]);
$sut = new TestLdapDriver($zendLdap);
$sut = $this->getTestLdapDriver($zendLdap);
$result = $sut->search('', '', []);
self::assertEquals(['count' => 3, 1, 2, 3], $result);
}
@@ -64,14 +79,15 @@ class LdapDriverTest extends TestCase
class TestLdapDriver extends LdapDriver
{
private $testDriver;
private Ldap $testDriver;
public function __construct(Ldap $ldap)
public function __construct(LdapConfiguration $config, Ldap $ldap)
{
parent::__construct($config);
$this->testDriver = $ldap;
}
protected function getDriver()
protected function getDriver(): Ldap
{
return $this->testDriver;
}

View File

@@ -10,14 +10,13 @@
namespace App\Tests\Ldap;
use App\Configuration\LdapConfiguration;
use App\Configuration\SystemConfiguration;
use App\Entity\User;
use App\Ldap\LdapDriver;
use App\Ldap\LdapDriverException;
use App\Ldap\LdapManager;
use App\Ldap\LdapUserHydrator;
use App\Tests\Configuration\TestConfigLoader;
use App\Tests\Mocks\Security\RoleServiceFactory;
use App\Tests\Mocks\SystemConfigurationFactory;
use PHPUnit\Framework\TestCase;
/**
@@ -51,18 +50,17 @@ class LdapManagerTest extends TestCase
],
'role' => $roleConfig,
];
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['ldap' => $conf]);
$systemConfig = SystemConfigurationFactory::create(new TestConfigLoader([]), ['ldap' => $conf]);
$config = new LdapConfiguration($systemConfig);
$roles = [
'ROLE_TEAMLEAD' => ['ROLE_USER'],
'ROLE_ADMIN' => ['ROLE_TEAMLEAD'],
'ROLE_SUPER_ADMIN' => ['ROLE_ADMIN']
'ROLE_USER',
'ROLE_TEAMLEAD',
'ROLE_ADMIN',
'ROLE_SUPER_ADMIN',
];
$hydrator = new LdapUserHydrator($config, (new RoleServiceFactory($this))->create($roles));
return new LdapManager($driver, $hydrator, $config);
return new LdapManager($driver, $config, (new RoleServiceFactory($this))->create($roles));
}
public function testFindUserByUsernameOnZeroResults()
@@ -108,7 +106,7 @@ class LdapManagerTest extends TestCase
public function testFindUserByUsernameOnValidResult()
{
$expected = [
0 => ['dn' => 'foo'],
0 => ['dn' => 'foo', 'uid' => ['foo']],
'count' => 1,
];
@@ -140,7 +138,7 @@ class LdapManagerTest extends TestCase
});
$sut = $this->getLdapManager($driver);
$actual = $sut->findUserBy(['uid' => 'foo']);
$actual = $sut->findUserByUsername('foo');
self::assertNull($actual);
}
@@ -162,53 +160,56 @@ class LdapManagerTest extends TestCase
});
$sut = $this->getLdapManager($driver);
$sut->findUserBy(['uid' => 'foo']);
$sut->findUserByUsername('foo');
}
public function testFindUserByOnValidResult()
{
$expected = [
0 => ['dn' => 'foo'],
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))(träl=alß#\\\aa=XY\5cZ0)(test=fu=n))', $filter);
self::assertEquals('(&(&(objectClass=inetOrgPerson))(uid=trä\5cl=alß#aa=XY\5cZ0))', $filter);
return $expected;
});
$sut = $this->getLdapManager($driver);
$actual = $sut->findUserBy(['träl=alß#\\\aa' => 'XY\Z0', 'test' => 'fu=n']);
$actual = $sut->findUserByUsername('trä\l=alß#aa=XY\Z0');
self::assertInstanceOf(User::class, $actual);
}
public function testBind()
{
$user = (new User())->setUsername('foobar');
$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) use ($user) {
self::assertSame($user, $bindUser);
$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, 'a-very-secret-secret');
$actual = $sut->bind($user->getUserIdentifier(), 'a-very-secret-secret');
self::assertTrue($actual);
}
public function testUpdateUserOnZeroResults()
{
$user = (new User())->setUsername('foobar');
$user = new User();
$user->setUserIdentifier('foobar');
$user->setPreferenceValue('ldap.dn', 'fooooooooooo');
$expected = [
[
0 => ['dn' => 'blub'],
0 => ['dn' => 'blub', 'uid' => ['blub']],
'count' => 1,
],
[
@@ -242,12 +243,13 @@ class LdapManagerTest extends TestCase
$this->expectException(LdapDriverException::class);
$this->expectExceptionMessage('This search must only return a single user');
$user = (new User())->setUsername('foobar');
$user = new User();
$user->setUserIdentifier('foobar');
$user->setPreferenceValue('ldap.dn', 'xxxxxxx');
$expected = [
[
0 => ['dn' => 'blub'],
0 => ['dn' => 'blub', 'uid' => ['blub']],
'count' => 1,
],
[
@@ -276,16 +278,17 @@ class LdapManagerTest extends TestCase
public function testUpdateUserOnValidResultWithEmptyRoleBaseDn()
{
$user = (new User())->setUsername('foobar');
$user = new User();
$user->setUserIdentifier('foobar');
$user->setPreferenceValue('ldap.dn', 'sssssss');
$expected = [
[
0 => ['dn' => 'blub'],
0 => ['dn' => 'blub', 'uid' => ['blub']],
'count' => 1,
],
[
0 => ['dn' => 'blub-updated'],
0 => ['dn' => 'blub-updated', 'uid' => ['foobar']],
'count' => 1,
],
];
@@ -391,7 +394,7 @@ class LdapManagerTest extends TestCase
public function testUpdateUserOnValidResultWithRolesResult(array $expectedUsers, array $groupConfig, string $expectedGroupQuery)
{
$expected = [
0 => ['dn' => 'blub'],
0 => ['dn' => 'blub', 'uid' => ['blub']],
'count' => 1,
];
@@ -447,7 +450,8 @@ class LdapManagerTest extends TestCase
$sut = $this->getLdapManager($driver, $groupConfig);
$user = (new User())->setUsername('Karl-Heinz');
$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);
@@ -456,4 +460,286 @@ class LdapManagerTest extends TestCase
self::assertEquals($userOrig, $user);
self::assertEquals(['ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_USER'], $user->getRoles());
}
public function testEmptyHydrate()
{
$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()
{
$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()
{
$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()
{
$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()
{
$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()
{
$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());
}
}

View File

@@ -1,202 +0,0 @@
<?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\Configuration\SystemConfiguration;
use App\Entity\User;
use App\Ldap\LdapUserHydrator;
use App\Tests\Configuration\TestConfigLoader;
use App\Tests\Mocks\Security\RoleServiceFactory;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Ldap\LdapUserHydrator
*/
class LdapUserHydratorTest extends TestCase
{
public function testEmptyHydrate()
{
$ldapConfig = [
'activate' => true,
'connection' => [
'host' => '1.1.1.1'
],
'user' => [
'usernameAttribute' => 'foo',
'attributes' => []
],
'role' => [],
];
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['ldap' => $ldapConfig]);
$config = new LdapConfiguration($systemConfig);
$sut = new LdapUserHydrator($config, (new RoleServiceFactory($this))->create([]));
$user = $sut->hydrate(['dn' => 'blub']);
self::assertInstanceOf(User::class, $user);
self::assertEmpty($user->getUsername());
self::assertEmpty($user->getEmail());
}
public function testHydrate()
{
$ldapConfig = [
'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' => [],
];
$systemConfig = new SystemConfiguration(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 LdapUserHydrator($config, (new RoleServiceFactory($this))->create([]));
$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()
{
$ldapConfig = [
'connection' => [
'host' => '1.1.1.1'
],
'user' => [
'usernameAttribute' => 'foo',
'attributes' => [
['ldap_attr' => 'uid', 'user_method' => 'setUsername'],
['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 = new SystemConfiguration(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 LdapUserHydrator($config, (new RoleServiceFactory($this))->create([]));
$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@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()
{
$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 = new SystemConfiguration(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_TEAMLEAD' => ['ROLE_USER'],
'ROLE_ADMIN' => ['ROLE_TEAMLEAD'],
'ROLE_SUPER_ADMIN' => ['ROLE_ADMIN']
];
$sut = new LdapUserHydrator($config, (new RoleServiceFactory($this))->create($roles));
$user = new User();
$sut->hydrateRoles($user, $ldapGroups);
self::assertEquals(['ROLE_TEAMLEAD', 'ROLE_ADMIN', 'ROLE_USER'], $user->getRoles());
}
}

View File

@@ -15,35 +15,35 @@ use App\Ldap\LdapManager;
use App\Ldap\LdapUserProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
/**
* @covers \App\Ldap\LdapUserProvider
*/
class LdapUserProviderTest extends TestCase
{
public function testLoadUserByUsernameReturnsNull()
public function testLoadUserByIdentifierReturnsNull()
{
$this->expectException(UsernameNotFoundException::class);
$this->expectException(UserNotFoundException::class);
$this->expectExceptionMessage('User "test" not found');
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->onlyMethods(['findUserByUsername'])->getMock();
$manager->expects($this->once())->method('findUserByUsername')->willReturn(null);
$sut = new LdapUserProvider($manager);
$sut->loadUserByUsername('test');
$sut->loadUserByIdentifier('test');
}
public function testLoadUserByUsernameReturnsUser()
public function testLoadUserByIdentifierReturnsUser()
{
$user = new User();
$user->setUsername('foobar');
$user->setUserIdentifier('foobar');
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->onlyMethods(['findUserByUsername'])->getMock();
$manager->expects($this->once())->method('findUserByUsername')->willReturn($user);
$sut = new LdapUserProvider($manager);
$actual = $sut->loadUserByUsername('test');
$actual = $sut->loadUserByIdentifier('test');
self::assertInstanceOf(User::class, $actual);
self::assertSame($user, $actual);
}
@@ -51,7 +51,7 @@ class LdapUserProviderTest extends TestCase
public function testRefreshUserReturnsUser()
{
$user = new User();
$user->setUsername('foobar');
$user->setUserIdentifier('foobar');
$user->setPreferenceValue('ldap.dn', 'sdfdsf');
self::assertFalse($user->isLdapUser());
@@ -71,7 +71,7 @@ class LdapUserProviderTest extends TestCase
$this->expectExceptionMessage('Account "foobar" is not a registered LDAP user.');
$user = new User();
$user->setUsername('foobar');
$user->setUserIdentifier('foobar');
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->onlyMethods(['updateUser'])->getMock();
@@ -85,7 +85,7 @@ class LdapUserProviderTest extends TestCase
$this->expectExceptionMessage('Failed to refresh user "foobar", probably DN is expired.');
$user = new User();
$user->setUsername('foobar');
$user->setUserIdentifier('foobar');
$user->setPreferenceValue('ldap.dn', 'sdfdsf');
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->onlyMethods(['updateUser'])->getMock();