Refactor authentication system (#2602)
Make auth configuration available via UI, remove FOSUserBundle and SAML-Bundle dependency
This commit is contained in:
102
tests/Command/ActivateUserCommandTest.php
Normal file
102
tests/Command/ActivateUserCommandTest.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\Command;
|
||||
|
||||
use App\Command\ActivateUserCommand;
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use App\User\UserService;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* @covers \App\Command\ActivateUserCommand
|
||||
* @group integration
|
||||
*/
|
||||
class ActivateUserCommandTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
private $application;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$kernel = self::bootKernel();
|
||||
$this->application = new Application($kernel);
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$userService = $container->get(UserService::class);
|
||||
|
||||
$this->application->add(new ActivateUserCommand($userService));
|
||||
}
|
||||
|
||||
public function testCommandName()
|
||||
{
|
||||
$application = $this->application;
|
||||
|
||||
$command = $application->find('kimai:user:activate');
|
||||
self::assertInstanceOf(ActivateUserCommand::class, $command);
|
||||
|
||||
// test alias
|
||||
$command = $application->find('fos:user:activate');
|
||||
self::assertInstanceOf(ActivateUserCommand::class, $command);
|
||||
}
|
||||
|
||||
protected function callCommand(?string $username)
|
||||
{
|
||||
$command = $this->application->find('kimai:user:activate');
|
||||
$input = [
|
||||
'command' => $command->getName(),
|
||||
];
|
||||
|
||||
if ($username !== null) {
|
||||
$input['username'] = $username;
|
||||
}
|
||||
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->execute($input);
|
||||
|
||||
return $commandTester;
|
||||
}
|
||||
|
||||
public function testActivate()
|
||||
{
|
||||
$commandTester = $this->callCommand('chris_user');
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[OK] User "chris_user" has been activated.', $output);
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
/** @var UserRepository $userRepository */
|
||||
$userRepository = $container->get('doctrine')->getRepository(User::class);
|
||||
$user = $userRepository->loadUserByUsername('chris_user');
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
self::assertTrue($user->isEnabled());
|
||||
}
|
||||
|
||||
public function testActivateOnActiveUser()
|
||||
{
|
||||
$commandTester = $this->callCommand('susan_super');
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[WARNING] User "susan_super" is already active.', $output);
|
||||
}
|
||||
|
||||
public function testWithMissingUsername()
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('Not enough arguments (missing: "username").');
|
||||
|
||||
$this->callCommand(null);
|
||||
}
|
||||
}
|
||||
109
tests/Command/ChangePasswordCommandTest.php
Normal file
109
tests/Command/ChangePasswordCommandTest.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?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\Command;
|
||||
|
||||
use App\Command\ChangePasswordCommand;
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use App\User\UserService;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* @covers \App\Command\ChangePasswordCommand
|
||||
* @group integration
|
||||
*/
|
||||
class ChangePasswordCommandTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
private $application;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$kernel = self::bootKernel();
|
||||
$this->application = new Application($kernel);
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$userService = $container->get(UserService::class);
|
||||
|
||||
$this->application->add(new ChangePasswordCommand($userService));
|
||||
}
|
||||
|
||||
public function testCommandName()
|
||||
{
|
||||
$application = $this->application;
|
||||
|
||||
$command = $application->find('kimai:user:password');
|
||||
self::assertInstanceOf(ChangePasswordCommand::class, $command);
|
||||
|
||||
// test alias
|
||||
$command = $application->find('fos:user:change-password');
|
||||
self::assertInstanceOf(ChangePasswordCommand::class, $command);
|
||||
}
|
||||
|
||||
protected function callCommand(?string $username, ?string $password)
|
||||
{
|
||||
$command = $this->application->find('kimai:user:password');
|
||||
$input = [
|
||||
'command' => $command->getName(),
|
||||
];
|
||||
|
||||
if ($username !== null) {
|
||||
$input['username'] = $username;
|
||||
}
|
||||
|
||||
if ($password !== null) {
|
||||
$input['password'] = $password;
|
||||
}
|
||||
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->execute($input);
|
||||
|
||||
return $commandTester;
|
||||
}
|
||||
|
||||
public function testChangePassword()
|
||||
{
|
||||
$commandTester = $this->callCommand('john_user', '0987654321');
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[OK] Changed password for user "john_user".', $output);
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
/** @var UserRepository $userRepository */
|
||||
$userRepository = $container->get('doctrine')->getRepository(User::class);
|
||||
$user = $userRepository->loadUserByUsername('john_user');
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
$encoderService = $container->get('security.password_encoder');
|
||||
self::assertTrue($encoderService->isPasswordValid($user, '0987654321'));
|
||||
}
|
||||
|
||||
public function testWithMissingUsername()
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('Not enough arguments (missing: "username").');
|
||||
|
||||
$this->callCommand(null, '1234567890');
|
||||
}
|
||||
|
||||
public function testWithMissingPassword()
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('Not enough arguments (missing: "password").');
|
||||
|
||||
$this->callCommand('1234567890', null);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ namespace App\Tests\Command;
|
||||
use App\Command\CreateUserCommand;
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use App\User\UserService;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
@@ -25,7 +26,7 @@ class CreateUserCommandTest extends KernelTestCase
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
protected $application;
|
||||
private $application;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
@@ -33,12 +34,8 @@ class CreateUserCommandTest extends KernelTestCase
|
||||
$this->application = new Application($kernel);
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$passwordEncoder = $container->get('security.password_encoder');
|
||||
|
||||
$this->application->add(new CreateUserCommand(
|
||||
$passwordEncoder,
|
||||
$container->get('doctrine'),
|
||||
$container->get('validator')
|
||||
$container->get(UserService::class),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -68,7 +65,7 @@ class CreateUserCommandTest extends KernelTestCase
|
||||
|
||||
protected function createUser($username, $email, $role, $password)
|
||||
{
|
||||
$command = $this->application->find('kimai:create-user');
|
||||
$command = $this->application->find('kimai:user:create');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
@@ -86,19 +83,31 @@ class CreateUserCommandTest extends KernelTestCase
|
||||
$commandTester = $this->createUser('xx', '', 'ROLE_USER', '');
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[ERROR] email ()', $output);
|
||||
$this->assertStringContainsString('Please enter an email', $output);
|
||||
$this->assertStringContainsString('This value should not be blank', $output);
|
||||
$this->assertStringContainsString('[ERROR] plainPassword ()', $output);
|
||||
$this->assertStringContainsString('Please enter a password', $output);
|
||||
$this->assertStringContainsString('This value should not be blank', $output);
|
||||
$this->assertStringContainsString('[ERROR] plainPassword ()', $output);
|
||||
$this->assertStringContainsString('This value is too short. It should have 8 characters or more', $output);
|
||||
}
|
||||
|
||||
public function testUserAlreadyExisting()
|
||||
{
|
||||
$this->createUser('MyTestUser', 'user@example.com', 'ROLE_USER', 'foobar12');
|
||||
$commandTester = $this->createUser('MyTestUser', 'user@example.com', 'ROLE_USER', 'foobar');
|
||||
$this->createUser('MyTestUser', 'user@example.com', 'ROLE_USER', 'foobar123');
|
||||
$commandTester = $this->createUser('MyTestUser', 'user2@example.com', 'ROLE_USER', 'foobar123');
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[ERROR] username (mytestuser)', $output);
|
||||
$this->assertStringContainsString('The username is already used', $output);
|
||||
$this->assertStringContainsString('[ERROR] username (MyTestUser)', $output);
|
||||
$this->assertStringContainsString('The username is already used.', $output);
|
||||
}
|
||||
|
||||
public function testEmailAlreadyExisting()
|
||||
{
|
||||
$this->createUser('MyTestUser', 'user@example.com', 'ROLE_USER', 'foobar12');
|
||||
$commandTester = $this->createUser('MyTestUser2', 'user@example.com', 'ROLE_USER', 'foobar');
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[ERROR] email (MyTestUser2)', $output);
|
||||
$this->assertStringContainsString(' The email is already used.', $output);
|
||||
}
|
||||
|
||||
public function testUserEmail()
|
||||
@@ -107,6 +116,6 @@ class CreateUserCommandTest extends KernelTestCase
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[ERROR] email (ROLE_USER)', $output);
|
||||
$this->assertStringContainsString('The email is not valid', $output);
|
||||
$this->assertStringContainsString('This value is not a valid email address', $output);
|
||||
}
|
||||
}
|
||||
|
||||
102
tests/Command/DeactivateUserCommandTest.php
Normal file
102
tests/Command/DeactivateUserCommandTest.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\Command;
|
||||
|
||||
use App\Command\DeactivateUserCommand;
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use App\User\UserService;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* @covers \App\Command\DeactivateUserCommand
|
||||
* @group integration
|
||||
*/
|
||||
class DeactivateUserCommandTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
private $application;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$kernel = self::bootKernel();
|
||||
$this->application = new Application($kernel);
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$userService = $container->get(UserService::class);
|
||||
|
||||
$this->application->add(new DeactivateUserCommand($userService));
|
||||
}
|
||||
|
||||
public function testCommandName()
|
||||
{
|
||||
$application = $this->application;
|
||||
|
||||
$command = $application->find('kimai:user:deactivate');
|
||||
self::assertInstanceOf(DeactivateUserCommand::class, $command);
|
||||
|
||||
// test alias
|
||||
$command = $application->find('fos:user:deactivate');
|
||||
self::assertInstanceOf(DeactivateUserCommand::class, $command);
|
||||
}
|
||||
|
||||
protected function callCommand(?string $username)
|
||||
{
|
||||
$command = $this->application->find('kimai:user:deactivate');
|
||||
$input = [
|
||||
'command' => $command->getName(),
|
||||
];
|
||||
|
||||
if ($username !== null) {
|
||||
$input['username'] = $username;
|
||||
}
|
||||
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->execute($input);
|
||||
|
||||
return $commandTester;
|
||||
}
|
||||
|
||||
public function testDeactivate()
|
||||
{
|
||||
$commandTester = $this->callCommand('john_user');
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[OK] User "john_user" has been deactivated.', $output);
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
/** @var UserRepository $userRepository */
|
||||
$userRepository = $container->get('doctrine')->getRepository(User::class);
|
||||
$user = $userRepository->loadUserByUsername('john_user');
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
self::assertFalse($user->isEnabled());
|
||||
}
|
||||
|
||||
public function testDeactivateOnDeactivatedUser()
|
||||
{
|
||||
$commandTester = $this->callCommand('chris_user');
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[WARNING] User "chris_user" is already deactivated.', $output);
|
||||
}
|
||||
|
||||
public function testWithMissingUsername()
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('Not enough arguments (missing: "username").');
|
||||
|
||||
$this->callCommand(null);
|
||||
}
|
||||
}
|
||||
142
tests/Command/DemoteUserCommandTest.php
Normal file
142
tests/Command/DemoteUserCommandTest.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?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\Command;
|
||||
|
||||
use App\Command\DemoteUserCommand;
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use App\User\UserService;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* @covers \App\Command\AbstractRoleCommand
|
||||
* @covers \App\Command\DemoteUserCommand
|
||||
* @group integration
|
||||
*/
|
||||
class DemoteUserCommandTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
private $application;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$kernel = self::bootKernel();
|
||||
$this->application = new Application($kernel);
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$userService = $container->get(UserService::class);
|
||||
|
||||
$this->application->add(new DemoteUserCommand($userService));
|
||||
}
|
||||
|
||||
public function testCommandName()
|
||||
{
|
||||
$application = $this->application;
|
||||
|
||||
$command = $application->find('kimai:user:demote');
|
||||
self::assertInstanceOf(DemoteUserCommand::class, $command);
|
||||
|
||||
// test alias
|
||||
$command = $application->find('fos:user:demote');
|
||||
self::assertInstanceOf(DemoteUserCommand::class, $command);
|
||||
}
|
||||
|
||||
protected function callCommand(?string $username, ?string $role, bool $super = false)
|
||||
{
|
||||
$command = $this->application->find('kimai:user:demote');
|
||||
$input = [
|
||||
'command' => $command->getName(),
|
||||
];
|
||||
|
||||
if ($role !== null) {
|
||||
$input['role'] = $role;
|
||||
}
|
||||
|
||||
if ($username !== null) {
|
||||
$input['username'] = $username;
|
||||
}
|
||||
|
||||
if ($super) {
|
||||
$input['--super'] = true;
|
||||
}
|
||||
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->execute($input);
|
||||
|
||||
return $commandTester;
|
||||
}
|
||||
|
||||
public function testDemoteRole()
|
||||
{
|
||||
$commandTester = $this->callCommand('tony_teamlead', 'ROLE_TEAMLEAD');
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[OK] Role "ROLE_TEAMLEAD" has been removed from user "tony_teamlead".', $output);
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
/** @var UserRepository $userRepository */
|
||||
$userRepository = $container->get('doctrine')->getRepository(User::class);
|
||||
$user = $userRepository->loadUserByUsername('tony_teamlead');
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
self::assertFalse($user->isTeamlead());
|
||||
}
|
||||
|
||||
public function testDemoteSuper()
|
||||
{
|
||||
$commandTester = $this->callCommand('susan_super', null, true);
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[OK] Super administrator role has been removed from the user "susan_super".', $output);
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
/** @var UserRepository $userRepository */
|
||||
$userRepository = $container->get('doctrine')->getRepository(User::class);
|
||||
$user = $userRepository->loadUserByUsername('susan_super');
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
self::assertFalse($user->isSuperAdmin());
|
||||
}
|
||||
|
||||
public function testDemoteSuperFailsOnTeamlead()
|
||||
{
|
||||
$commandTester = $this->callCommand('tony_teamlead', null, true);
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[WARNING] User "tony_teamlead" doesn\'t have the super administrator role.', $output);
|
||||
}
|
||||
|
||||
public function testDemoteAdminFailsOnTeamlead()
|
||||
{
|
||||
$commandTester = $this->callCommand('tony_teamlead', 'ROLE_ADMIN', false);
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[WARNING] User "tony_teamlead" didn\'t have "ROLE_ADMIN" role.', $output);
|
||||
}
|
||||
|
||||
public function testDemoteRoleAndSuperFails()
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('You can pass either the role or the --super option (but not both simultaneously).');
|
||||
|
||||
$this->callCommand('john_user', 'ROLE_TEAMLEAD', true);
|
||||
}
|
||||
|
||||
public function testWithMissingUsername()
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('Not enough arguments (missing: "username").');
|
||||
|
||||
$this->callCommand(null, null, true);
|
||||
}
|
||||
}
|
||||
142
tests/Command/PromoteUserCommandTest.php
Normal file
142
tests/Command/PromoteUserCommandTest.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?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\Command;
|
||||
|
||||
use App\Command\PromoteUserCommand;
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use App\User\UserService;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* @covers \App\Command\AbstractRoleCommand
|
||||
* @covers \App\Command\PromoteUserCommand
|
||||
* @group integration
|
||||
*/
|
||||
class PromoteUserCommandTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
private $application;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$kernel = self::bootKernel();
|
||||
$this->application = new Application($kernel);
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$userService = $container->get(UserService::class);
|
||||
|
||||
$this->application->add(new PromoteUserCommand($userService));
|
||||
}
|
||||
|
||||
public function testCommandName()
|
||||
{
|
||||
$application = $this->application;
|
||||
|
||||
$command = $application->find('kimai:user:promote');
|
||||
self::assertInstanceOf(PromoteUserCommand::class, $command);
|
||||
|
||||
// test alias
|
||||
$command = $application->find('fos:user:promote');
|
||||
self::assertInstanceOf(PromoteUserCommand::class, $command);
|
||||
}
|
||||
|
||||
protected function callCommand(?string $username, ?string $role, bool $super = false)
|
||||
{
|
||||
$command = $this->application->find('kimai:user:promote');
|
||||
$input = [
|
||||
'command' => $command->getName(),
|
||||
];
|
||||
|
||||
if ($role !== null) {
|
||||
$input['role'] = $role;
|
||||
}
|
||||
|
||||
if ($username !== null) {
|
||||
$input['username'] = $username;
|
||||
}
|
||||
|
||||
if ($super) {
|
||||
$input['--super'] = true;
|
||||
}
|
||||
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->execute($input);
|
||||
|
||||
return $commandTester;
|
||||
}
|
||||
|
||||
public function testPromoteRole()
|
||||
{
|
||||
$commandTester = $this->callCommand('john_user', 'ROLE_TEAMLEAD');
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[OK] Role "ROLE_TEAMLEAD" has been added to user "john_user".', $output);
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
/** @var UserRepository $userRepository */
|
||||
$userRepository = $container->get('doctrine')->getRepository(User::class);
|
||||
$user = $userRepository->loadUserByUsername('john_user');
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
self::assertTrue($user->isTeamlead());
|
||||
}
|
||||
|
||||
public function testPromoteSuper()
|
||||
{
|
||||
$commandTester = $this->callCommand('john_user', null, true);
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[OK] User "john_user" has been promoted as a super administrator.', $output);
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
/** @var UserRepository $userRepository */
|
||||
$userRepository = $container->get('doctrine')->getRepository(User::class);
|
||||
$user = $userRepository->loadUserByUsername('john_user');
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
self::assertTrue($user->isSuperAdmin());
|
||||
}
|
||||
|
||||
public function testPromoteSuperFailsOnSuperAdmin()
|
||||
{
|
||||
$commandTester = $this->callCommand('susan_super', null, true);
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[WARNING] User "susan_super" does already have the super administrator role.', $output);
|
||||
}
|
||||
|
||||
public function testPromoteTeamleadFailsOnTeamlead()
|
||||
{
|
||||
$commandTester = $this->callCommand('tony_teamlead', 'ROLE_TEAMLEAD', false);
|
||||
|
||||
$output = $commandTester->getDisplay();
|
||||
$this->assertStringContainsString('[WARNING] User "tony_teamlead" did already have "ROLE_TEAMLEAD" role.', $output);
|
||||
}
|
||||
|
||||
public function testPromoteRoleAndSuperFails()
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('You can pass either the role or the --super option (but not both simultaneously).');
|
||||
|
||||
$this->callCommand('john_user', 'ROLE_TEAMLEAD', true);
|
||||
}
|
||||
|
||||
public function testWithMissingUsername()
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('Not enough arguments (missing: "username").');
|
||||
|
||||
$this->callCommand(null, null, true);
|
||||
}
|
||||
}
|
||||
@@ -10,21 +10,26 @@
|
||||
namespace App\Tests\Configuration;
|
||||
|
||||
use App\Configuration\LdapConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Configuration\LdapConfiguration
|
||||
* @covers \App\Configuration\SystemConfiguration
|
||||
*/
|
||||
class LdapConfigurationTest extends TestCase
|
||||
{
|
||||
protected function getSut(array $settings)
|
||||
{
|
||||
return new LdapConfiguration($settings);
|
||||
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['ldap' => $settings]);
|
||||
|
||||
return new LdapConfiguration($systemConfig);
|
||||
}
|
||||
|
||||
protected function getDefaultSettings()
|
||||
{
|
||||
return [
|
||||
'activate' => true,
|
||||
'connection' => [
|
||||
'host' => '1.2.3.4',
|
||||
],
|
||||
@@ -37,9 +42,19 @@ class LdapConfigurationTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
public function testDefault()
|
||||
{
|
||||
$sut = $this->getSut([]);
|
||||
$this->assertFalse($sut->isActivated());
|
||||
$this->assertEquals([], $sut->getUserParameters());
|
||||
$this->assertEquals([], $sut->getRoleParameters());
|
||||
$this->assertEquals([], $sut->getConnectionParameters());
|
||||
}
|
||||
|
||||
public function testMapping()
|
||||
{
|
||||
$sut = $this->getSut($this->getDefaultSettings());
|
||||
$this->assertTrue($sut->isActivated());
|
||||
$this->assertEquals(['foo' => 'bar'], $sut->getUserParameters());
|
||||
$this->assertEquals(['bar' => 'foo'], $sut->getRoleParameters());
|
||||
$this->assertEquals(['host' => '1.2.3.4'], $sut->getConnectionParameters());
|
||||
|
||||
80
tests/Configuration/SamlConfigurationTest.php
Normal file
80
tests/Configuration/SamlConfigurationTest.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?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\Configuration;
|
||||
|
||||
use App\Configuration\SamlConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Configuration\SamlConfiguration
|
||||
* @covers \App\Configuration\SystemConfiguration
|
||||
*/
|
||||
class SamlConfigurationTest extends TestCase
|
||||
{
|
||||
protected function getSut(array $settings)
|
||||
{
|
||||
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['saml' => $settings]);
|
||||
|
||||
return new SamlConfiguration($systemConfig);
|
||||
}
|
||||
|
||||
protected function getDefaultSettings()
|
||||
{
|
||||
return [
|
||||
'activate' => true,
|
||||
'title' => 'SAML title',
|
||||
'connection' => [
|
||||
'host' => '1.2.3.4',
|
||||
],
|
||||
'mapping' => [
|
||||
['saml' => '$Email', 'kimai' => 'email'],
|
||||
['saml' => '$FirstName $LastName', 'kimai' => 'alias'],
|
||||
],
|
||||
'roles' => [
|
||||
'attribute' => 'Roles',
|
||||
'mapping' => [
|
||||
['saml' => 'Kimai - Admin', 'kimai' => 'ROLE_SUPER_ADMIN'],
|
||||
['saml' => 'Management', 'kimai' => 'ROLE_TEAMLEAD'],
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function testDefault()
|
||||
{
|
||||
$sut = $this->getSut([]);
|
||||
$this->assertFalse($sut->isActivated());
|
||||
$this->assertEquals('', $sut->getTitle());
|
||||
$this->assertEquals([], $sut->getConnection());
|
||||
$this->assertEquals([], $sut->getRolesMapping());
|
||||
$this->assertEquals('', $sut->getRolesAttribute());
|
||||
$this->assertEquals([], $sut->getAttributeMapping());
|
||||
}
|
||||
|
||||
public function testDefaultSettings()
|
||||
{
|
||||
$sut = $this->getSut($this->getDefaultSettings());
|
||||
$this->assertTrue($sut->isActivated());
|
||||
$this->assertEquals('SAML title', $sut->getTitle());
|
||||
$this->assertEquals([
|
||||
'host' => '1.2.3.4',
|
||||
], $sut->getConnection());
|
||||
$this->assertEquals([
|
||||
['saml' => 'Kimai - Admin', 'kimai' => 'ROLE_SUPER_ADMIN'],
|
||||
['saml' => 'Management', 'kimai' => 'ROLE_TEAMLEAD'],
|
||||
], $sut->getRolesMapping());
|
||||
$this->assertEquals('Roles', $sut->getRolesAttribute());
|
||||
$this->assertEquals([
|
||||
['saml' => '$Email', 'kimai' => 'email'],
|
||||
['saml' => '$FirstName $LastName', 'kimai' => 'alias'],
|
||||
], $sut->getAttributeMapping());
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,9 @@ class TestConfigLoader implements ConfigLoaderInterface
|
||||
{
|
||||
private $configs = [];
|
||||
|
||||
/**
|
||||
* @param Configuration[] $configs
|
||||
*/
|
||||
public function __construct(array $configs)
|
||||
{
|
||||
$this->configs = $configs;
|
||||
|
||||
@@ -11,8 +11,10 @@ namespace App\Tests\Controller\Auth;
|
||||
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Controller\Auth\SamlController;
|
||||
use App\Saml\SamlAuthFactory;
|
||||
use App\Tests\Configuration\TestConfigLoader;
|
||||
use App\Tests\Mocks\Saml\SamlAuthFactory;
|
||||
use App\Tests\Mocks\Saml\SamlAuthFactoryFactory;
|
||||
use OneLogin\Saml2\Auth;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\Util\Xml;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -47,9 +49,9 @@ class SamlControllerTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
protected function getAuth()
|
||||
protected function getAuth(): Auth
|
||||
{
|
||||
return (new SamlAuthFactory($this))->create();
|
||||
return (new SamlAuthFactoryFactory($this))->create()->create();
|
||||
}
|
||||
|
||||
protected function getSystemConfiguration(bool $activated = true)
|
||||
@@ -62,8 +64,9 @@ class SamlControllerTest extends TestCase
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('You must configure the check path in your firewall.');
|
||||
|
||||
$oauth = $this->getAuth();
|
||||
$sut = new SamlController($oauth, $this->getSystemConfiguration());
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$sut = new SamlController($factory, $this->getSystemConfiguration());
|
||||
$sut->assertionConsumerServiceAction();
|
||||
}
|
||||
|
||||
@@ -72,8 +75,9 @@ class SamlControllerTest extends TestCase
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('You must configure the logout path in your firewall.');
|
||||
|
||||
$oauth = $this->getAuth();
|
||||
$sut = new SamlController($oauth, $this->getSystemConfiguration());
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$sut = new SamlController($factory, $this->getSystemConfiguration());
|
||||
$sut->logoutAction();
|
||||
}
|
||||
|
||||
@@ -104,7 +108,11 @@ class SamlControllerTest extends TestCase
|
||||
EOD;
|
||||
|
||||
$oauth = $this->getAuth();
|
||||
$sut = new SamlController($oauth, $this->getSystemConfiguration());
|
||||
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
$factory->expects($this->once())->method('create')->willReturn($oauth);
|
||||
|
||||
$sut = new SamlController($factory, $this->getSystemConfiguration());
|
||||
$result = $sut->metadataAction();
|
||||
|
||||
self::assertInstanceOf(Response::class, $result);
|
||||
@@ -126,8 +134,9 @@ EOD;
|
||||
$request->setSession($this->createMock(SessionInterface::class));
|
||||
$request->attributes->set(Security::AUTHENTICATION_ERROR, new \Exception('My test error'));
|
||||
|
||||
$oauth = $this->getAuth();
|
||||
$sut = new SamlController($oauth, $this->getSystemConfiguration());
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$sut = new SamlController($factory, $this->getSystemConfiguration());
|
||||
$sut->loginAction($request);
|
||||
}
|
||||
|
||||
@@ -136,7 +145,9 @@ EOD;
|
||||
$this->expectException(NotFoundHttpException::class);
|
||||
$this->expectExceptionMessage('SAML deactivated');
|
||||
|
||||
$sut = new SamlController($this->getAuth(), $this->getSystemConfiguration(false));
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$sut = new SamlController($factory, $this->getSystemConfiguration(false));
|
||||
$sut->loginAction(new Request());
|
||||
}
|
||||
|
||||
@@ -145,7 +156,9 @@ EOD;
|
||||
$this->expectException(NotFoundHttpException::class);
|
||||
$this->expectExceptionMessage('SAML deactivated');
|
||||
|
||||
$sut = new SamlController($this->getAuth(), $this->getSystemConfiguration(false));
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$sut = new SamlController($factory, $this->getSystemConfiguration(false));
|
||||
$sut->metadataAction();
|
||||
}
|
||||
|
||||
@@ -154,7 +167,9 @@ EOD;
|
||||
$this->expectException(NotFoundHttpException::class);
|
||||
$this->expectExceptionMessage('SAML deactivated');
|
||||
|
||||
$sut = new SamlController($this->getAuth(), $this->getSystemConfiguration(false));
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$sut = new SamlController($factory, $this->getSystemConfiguration(false));
|
||||
$sut->logoutAction();
|
||||
}
|
||||
|
||||
@@ -163,7 +178,9 @@ EOD;
|
||||
$this->expectException(NotFoundHttpException::class);
|
||||
$this->expectExceptionMessage('SAML deactivated');
|
||||
|
||||
$sut = new SamlController($this->getAuth(), $this->getSystemConfiguration(false));
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$sut = new SamlController($factory, $this->getSystemConfiguration(false));
|
||||
$sut->assertionConsumerServiceAction();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\DataFixtures\UserFixtures;
|
||||
use App\Entity\Configuration;
|
||||
use App\Entity\User;
|
||||
use App\Repository\ConfigurationRepository;
|
||||
use App\Repository\UserRepository;
|
||||
use App\Tests\KernelTestTrait;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
@@ -33,6 +35,43 @@ abstract class ControllerBaseTest extends WebTestCase
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Using a special container, to access private services as well.
|
||||
*
|
||||
* @param string $service
|
||||
* @return object|null
|
||||
* @see https://symfony.com/blog/new-in-symfony-4-1-simpler-service-testing
|
||||
*/
|
||||
protected function getPrivateService(string $service)
|
||||
{
|
||||
return self::$container->get($service);
|
||||
}
|
||||
|
||||
protected function loadUserFromDatabase(string $username)
|
||||
{
|
||||
$container = self::$kernel->getContainer();
|
||||
/** @var UserRepository $userRepository */
|
||||
$userRepository = $container->get('doctrine')->getRepository(User::class);
|
||||
$user = $userRepository->loadUserByUsername($username);
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
protected function setSystemConfiguration(string $name, $value): void
|
||||
{
|
||||
$repository = static::$kernel->getContainer()->get(ConfigurationRepository::class);
|
||||
|
||||
$entity = $repository->findOneBy(['name' => $name]);
|
||||
if ($entity === null) {
|
||||
$entity = new Configuration();
|
||||
$entity->setName($name);
|
||||
}
|
||||
$entity->setValue($value);
|
||||
$repository->saveConfiguration($entity);
|
||||
$this->clearConfigCache();
|
||||
}
|
||||
|
||||
protected function clearConfigCache()
|
||||
{
|
||||
/** @var ConfigurationRepository $repository */
|
||||
|
||||
80
tests/Controller/Security/PasswordResetControllerTest.php
Normal file
80
tests/Controller/Security/PasswordResetControllerTest.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?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\Controller\Security;
|
||||
|
||||
use App\Tests\Controller\ControllerBaseTest;
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
class PasswordResetControllerTest extends ControllerBaseTest
|
||||
{
|
||||
private function testResetActionWithDeactivatedFeature(string $route, string $method = 'GET')
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->setSystemConfiguration('user.password_reset', false);
|
||||
$this->request($client, $route, $method);
|
||||
$this->assertRouteNotFound($client);
|
||||
}
|
||||
|
||||
public function testResetRequestWithDeactivatedFeature()
|
||||
{
|
||||
$this->testResetActionWithDeactivatedFeature('/resetting/request');
|
||||
}
|
||||
|
||||
public function testSendEmailRequestWithDeactivatedFeature()
|
||||
{
|
||||
$this->testResetActionWithDeactivatedFeature('/resetting/send-email', 'POST');
|
||||
}
|
||||
|
||||
public function testCheckEmailWithDeactivatedFeature()
|
||||
{
|
||||
$this->testResetActionWithDeactivatedFeature('/resetting/check-email');
|
||||
}
|
||||
|
||||
public function testResetWithDeactivatedFeature()
|
||||
{
|
||||
$this->testResetActionWithDeactivatedFeature('/resetting/reset/1234567890');
|
||||
}
|
||||
|
||||
public function testResetRequestPageIsRendered()
|
||||
{
|
||||
$client = self::createClient();
|
||||
|
||||
$this->setSystemConfiguration('user.password_reset', true);
|
||||
$this->request($client, '/resetting/request');
|
||||
|
||||
$response = $client->getResponse();
|
||||
$this->assertTrue($response->isSuccessful());
|
||||
|
||||
$content = $response->getContent();
|
||||
$this->assertStringContainsString('<title>Kimai – Time Tracking</title>', $content);
|
||||
$this->assertStringContainsString('Reset your password', $content);
|
||||
$this->assertStringContainsString('<form action="/en/resetting/send-email" method="POST" class="fos_user_resetting_request">', $content);
|
||||
$this->assertStringContainsString('<input type="text"', $content);
|
||||
$this->assertStringContainsString('id="username" name="username" required="required"', $content);
|
||||
$this->assertStringContainsString('>Reset your password</button>', $content);
|
||||
|
||||
$form = $client->getCrawler()->filter('form.fos_user_resetting_request')->form();
|
||||
$client->submit($form, [
|
||||
'username' => 'john_user',
|
||||
]);
|
||||
|
||||
$this->assertIsRedirect($client, $this->createUrl('/resetting/check-email?username=john_user'));
|
||||
$client->followRedirect();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$user = $this->loadUserFromDatabase('john_user');
|
||||
$token = $user->getConfirmationToken();
|
||||
|
||||
$this->request($client, '/resetting/reset/' . $token);
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
}
|
||||
}
|
||||
120
tests/Controller/Security/SecurityControllerTest.php
Normal file
120
tests/Controller/Security/SecurityControllerTest.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?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\Controller\Security;
|
||||
|
||||
use App\Controller\Security\SecurityController;
|
||||
use App\Tests\Controller\ControllerBaseTest;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
|
||||
/**
|
||||
* This test makes sure the login and registration work as expected.
|
||||
* The logic is located in the FOSUserBundle and already tested, but we use a different layout.
|
||||
*
|
||||
* @group integration
|
||||
*/
|
||||
class SecurityControllerTest extends ControllerBaseTest
|
||||
{
|
||||
public function testRootUrlIsRedirectedToLogin()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$client->request('GET', '/');
|
||||
|
||||
$this->assertIsRedirect($client, $this->createUrl('/homepage'));
|
||||
$client->followRedirect();
|
||||
$this->assertIsRedirect($client, $this->createUrl('/login'));
|
||||
}
|
||||
|
||||
public function testLoginPageIsRendered()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->request($client, '/login');
|
||||
|
||||
$response = $client->getResponse();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$content = $response->getContent();
|
||||
$this->assertStringContainsString('<title>Kimai – Time Tracking</title>', $content);
|
||||
$this->assertStringContainsString('<form action="/en/login_check" method="post">', $content);
|
||||
$this->assertStringContainsString('<input type="text" name="_username"', $content);
|
||||
$this->assertStringContainsString('<input name="_password" type="password"', $content);
|
||||
$this->assertStringContainsString('<input id="remember_me" name="_remember_me" type="checkbox"', $content);
|
||||
$this->assertStringContainsString('">Login</button>', $content);
|
||||
$this->assertStringContainsString('<input type="hidden" name="_csrf_token" value="', $content);
|
||||
$this->assertStringNotContainsString('<a href="/en/register/"', $content);
|
||||
$this->assertStringNotContainsString('Register a new account', $content);
|
||||
}
|
||||
|
||||
public function testLoginPositive()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->request($client, '/login');
|
||||
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$form = $client->getCrawler()->filter('body form')->form();
|
||||
$client->submit($form, [
|
||||
'_username' => 'susan_super',
|
||||
'_password' => 'kitten'
|
||||
]);
|
||||
|
||||
$this->assertIsRedirect($client); // redirect to root URL
|
||||
$client->followRedirect();
|
||||
|
||||
$this->assertIsRedirect($client, '/homepage'); // redirect to homepage
|
||||
$client->followRedirect();
|
||||
|
||||
$this->assertIsRedirect($client, '/timesheet/'); // redirect to configured start page
|
||||
$client->followRedirect();
|
||||
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
}
|
||||
|
||||
public function testLoginNegative()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->request($client, '/login');
|
||||
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$form = $client->getCrawler()->filter('body form')->form();
|
||||
$client->submit($form, [
|
||||
'_username' => 'susan_super',
|
||||
'_password' => '1234567890'
|
||||
]);
|
||||
|
||||
$this->assertIsRedirect($client); // redirect to root URL
|
||||
$client->followRedirect();
|
||||
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
self::assertStringContainsString('<div class="alert alert-danger">Invalid credentials.</div>', $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testCheckAction()
|
||||
{
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.');
|
||||
|
||||
$client = self::createClient(); // just to bootstrap the container
|
||||
$csrf = $this->createMock(CsrfTokenManagerInterface::class);
|
||||
$sut = new SecurityController($csrf);
|
||||
$sut->checkAction();
|
||||
}
|
||||
|
||||
public function testLogoutAction()
|
||||
{
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('You must activate the logout in your security firewall configuration.');
|
||||
|
||||
$client = self::createClient(); // just to bootstrap the container
|
||||
$csrf = $this->createMock(CsrfTokenManagerInterface::class);
|
||||
$sut = new SecurityController($csrf);
|
||||
$sut->logoutAction();
|
||||
}
|
||||
}
|
||||
@@ -7,49 +7,49 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
namespace App\Tests\Controller\Security;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Tests\Controller\ControllerBaseTest;
|
||||
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
|
||||
|
||||
/**
|
||||
* This test makes sure the login and registration work as expected.
|
||||
* The logic is located in the FOSUserBundle and already tested, but we use a different layout.
|
||||
*
|
||||
* @group integration
|
||||
*/
|
||||
class SecurityControllerTest extends ControllerBaseTest
|
||||
class SelfRegistrationControllerTest extends ControllerBaseTest
|
||||
{
|
||||
public function testRootUrlIsRedirectedToLogin()
|
||||
private function testRegisterActionWithDeactivatedFeature(string $route)
|
||||
{
|
||||
$client = self::createClient();
|
||||
$client->request('GET', '/');
|
||||
|
||||
$this->assertIsRedirect($client, $this->createUrl('/homepage'));
|
||||
$client->followRedirect();
|
||||
$this->assertIsRedirect($client, $this->createUrl('/login'));
|
||||
$this->setSystemConfiguration('user.registration', false);
|
||||
$this->request($client, $route);
|
||||
$this->assertRouteNotFound($client);
|
||||
}
|
||||
|
||||
public function testLoginPageIsRendered()
|
||||
public function testRegisterWithDeactivatedFeature()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->request($client, '/login');
|
||||
$this->testRegisterActionWithDeactivatedFeature('/register/');
|
||||
}
|
||||
|
||||
$response = $client->getResponse();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
public function testCheckEmailWithDeactivatedFeature()
|
||||
{
|
||||
$this->testRegisterActionWithDeactivatedFeature('/register/check-email');
|
||||
}
|
||||
|
||||
$content = $response->getContent();
|
||||
$this->assertStringContainsString('<title>Kimai – Time Tracking</title>', $content);
|
||||
$this->assertStringContainsString('<form action="/en/login_check" method="post">', $content);
|
||||
$this->assertStringContainsString('<input type="text" name="_username"', $content);
|
||||
$this->assertStringContainsString('<input name="_password" type="password"', $content);
|
||||
$this->assertStringContainsString('<input id="remember_me" name="_remember_me" type="checkbox"', $content);
|
||||
$this->assertStringContainsString('">Login</button>', $content);
|
||||
$this->assertStringContainsString('<input type="hidden" name="_csrf_token" value="', $content);
|
||||
$this->assertStringContainsString('<a href="/en/register/"', $content);
|
||||
$this->assertStringContainsString('Register a new account', $content);
|
||||
public function testConfirmWithDeactivatedFeature()
|
||||
{
|
||||
$this->testRegisterActionWithDeactivatedFeature('/register/confirm/123123');
|
||||
}
|
||||
|
||||
public function testConfirmedWithDeactivatedFeature()
|
||||
{
|
||||
$this->testRegisterActionWithDeactivatedFeature('/register/confirmed');
|
||||
}
|
||||
|
||||
public function testRegisterAccountPageIsRendered()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->setSystemConfiguration('user.registration', true);
|
||||
$this->request($client, '/register/');
|
||||
|
||||
$response = $client->getResponse();
|
||||
@@ -71,9 +71,9 @@ class SecurityControllerTest extends ControllerBaseTest
|
||||
$this->assertStringContainsString('>Register</button>', $content);
|
||||
}
|
||||
|
||||
public function testRegisterAccount()
|
||||
private function createUser(KernelBrowser $client, string $username, string $email, string $password): User
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->setSystemConfiguration('user.registration', true);
|
||||
$this->request($client, '/register/');
|
||||
|
||||
$response = $client->getResponse();
|
||||
@@ -82,23 +82,85 @@ class SecurityControllerTest extends ControllerBaseTest
|
||||
$form = $client->getCrawler()->filter('form[name=fos_user_registration_form]')->form();
|
||||
$client->submit($form, [
|
||||
'fos_user_registration_form' => [
|
||||
'email' => 'test@example.com',
|
||||
'username' => 'example',
|
||||
'email' => $email,
|
||||
'username' => $username,
|
||||
'plainPassword' => [
|
||||
'first' => 'test1234',
|
||||
'second' => 'test1234',
|
||||
'first' => $password,
|
||||
'second' => $password,
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertIsRedirect($client, $this->createUrl('/register/confirmed'));
|
||||
$this->assertIsRedirect($client, $this->createUrl('/register/check-email'));
|
||||
$client->followRedirect();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
return $this->loadUserFromDatabase($username);
|
||||
}
|
||||
|
||||
public function testCheckEmailWithoutEmail()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->setSystemConfiguration('user.registration', true);
|
||||
$this->request($client, '/register/check-email');
|
||||
|
||||
$this->assertIsRedirect($client, $this->createUrl('/register/'));
|
||||
$client->followRedirect();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
}
|
||||
|
||||
public function testRegisterAccount()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->createUser($client, 'example', 'register@example.com', 'test1234');
|
||||
|
||||
$content = $client->getResponse()->getContent();
|
||||
$this->assertStringContainsString('<title>Kimai – Time Tracking</title>', $content);
|
||||
$this->assertStringContainsString('<p>Congrats example, your account is now activated.</p>', $content);
|
||||
$this->assertStringContainsString('<a href="/en/homepage">', $content);
|
||||
$this->assertStringContainsString('An email has been sent to register@example.com. It contains an activation link you must click to activate your account.', $content);
|
||||
$this->assertStringContainsString('<a href="/en/login">', $content);
|
||||
}
|
||||
|
||||
public function testConfirmWithInvalidToken()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->setSystemConfiguration('user.registration', true);
|
||||
$this->request($client, '/register/confirm/1234567890');
|
||||
|
||||
$this->assertIsRedirect($client, $this->createUrl('/login'));
|
||||
$client->followRedirect();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
}
|
||||
|
||||
public function testConfirmAccount()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$user = $this->createUser($client, 'example', 'register@example.com', 'test1234');
|
||||
|
||||
$token = $user->getConfirmationToken();
|
||||
self::assertNotEmpty($token);
|
||||
self::assertFalse($user->isEnabled());
|
||||
|
||||
$this->request($client, '/register/confirm/' . $token);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/register/confirmed'));
|
||||
$client->followRedirect();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$content = $client->getResponse()->getContent();
|
||||
$this->assertStringContainsString('Congratulations example, your account is now activated.', $content);
|
||||
|
||||
$user = $this->loadUserFromDatabase('example');
|
||||
self::assertTrue($user->isEnabled());
|
||||
}
|
||||
|
||||
public function testConfirmedAnonymousRedirectsToLogin()
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->setSystemConfiguration('user.registration', true);
|
||||
$this->request($client, '/register/confirmed');
|
||||
|
||||
// AccessDeniedException redirects to login
|
||||
$this->assertIsRedirect($client, $this->createUrl('/login'));
|
||||
$client->followRedirect();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,6 +169,7 @@ class SecurityControllerTest extends ControllerBaseTest
|
||||
public function testRegisterActionWithValidationProblems(array $formData, array $validationFields)
|
||||
{
|
||||
$client = self::createClient();
|
||||
$this->setSystemConfiguration('user.registration', true);
|
||||
|
||||
$this->assertHasValidationError($client, '/register/', 'form[name=fos_user_registration_form]', $formData, $validationFields);
|
||||
}
|
||||
@@ -124,11 +187,9 @@ class SecurityControllerTest extends ControllerBaseTest
|
||||
]
|
||||
],
|
||||
[
|
||||
'#fos_user_registration_form_username',
|
||||
'#fos_user_registration_form_username',
|
||||
'#fos_user_registration_form_plainPassword_first',
|
||||
'#fos_user_registration_form_email',
|
||||
'#fos_user_registration_form_email',
|
||||
]
|
||||
],
|
||||
// invalid fields: username, password, email
|
||||
@@ -141,11 +202,9 @@ class SecurityControllerTest extends ControllerBaseTest
|
||||
]
|
||||
],
|
||||
[
|
||||
'#fos_user_registration_form_username',
|
||||
'#fos_user_registration_form_username',
|
||||
'#fos_user_registration_form_plainPassword_first',
|
||||
'#fos_user_registration_form_email',
|
||||
'#fos_user_registration_form_email',
|
||||
]
|
||||
],
|
||||
// invalid fields: password (too short)
|
||||
@@ -74,6 +74,7 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
|
||||
['form[name=system_configuration_form_timesheet]', $this->createUrl('/admin/system-config/update/timesheet')],
|
||||
['form[name=system_configuration_form_lockdown_period]', $this->createUrl('/admin/system-config/update/lockdown_period')],
|
||||
['form[name=system_configuration_form_invoice]', $this->createUrl('/admin/system-config/update/invoice')],
|
||||
['form[name=system_configuration_form_authentication]', $this->createUrl('/admin/system-config/update/authentication')],
|
||||
['form[name=system_configuration_form_rounding]', $this->createUrl('/admin/system-config/update/rounding')],
|
||||
['form[name=system_configuration_form_form_customer]', $this->createUrl('/admin/system-config/update/form_customer')],
|
||||
['form[name=system_configuration_form_form_user]', $this->createUrl('/admin/system-config/update/form_user')],
|
||||
|
||||
@@ -273,11 +273,9 @@ class UserControllerTest extends ControllerBaseTest
|
||||
]
|
||||
],
|
||||
[
|
||||
'#user_create_username',
|
||||
'#user_create_username',
|
||||
'#user_create_plainPassword_first',
|
||||
'#user_create_email',
|
||||
'#user_create_email',
|
||||
]
|
||||
],
|
||||
// invalid fields: username, password, email, enabled
|
||||
@@ -293,11 +291,9 @@ class UserControllerTest extends ControllerBaseTest
|
||||
]
|
||||
],
|
||||
[
|
||||
'#user_create_username',
|
||||
'#user_create_username',
|
||||
'#user_create_plainPassword_first',
|
||||
'#user_create_email',
|
||||
'#user_create_email',
|
||||
]
|
||||
],
|
||||
// invalid fields: password (too short)
|
||||
|
||||
@@ -179,10 +179,6 @@ class AppExtensionTest extends TestCase
|
||||
],
|
||||
'kimai.theme.select_type' => 'selectpicker',
|
||||
'kimai.theme.show_about' => true,
|
||||
'kimai.fosuser' => [
|
||||
'registration' => true,
|
||||
'password_reset' => true,
|
||||
],
|
||||
'kimai.timesheet' => [
|
||||
'mode' => 'default',
|
||||
'markdown_content' => false,
|
||||
@@ -223,31 +219,6 @@ class AppExtensionTest extends TestCase
|
||||
'days' => 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
|
||||
]
|
||||
],
|
||||
'kimai.ldap' => [
|
||||
'user' => [
|
||||
'baseDn' => null,
|
||||
'filter' => '',
|
||||
'usernameAttribute' => 'uid',
|
||||
'attributesFilter' => '(objectClass=*)',
|
||||
'attributes' => [],
|
||||
],
|
||||
'role' => [
|
||||
'baseDn' => null,
|
||||
'nameAttribute' => 'cn',
|
||||
'userDnAttribute' => 'member',
|
||||
'groups' => [],
|
||||
'usernameAttribute' => 'dn',
|
||||
],
|
||||
'connection' => [
|
||||
'baseDn' => null,
|
||||
'host' => null,
|
||||
'port' => 389,
|
||||
'useStartTls' => false,
|
||||
'useSsl' => false,
|
||||
'bindRequiresDn' => true,
|
||||
'accountFilterFormat' => '(&(uid=%s))',
|
||||
],
|
||||
],
|
||||
'kimai.permissions' => [
|
||||
'ROLE_USER' => [],
|
||||
'ROLE_TEAMLEAD' => [],
|
||||
@@ -257,8 +228,39 @@ class AppExtensionTest extends TestCase
|
||||
'kimai.i18n_domains' => []
|
||||
];
|
||||
|
||||
$kimaiLdap = [
|
||||
'activate' => false,
|
||||
'user' => [
|
||||
'baseDn' => null,
|
||||
'filter' => '',
|
||||
'usernameAttribute' => 'uid',
|
||||
'attributesFilter' => '(objectClass=*)',
|
||||
'attributes' => [],
|
||||
],
|
||||
'role' => [
|
||||
'baseDn' => null,
|
||||
'nameAttribute' => 'cn',
|
||||
'userDnAttribute' => 'member',
|
||||
'groups' => [],
|
||||
'usernameAttribute' => 'dn',
|
||||
],
|
||||
'connection' => [
|
||||
'baseDn' => null,
|
||||
'host' => null,
|
||||
'port' => 389,
|
||||
'useStartTls' => false,
|
||||
'useSsl' => false,
|
||||
'bindRequiresDn' => true,
|
||||
'accountFilterFormat' => '(&(uid=%s))',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertTrue($container->hasParameter('kimai.config'));
|
||||
|
||||
$config = $container->getParameter('kimai.config');
|
||||
$this->assertArrayHasKey('ldap', $config);
|
||||
$this->assertEquals($kimaiLdap, $config['ldap']);
|
||||
|
||||
foreach ($expected as $key => $value) {
|
||||
$this->assertTrue($container->hasParameter($key), 'Could not find config: ' . $key);
|
||||
$this->assertEquals($value, $container->getParameter($key), 'Invalid config: ' . $key);
|
||||
@@ -287,32 +289,6 @@ class AppExtensionTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testDeactivateAdditionalAuthenticationRoutes()
|
||||
{
|
||||
$minConfig = $this->getMinConfig();
|
||||
$minConfig['kimai']['user'] = [
|
||||
'registration' => false,
|
||||
'password_reset' => false,
|
||||
];
|
||||
$adminLte = [
|
||||
'adminlte_registration' => 'foo',
|
||||
'adminlte_password_reset' => 'bar',
|
||||
];
|
||||
|
||||
$container = $this->getContainer();
|
||||
$container->setParameter('admin_lte_theme.routes', $adminLte);
|
||||
|
||||
$this->extension->load($minConfig, $container);
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'adminlte_registration' => null,
|
||||
'adminlte_password_reset' => null,
|
||||
],
|
||||
$container->getParameter('admin_lte_theme.routes')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation Configuration "kimai.timesheet.duration_only" is deprecated, please remove it
|
||||
* @group legacy
|
||||
@@ -362,7 +338,9 @@ class AppExtensionTest extends TestCase
|
||||
|
||||
$this->extension->load($minConfig, $container = $this->getContainer());
|
||||
|
||||
$ldapConfig = $container->getParameter('kimai.ldap');
|
||||
$config = $container->getParameter('kimai.config');
|
||||
$ldapConfig = $config['ldap'];
|
||||
|
||||
$this->assertEquals('123123123', $ldapConfig['user']['baseDn']);
|
||||
$this->assertEquals('(..........)', $ldapConfig['user']['filter']);
|
||||
$this->assertEquals('xxx', $ldapConfig['user']['usernameAttribute']);
|
||||
@@ -385,7 +363,9 @@ class AppExtensionTest extends TestCase
|
||||
|
||||
$this->extension->load($minConfig, $container = $this->getContainer());
|
||||
|
||||
$ldapConfig = $container->getParameter('kimai.ldap');
|
||||
$config = $container->getParameter('kimai.config');
|
||||
$ldapConfig = $config['ldap'];
|
||||
|
||||
$this->assertEquals('123123123', $ldapConfig['user']['baseDn']);
|
||||
$this->assertEquals('xxx', $ldapConfig['user']['usernameAttribute']);
|
||||
$this->assertEquals('123123123', $ldapConfig['connection']['baseDn']);
|
||||
@@ -410,7 +390,9 @@ class AppExtensionTest extends TestCase
|
||||
|
||||
$this->extension->load($minConfig, $container = $this->getContainer());
|
||||
|
||||
$ldapConfig = $container->getParameter('kimai.ldap');
|
||||
$config = $container->getParameter('kimai.config');
|
||||
$ldapConfig = $config['ldap'];
|
||||
|
||||
$this->assertEquals('123123123', $ldapConfig['user']['baseDn']);
|
||||
$this->assertEquals('zzzz', $ldapConfig['user']['usernameAttribute']);
|
||||
$this->assertEquals('7658765', $ldapConfig['connection']['baseDn']);
|
||||
|
||||
@@ -73,6 +73,7 @@ class ConfigurationTest extends TestCase
|
||||
|
||||
$config = $this->getMinConfig();
|
||||
$config['ldap'] = [
|
||||
'activate' => true,
|
||||
'connection' => [
|
||||
'host' => 'foo'
|
||||
],
|
||||
@@ -231,6 +232,7 @@ class ConfigurationTest extends TestCase
|
||||
{
|
||||
$finalizedConfig = $this->getCompiledConfig($this->getMinConfig());
|
||||
$expected = [
|
||||
'activate' => false,
|
||||
'user' => [
|
||||
'baseDn' => '',
|
||||
'filter' => '',
|
||||
@@ -292,8 +294,11 @@ class ConfigurationTest extends TestCase
|
||||
'time_increment' => null,
|
||||
],
|
||||
'user' => [
|
||||
'registration' => true,
|
||||
'registration' => false,
|
||||
'password_reset' => true,
|
||||
'login' => true,
|
||||
'password_reset_retry_ttl' => 7200,
|
||||
'password_reset_token_ttl' => 86400,
|
||||
],
|
||||
'invoice' => [
|
||||
'documents' => [
|
||||
@@ -395,6 +400,7 @@ class ConfigurationTest extends TestCase
|
||||
],
|
||||
],
|
||||
'ldap' => [
|
||||
'activate' => false,
|
||||
'connection' => [
|
||||
'host' => null,
|
||||
'port' => 389,
|
||||
|
||||
@@ -14,9 +14,12 @@ use App\Entity\User;
|
||||
use App\Entity\UserPreference;
|
||||
use App\Export\Spreadsheet\ColumnDefinition;
|
||||
use App\Export\Spreadsheet\Extractor\AnnotationExtractor;
|
||||
use App\Tests\Security\TestUserEntity;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\User\EquatableInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Entity\User
|
||||
@@ -26,6 +29,9 @@ class UserTest extends TestCase
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$user = new User();
|
||||
self::assertInstanceOf(\Serializable::class, $user);
|
||||
self::assertInstanceOf(EquatableInterface::class, $user);
|
||||
self::assertInstanceOf(UserInterface::class, $user);
|
||||
$this->assertInstanceOf(ArrayCollection::class, $user->getPreferences());
|
||||
self::assertNull($user->getTitle());
|
||||
self::assertNull($user->getDisplayName());
|
||||
@@ -34,6 +40,7 @@ class UserTest extends TestCase
|
||||
self::assertNull($user->getId());
|
||||
self::assertNull($user->getApiToken());
|
||||
self::assertNull($user->getPlainApiToken());
|
||||
self::assertNull($user->getPasswordRequestedAt());
|
||||
self::assertEquals(User::DEFAULT_LANGUAGE, $user->getLocale());
|
||||
self::assertFalse($user->hasTeamAssignment());
|
||||
self::assertFalse($user->canSeeAllData());
|
||||
@@ -89,6 +96,20 @@ class UserTest extends TestCase
|
||||
self::assertEquals($date, $user->getRegisteredAt());
|
||||
}
|
||||
|
||||
public function testPasswordRequestedAt()
|
||||
{
|
||||
$date = new \DateTime('-60 minutes');
|
||||
$sut = new User();
|
||||
self::assertFalse($sut->isPasswordRequestNonExpired(3599));
|
||||
|
||||
self::assertNull($sut->getPasswordRequestedAt());
|
||||
$sut->setPasswordRequestedAt($date);
|
||||
self::assertEquals($date, $sut->getPasswordRequestedAt());
|
||||
self::assertFalse($sut->isPasswordRequestNonExpired(3599));
|
||||
// 10 seconds just to make sure it doesn't expire by accident
|
||||
self::assertTrue($sut->isPasswordRequestNonExpired(3610));
|
||||
}
|
||||
|
||||
public function testPreferences()
|
||||
{
|
||||
$user = new User();
|
||||
@@ -216,6 +237,12 @@ class UserTest extends TestCase
|
||||
self::assertFalse($sut->canSeeAllData());
|
||||
self::assertFalse($sut->isSuperAdmin());
|
||||
self::assertTrue($sut->isTeamlead());
|
||||
|
||||
$sut->setSuperAdmin(true);
|
||||
self::assertTrue($sut->isSuperAdmin());
|
||||
|
||||
$sut->setSuperAdmin(false);
|
||||
self::assertFalse($sut->isSuperAdmin());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,4 +333,62 @@ class UserTest extends TestCase
|
||||
self::assertEquals($item[1], $column->getType());
|
||||
}
|
||||
}
|
||||
|
||||
public function testEqualsTo()
|
||||
{
|
||||
$sut = new User();
|
||||
|
||||
$user = new TestUserEntity();
|
||||
self::assertFalse($sut->isEqualTo($user));
|
||||
|
||||
$sut2 = clone $sut;
|
||||
self::assertTrue($sut->isEqualTo($sut));
|
||||
self::assertTrue($sut->isEqualTo($sut2));
|
||||
self::assertTrue($sut2->isEqualTo($sut));
|
||||
|
||||
$sut->setPassword('sdfsdfsdfsdf');
|
||||
self::assertFalse($sut->isEqualTo($sut2));
|
||||
self::assertFalse($sut2->isEqualTo($sut));
|
||||
|
||||
$sut2->setPassword('sdfsdfsdfsdf');
|
||||
self::assertTrue($sut->isEqualTo($sut2));
|
||||
self::assertTrue($sut2->isEqualTo($sut));
|
||||
|
||||
$sut->setUsername('12345678');
|
||||
self::assertFalse($sut->isEqualTo($sut2));
|
||||
self::assertFalse($sut2->isEqualTo($sut));
|
||||
|
||||
$sut2->setUsername('12345678');
|
||||
self::assertTrue($sut->isEqualTo($sut2));
|
||||
self::assertTrue($sut2->isEqualTo($sut));
|
||||
}
|
||||
|
||||
public function testSerialize()
|
||||
{
|
||||
$sut = new User();
|
||||
$sut->setPassword('ABC-1234567890');
|
||||
$sut->setUsername('foo-BAR');
|
||||
$sut->setEmail('hello@world.com');
|
||||
$sut->setEnabled(false);
|
||||
|
||||
$data = serialize($sut);
|
||||
|
||||
$expected = [
|
||||
'foo-BAR',
|
||||
false,
|
||||
null,
|
||||
'hello@world.com',
|
||||
];
|
||||
|
||||
$unserialized = unserialize($data);
|
||||
|
||||
$actual = [
|
||||
$sut->getUsername(),
|
||||
$sut->isEnabled(),
|
||||
$sut->getId(),
|
||||
$sut->getEmail(),
|
||||
];
|
||||
|
||||
self::assertEquals($expected, $actual);
|
||||
}
|
||||
}
|
||||
|
||||
30
tests/Event/EmailEventTest.php
Normal file
30
tests/Event/EmailEventTest.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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\Event;
|
||||
|
||||
use App\Event\EmailEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\EmailEvent
|
||||
*/
|
||||
class EmailEventTest extends TestCase
|
||||
{
|
||||
public function testGetter()
|
||||
{
|
||||
$email = new Email();
|
||||
$email->text('sdfsdfsdfsdf');
|
||||
|
||||
$sut = new EmailEvent($email);
|
||||
|
||||
$this->assertEquals($email, $sut->getEmail());
|
||||
}
|
||||
}
|
||||
37
tests/Event/EmailPasswordResetEventTest.php
Normal file
37
tests/Event/EmailPasswordResetEventTest.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Event\EmailPasswordResetEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\EmailEvent
|
||||
* @covers \App\Event\UserEmailEvent
|
||||
* @covers \App\Event\EmailPasswordResetEvent
|
||||
*/
|
||||
class EmailPasswordResetEventTest extends TestCase
|
||||
{
|
||||
public function testGetter()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setAlias('foo');
|
||||
|
||||
$email = new Email();
|
||||
$email->text('sdfsdfsdfsdf');
|
||||
|
||||
$sut = new EmailPasswordResetEvent($user, $email);
|
||||
|
||||
self::assertSame($email, $sut->getEmail());
|
||||
self::assertSame($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
37
tests/Event/EmailSelfRegistrationEventTest.php
Normal file
37
tests/Event/EmailSelfRegistrationEventTest.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Event\EmailSelfRegistrationEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\EmailEvent
|
||||
* @covers \App\Event\UserEmailEvent
|
||||
* @covers \App\Event\EmailSelfRegistrationEvent
|
||||
*/
|
||||
class EmailSelfRegistrationEventTest extends TestCase
|
||||
{
|
||||
public function testGetter()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setAlias('foo');
|
||||
|
||||
$email = new Email();
|
||||
$email->text('sdfsdfsdfsdf');
|
||||
|
||||
$sut = new EmailSelfRegistrationEvent($user, $email);
|
||||
|
||||
self::assertSame($email, $sut->getEmail());
|
||||
self::assertSame($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
31
tests/Event/UserCreateEventTest.php
Normal file
31
tests/Event/UserCreateEventTest.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\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Event\UserCreateEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractUserEvent
|
||||
* @covers \App\Event\UserCreateEvent
|
||||
*/
|
||||
class UserCreateEventTest extends TestCase
|
||||
{
|
||||
public function testGetter()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setAlias('foo');
|
||||
|
||||
$sut = new UserCreateEvent($user);
|
||||
|
||||
$this->assertEquals($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
31
tests/Event/UserCreatePostEventTest.php
Normal file
31
tests/Event/UserCreatePostEventTest.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\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Event\UserCreatePostEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractUserEvent
|
||||
* @covers \App\Event\UserCreatePostEvent
|
||||
*/
|
||||
class UserCreatePostEventTest extends TestCase
|
||||
{
|
||||
public function testGetter()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setAlias('foo');
|
||||
|
||||
$sut = new UserCreatePostEvent($user);
|
||||
|
||||
$this->assertEquals($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
31
tests/Event/UserCreatePreEventTest.php
Normal file
31
tests/Event/UserCreatePreEventTest.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\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Event\UserCreatePreEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractUserEvent
|
||||
* @covers \App\Event\UserCreatePreEvent
|
||||
*/
|
||||
class UserCreatePreEventTest extends TestCase
|
||||
{
|
||||
public function testGetter()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setAlias('foo');
|
||||
|
||||
$sut = new UserCreatePreEvent($user);
|
||||
|
||||
$this->assertEquals($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
31
tests/Event/UserInteractiveLoginEventTest.php
Normal file
31
tests/Event/UserInteractiveLoginEventTest.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\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Event\UserInteractiveLoginEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractUserEvent
|
||||
* @covers \App\Event\UserInteractiveLoginEvent
|
||||
*/
|
||||
class UserInteractiveLoginEventTest extends TestCase
|
||||
{
|
||||
public function testGetter()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setAlias('foo');
|
||||
|
||||
$sut = new UserInteractiveLoginEvent($user);
|
||||
|
||||
$this->assertEquals($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
31
tests/Event/UserUpdatePostEventTest.php
Normal file
31
tests/Event/UserUpdatePostEventTest.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\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Event\UserUpdatePostEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractUserEvent
|
||||
* @covers \App\Event\UserUpdatePostEvent
|
||||
*/
|
||||
class UserUpdatePostEventTest extends TestCase
|
||||
{
|
||||
public function testGetter()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setAlias('foo');
|
||||
|
||||
$sut = new UserUpdatePostEvent($user);
|
||||
|
||||
$this->assertEquals($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
31
tests/Event/UserUpdatePreEventTest.php
Normal file
31
tests/Event/UserUpdatePreEventTest.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\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Event\UserUpdatePreEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractUserEvent
|
||||
* @covers \App\Event\UserUpdatePreEvent
|
||||
*/
|
||||
class UserUpdatePreEventTest extends TestCase
|
||||
{
|
||||
public function testGetter()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setAlias('foo');
|
||||
|
||||
$sut = new UserUpdatePreEvent($user);
|
||||
|
||||
$this->assertEquals($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
97
tests/EventSubscriber/EmailSubscriberTest.php
Normal file
97
tests/EventSubscriber/EmailSubscriberTest.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?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\EventSubscriber;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Event\DashboardEvent;
|
||||
use App\Event\EmailEvent;
|
||||
use App\EventSubscriber\DashboardSubscriber;
|
||||
use App\EventSubscriber\EmailSubscriber;
|
||||
use App\Mail\KimaiMailer;
|
||||
use App\Repository\ActivityRepository;
|
||||
use App\Repository\CustomerRepository;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Repository\UserRepository;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\EventSubscriber\EmailSubscriber
|
||||
*/
|
||||
class EmailSubscriberTest extends TestCase
|
||||
{
|
||||
public function testGetSubscribedEvents()
|
||||
{
|
||||
$events = EmailSubscriber::getSubscribedEvents();
|
||||
$this->assertArrayHasKey(EmailEvent::class, $events);
|
||||
$methodName = $events[EmailEvent::class][0];
|
||||
$this->assertTrue(method_exists(EmailSubscriber::class, $methodName));
|
||||
}
|
||||
|
||||
public function testSendIsTriggered()
|
||||
{
|
||||
$mailer = $this->createMock(KimaiMailer::class);
|
||||
$mailer->expects($this->once())->method('send');
|
||||
|
||||
$sut = new EmailSubscriber($mailer);
|
||||
|
||||
$event = new EmailEvent(new Email());
|
||||
|
||||
$sut->onMailEvent($event);
|
||||
}
|
||||
|
||||
public function testWithAdminUser()
|
||||
{
|
||||
$sut = $this->getSubscriber(true, 13, 28, 37, 5);
|
||||
$event = new DashboardEvent(new User());
|
||||
|
||||
$this->assertEquals(0, \count($event->getSections()));
|
||||
$sut->onDashboardEvent($event);
|
||||
|
||||
$sections = $event->getSections();
|
||||
$widgets = $sections[0]->getWidgets();
|
||||
|
||||
$this->assertEquals(1, \count($sections));
|
||||
$this->assertEquals(4, \count($widgets));
|
||||
|
||||
$this->assertEquals('stats.userTotal', $widgets[0]->getTitle());
|
||||
$this->assertEquals(13, $widgets[0]->getData());
|
||||
|
||||
$this->assertEquals('stats.customerTotal', $widgets[1]->getTitle());
|
||||
$this->assertEquals(5, $widgets[1]->getData());
|
||||
|
||||
$this->assertEquals('stats.projectTotal', $widgets[2]->getTitle());
|
||||
$this->assertEquals(37, $widgets[2]->getData());
|
||||
|
||||
$this->assertEquals('stats.activityTotal', $widgets[3]->getTitle());
|
||||
$this->assertEquals(28, $widgets[3]->getData());
|
||||
}
|
||||
|
||||
protected function getSubscriber(bool $isAdmin, int $userCount, int $activityCount, int $projectCount, int $customerCount)
|
||||
{
|
||||
$authMock = $this->getMockBuilder(AuthorizationCheckerInterface::class)->getMock();
|
||||
$authMock->method('isGranted')->willReturn($isAdmin);
|
||||
|
||||
$userMock = $this->getMockBuilder(UserRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$userMock->method('countUsersForQuery')->willReturn($userCount);
|
||||
|
||||
$projectMock = $this->getMockBuilder(ProjectRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$projectMock->method('countProjectsForQuery')->willReturn($projectCount);
|
||||
|
||||
$activityMock = $this->getMockBuilder(ActivityRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$activityMock->method('countActivitiesForQuery')->willReturn($activityCount);
|
||||
|
||||
$customerMock = $this->getMockBuilder(CustomerRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$customerMock->method('countCustomersForQuery')->willReturn($customerCount);
|
||||
|
||||
return new DashboardSubscriber($authMock, $userMock, $activityMock, $projectMock, $customerMock);
|
||||
}
|
||||
}
|
||||
76
tests/EventSubscriber/LastLoginSubscriberTest.php
Normal file
76
tests/EventSubscriber/LastLoginSubscriberTest.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?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\EventSubscriber;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Event\UserInteractiveLoginEvent;
|
||||
use App\EventSubscriber\LastLoginSubscriber;
|
||||
use App\Repository\UserRepository;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
|
||||
/**
|
||||
* @covers \App\EventSubscriber\LastLoginSubscriber
|
||||
*/
|
||||
class LastLoginSubscriberTest extends TestCase
|
||||
{
|
||||
public function testGetSubscribedEvents()
|
||||
{
|
||||
$events = LastLoginSubscriber::getSubscribedEvents();
|
||||
|
||||
$this->assertArrayHasKey(UserInteractiveLoginEvent::class, $events);
|
||||
$methodName = $events[UserInteractiveLoginEvent::class];
|
||||
$this->assertTrue(method_exists(LastLoginSubscriber::class, $methodName));
|
||||
|
||||
$this->assertArrayHasKey(SecurityEvents::INTERACTIVE_LOGIN, $events);
|
||||
$methodName = $events[SecurityEvents::INTERACTIVE_LOGIN];
|
||||
$this->assertTrue(method_exists(LastLoginSubscriber::class, $methodName));
|
||||
}
|
||||
|
||||
public function testOnImplicitLogin()
|
||||
{
|
||||
$repository = $this->createMock(UserRepository::class);
|
||||
$repository->expects($this->once())->method('saveUser');
|
||||
|
||||
$sut = new LastLoginSubscriber($repository);
|
||||
|
||||
$user = new User();
|
||||
self::assertNull($user->getLastLogin());
|
||||
|
||||
$event = new UserInteractiveLoginEvent($user);
|
||||
$sut->onImplicitLogin($event);
|
||||
self::assertNotNull($user->getLastLogin());
|
||||
}
|
||||
|
||||
public function testOnSecurityInteractiveLoginWithUser()
|
||||
{
|
||||
$repository = $this->createMock(UserRepository::class);
|
||||
$repository->expects($this->once())->method('saveUser');
|
||||
|
||||
$sut = new LastLoginSubscriber($repository);
|
||||
|
||||
$user = new User();
|
||||
self::assertNull($user->getLastLogin());
|
||||
|
||||
$event = new InteractiveLoginEvent(new Request(), new UsernamePasswordToken($user, [], 'sdf'));
|
||||
$sut->onSecurityInteractiveLogin($event);
|
||||
self::assertNotNull($user->getLastLogin());
|
||||
|
||||
$user = new User();
|
||||
self::assertNull($user->getLastLogin());
|
||||
|
||||
$event = new InteractiveLoginEvent(new Request(), new UsernamePasswordToken('foo', 'bar', 'sdf'));
|
||||
$sut->onSecurityInteractiveLogin($event);
|
||||
self::assertNull($user->getLastLogin());
|
||||
}
|
||||
}
|
||||
@@ -1,99 +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\EventSubscriber;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\EventSubscriber\RegistrationSubscriber;
|
||||
use FOS\UserBundle\Event\FormEvent;
|
||||
use FOS\UserBundle\FOSUserEvents;
|
||||
use FOS\UserBundle\Model\UserManagerInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\EventSubscriber\RegistrationSubscriber
|
||||
*/
|
||||
class RegistrationSubscriberTest extends TestCase
|
||||
{
|
||||
public function testGetSubscribedEvents()
|
||||
{
|
||||
$events = RegistrationSubscriber::getSubscribedEvents();
|
||||
$this->assertArrayHasKey(FOSUserEvents::REGISTRATION_SUCCESS, $events);
|
||||
$methodName = $events[FOSUserEvents::REGISTRATION_SUCCESS][0];
|
||||
$this->assertTrue(method_exists(RegistrationSubscriber::class, $methodName));
|
||||
|
||||
$this->assertArrayHasKey(FOSUserEvents::RESETTING_RESET_SUCCESS, $events);
|
||||
$methodName = $events[FOSUserEvents::RESETTING_RESET_SUCCESS][0];
|
||||
$this->assertTrue(method_exists(RegistrationSubscriber::class, $methodName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testRoleAssignmentForNewUser(array $existingUsers, $expectedRoles)
|
||||
{
|
||||
$user = new User();
|
||||
$user->setAlias('foo');
|
||||
$this->assertEquals([User::ROLE_USER], $user->getRoles());
|
||||
|
||||
$userManager = $this->getMockBuilder(UserManagerInterface::class)->getMock();
|
||||
$userManager->method('findUsers')->willReturn($existingUsers);
|
||||
|
||||
$form = $this->getMockBuilder(FormInterface::class)->getMock();
|
||||
$form->method('getData')->willReturn($user);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->expects($this->any())->method('getLocale')->willReturn('ru');
|
||||
|
||||
$event = new FormEvent($form, $request);
|
||||
|
||||
$sut = new RegistrationSubscriber($userManager, $this->createMock(UrlGeneratorInterface::class));
|
||||
$sut->onRegistrationSuccess($event);
|
||||
|
||||
$this->assertEquals($expectedRoles, $user->getRoles());
|
||||
$this->assertEquals('ru', $user->getLanguage());
|
||||
}
|
||||
|
||||
public function getTestData()
|
||||
{
|
||||
return [
|
||||
// NewFirstUserGetsSuperAdminRole
|
||||
[[], [User::ROLE_SUPER_ADMIN, User::ROLE_USER]],
|
||||
// NewUserGetUserRole
|
||||
[[new User()], [User::ROLE_USER]],
|
||||
];
|
||||
}
|
||||
|
||||
public function testResetting()
|
||||
{
|
||||
$userManager = $this->createMock(UserManagerInterface::class);
|
||||
$form = $this->createMock(FormInterface::class);
|
||||
$request = $this->createMock(Request::class);
|
||||
$router = $this->createMock(UrlGeneratorInterface::class);
|
||||
|
||||
$router->expects($this->any())->method('generate')->willReturnArgument(0);
|
||||
$request->expects($this->any())->method('getLocale')->willReturn('ru');
|
||||
|
||||
$event = new FormEvent($form, $request);
|
||||
self::assertNull($event->getResponse());
|
||||
|
||||
$sut = new RegistrationSubscriber($userManager, $router);
|
||||
$sut->onResettingSuccess($event);
|
||||
|
||||
self::assertInstanceOf(RedirectResponse::class, $event->getResponse());
|
||||
|
||||
/** @var RedirectResponse $response */
|
||||
$response = $event->getResponse();
|
||||
self::assertEquals('my_profile', $response->getTargetUrl());
|
||||
}
|
||||
}
|
||||
@@ -1,92 +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\EventSubscriber;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\EventSubscriber\ResetPasswordSubscriber;
|
||||
use App\Tests\Security\TestUserEntity;
|
||||
use FOS\UserBundle\Event\GetResponseNullableUserEvent;
|
||||
use FOS\UserBundle\FOSUserEvents;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
/**
|
||||
* @covers \App\EventSubscriber\ResetPasswordSubscriber
|
||||
*/
|
||||
class ResetPasswordSubscriberTest extends TestCase
|
||||
{
|
||||
public function testGetSubscribedEvents()
|
||||
{
|
||||
$events = ResetPasswordSubscriber::getSubscribedEvents();
|
||||
self::assertCount(1, $events);
|
||||
$this->assertArrayHasKey(FOSUserEvents::RESETTING_SEND_EMAIL_INITIALIZE, $events);
|
||||
$methodName = $events[FOSUserEvents::RESETTING_SEND_EMAIL_INITIALIZE][0];
|
||||
$this->assertTrue(method_exists(ResetPasswordSubscriber::class, $methodName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testUnknownUserTypeIsIgnored()
|
||||
{
|
||||
$user = new TestUserEntity();
|
||||
$user->setUsername('foo@bar');
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$event = new GetResponseNullableUserEvent($user, $request);
|
||||
|
||||
$sut = new ResetPasswordSubscriber();
|
||||
$sut->onInitializeResetPassword($event);
|
||||
|
||||
self::assertNull($event->getResponse());
|
||||
}
|
||||
|
||||
public function testInternalAuthTypeIsIgnored()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setUsername('foo@bar');
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$event = new GetResponseNullableUserEvent($user, $request);
|
||||
|
||||
$sut = new ResetPasswordSubscriber();
|
||||
$sut->onInitializeResetPassword($event);
|
||||
|
||||
self::assertNull($event->getResponse());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getAuthTypeData
|
||||
*/
|
||||
public function testNonInternalAuthTypeThrowsAccessDeniedException(string $authType)
|
||||
{
|
||||
$this->expectException(AccessDeniedHttpException::class);
|
||||
$this->expectExceptionMessage(sprintf('The user "foo@bar" tried to reset the password, but it is registered as "%s" auth-type.', $authType));
|
||||
|
||||
$user = new User();
|
||||
$user->setUsername('foo@bar');
|
||||
$user->setAuth($authType);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$event = new GetResponseNullableUserEvent($user, $request);
|
||||
|
||||
$sut = new ResetPasswordSubscriber();
|
||||
$sut->onInitializeResetPassword($event);
|
||||
}
|
||||
|
||||
public function getAuthTypeData()
|
||||
{
|
||||
return [
|
||||
[User::AUTH_SAML],
|
||||
[User::AUTH_LDAP],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ use App\Form\Model\SystemConfiguration;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Form\Model\Configuration
|
||||
* @covers \App\Form\Model\SystemConfiguration
|
||||
*/
|
||||
class SystemConfigurationTest extends TestCase
|
||||
@@ -44,5 +45,16 @@ class SystemConfigurationTest extends TestCase
|
||||
|
||||
self::assertInstanceOf(SystemConfiguration::class, $sut->addConfiguration($config));
|
||||
self::assertEquals([$config, $config, $config], $sut->getConfiguration());
|
||||
|
||||
$config = new Configuration();
|
||||
$config->setName('foo');
|
||||
$sut->addConfiguration($config);
|
||||
|
||||
$config2 = new Configuration();
|
||||
$config2->setName('bar');
|
||||
$sut->addConfiguration($config2);
|
||||
|
||||
self::assertSame($config, $sut->getConfigurationByName('foo'));
|
||||
self::assertNull($sut->getConfigurationByName('bar2'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
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;
|
||||
@@ -26,10 +28,33 @@ use Symfony\Component\Security\Core\User\UserChecker;
|
||||
*/
|
||||
class LdapAuthenticationProviderTest extends TestCase
|
||||
{
|
||||
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 = new LdapConfiguration([]);
|
||||
$config = $this->getConfiguration(false);
|
||||
$userProvider = new LdapUserProvider($manager);
|
||||
$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 = new LdapUserProvider($manager);
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
@@ -47,7 +72,7 @@ class LdapAuthenticationProviderTest extends TestCase
|
||||
$this->expectExceptionMessage('The password in the token is empty. Check `erase_credentials` in your `security.yaml`');
|
||||
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration([]);
|
||||
$config = $this->getConfiguration(true);
|
||||
$userProvider = new LdapUserProvider($manager);
|
||||
$providerKey = 'secured_area';
|
||||
$userChecker = new UserChecker();
|
||||
@@ -66,7 +91,7 @@ class LdapAuthenticationProviderTest extends TestCase
|
||||
|
||||
$user = (new User())->setUsername('foo')->setEnabled(true);
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration([]);
|
||||
$config = $this->getConfiguration(true);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->onlyMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->once())->method('loadUserByUsername')->willReturn($user);
|
||||
$providerKey = 'secured_area';
|
||||
@@ -86,7 +111,7 @@ class LdapAuthenticationProviderTest extends TestCase
|
||||
$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 = new LdapConfiguration([]);
|
||||
$config = $this->getConfiguration(true);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->onlyMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->once())->method('loadUserByUsername')->willReturn($user);
|
||||
$providerKey = 'secured_area';
|
||||
@@ -106,7 +131,7 @@ class LdapAuthenticationProviderTest extends TestCase
|
||||
$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 = new LdapConfiguration([]);
|
||||
$config = $this->getConfiguration(true);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->onlyMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->never())->method('loadUserByUsername');
|
||||
$providerKey = 'secured_area';
|
||||
@@ -127,7 +152,7 @@ class LdapAuthenticationProviderTest extends TestCase
|
||||
$manager->expects($this->once())->method('updateUser')->willReturnCallback(function ($updateUser) use ($user) {
|
||||
self::assertSame($updateUser, $user);
|
||||
});
|
||||
$config = new LdapConfiguration([]);
|
||||
$config = $this->getConfiguration(true);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->onlyMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->once())->method('loadUserByUsername')->willReturn($user);
|
||||
$providerKey = 'secured_area';
|
||||
@@ -149,7 +174,7 @@ class LdapAuthenticationProviderTest extends TestCase
|
||||
$manager->expects($this->once())->method('updateUser')->willReturnCallback(function ($updateUser) use ($user) {
|
||||
self::assertSame($updateUser, $user);
|
||||
});
|
||||
$config = new LdapConfiguration([]);
|
||||
$config = $this->getConfiguration(true);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->onlyMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->never())->method('loadUserByUsername');
|
||||
$providerKey = 'secured_area';
|
||||
@@ -168,7 +193,7 @@ class LdapAuthenticationProviderTest extends TestCase
|
||||
$this->expectExceptionMessage('blub foo bar');
|
||||
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration([]);
|
||||
$config = $this->getConfiguration(true);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->onlyMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->once())->method('loadUserByUsername')->willThrowException(new UsernameNotFoundException('blub foo bar'));
|
||||
$providerKey = 'secured_area';
|
||||
@@ -187,7 +212,7 @@ class LdapAuthenticationProviderTest extends TestCase
|
||||
$this->expectExceptionCode('1234');
|
||||
|
||||
$manager = $this->getMockBuilder(LdapManager::class)->disableOriginalConstructor()->getMock();
|
||||
$config = new LdapConfiguration([]);
|
||||
$config = $this->getConfiguration(true);
|
||||
$userProvider = $this->getMockBuilder(LdapUserProvider::class)->disableOriginalConstructor()->onlyMethods(['loadUserByUsername'])->getMock();
|
||||
$userProvider->expects($this->once())->method('loadUserByUsername')->willThrowException(new \Exception('server away', 1234));
|
||||
$providerKey = 'secured_area';
|
||||
|
||||
@@ -10,11 +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 PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -39,7 +41,7 @@ class LdapManagerTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
$config = new LdapConfiguration([
|
||||
$conf = [
|
||||
'user' => [
|
||||
'attributes' => [],
|
||||
'filter' => '(&(objectClass=inetOrgPerson))',
|
||||
@@ -48,7 +50,9 @@ class LdapManagerTest extends TestCase
|
||||
'baseDn' => 'ou=users, dc=kimai, dc=org',
|
||||
],
|
||||
'role' => $roleConfig,
|
||||
]);
|
||||
];
|
||||
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['ldap' => $conf]);
|
||||
$config = new LdapConfiguration($systemConfig);
|
||||
|
||||
$roles = [
|
||||
'ROLE_TEAMLEAD' => ['ROLE_USER'],
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
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;
|
||||
|
||||
@@ -22,7 +24,8 @@ class LdapUserHydratorTest extends TestCase
|
||||
{
|
||||
public function testEmptyHydrate()
|
||||
{
|
||||
$config = new LdapConfiguration([
|
||||
$ldapConfig = [
|
||||
'activate' => true,
|
||||
'connection' => [
|
||||
'host' => '1.1.1.1'
|
||||
],
|
||||
@@ -31,7 +34,10 @@ class LdapUserHydratorTest extends TestCase
|
||||
'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']);
|
||||
@@ -42,7 +48,7 @@ class LdapUserHydratorTest extends TestCase
|
||||
|
||||
public function testHydrate()
|
||||
{
|
||||
$config = new LdapConfiguration([
|
||||
$ldapConfig = [
|
||||
'connection' => [
|
||||
'host' => '1.1.1.1'
|
||||
],
|
||||
@@ -58,7 +64,9 @@ class LdapUserHydratorTest extends TestCase
|
||||
]
|
||||
],
|
||||
'role' => [],
|
||||
]);
|
||||
];
|
||||
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['ldap' => $ldapConfig]);
|
||||
$config = new LdapConfiguration($systemConfig);
|
||||
|
||||
$ldapEntry = [
|
||||
'uid' => ['Karl-Heinz'],
|
||||
@@ -85,7 +93,7 @@ class LdapUserHydratorTest extends TestCase
|
||||
|
||||
public function testHydrateUser()
|
||||
{
|
||||
$config = new LdapConfiguration([
|
||||
$ldapConfig = [
|
||||
'connection' => [
|
||||
'host' => '1.1.1.1'
|
||||
],
|
||||
@@ -100,7 +108,9 @@ class LdapUserHydratorTest extends TestCase
|
||||
]
|
||||
],
|
||||
'role' => [],
|
||||
]);
|
||||
];
|
||||
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['ldap' => $ldapConfig]);
|
||||
$config = new LdapConfiguration($systemConfig);
|
||||
|
||||
$ldapEntry = [
|
||||
'uid' => ['Karl-Heinz'],
|
||||
@@ -131,7 +141,7 @@ class LdapUserHydratorTest extends TestCase
|
||||
|
||||
public function testHydrateRoles()
|
||||
{
|
||||
$config = new LdapConfiguration([
|
||||
$ldapConfig = [
|
||||
'user' => [
|
||||
'attributes' => []
|
||||
],
|
||||
@@ -145,7 +155,9 @@ class LdapUserHydratorTest extends TestCase
|
||||
['ldap_value' => 'group4', 'role' => 'ROLE_SUPER_ADMIN'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
];
|
||||
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['ldap' => $ldapConfig]);
|
||||
$config = new LdapConfiguration($systemConfig);
|
||||
|
||||
$ldapGroups = [
|
||||
// ROLE_TEAMLEAD
|
||||
|
||||
@@ -1,67 +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\Mail;
|
||||
|
||||
use App\Configuration\MailConfiguration;
|
||||
use App\Entity\User;
|
||||
use App\Mail\KimaiMailer;
|
||||
use App\Mail\UserMails;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Mail\UserMails
|
||||
*/
|
||||
class UserMailsTest extends TestCase
|
||||
{
|
||||
public function getSut(): UserMails
|
||||
{
|
||||
$config = $this->createMock(MailConfiguration::class);
|
||||
$config->expects($this->any())->method('getFromAddress')->willReturn('zippel@example.com');
|
||||
$mailer = $this->createMock(MailerInterface::class);
|
||||
$mailer->expects($this->once())->method('send')->willReturnCallback(function (Email $message) {
|
||||
self::assertEquals([new Address('zippel@example.com')], $message->getFrom());
|
||||
self::assertEquals([new Address('foo@example.com')], $message->getTo());
|
||||
self::assertEquals('foo', $message->getSubject());
|
||||
});
|
||||
$kimaiMailer = new KimaiMailer($config, $mailer);
|
||||
$router = $this->createMock(UrlGeneratorInterface::class);
|
||||
$translator = $this->createMock(TranslatorInterface::class);
|
||||
$translator->expects($this->any())->method('trans')->willReturn('foo');
|
||||
|
||||
return new UserMails($kimaiMailer, $router, $translator);
|
||||
}
|
||||
|
||||
public function testSendConfirmationEmailMessage()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setUsername('Testing');
|
||||
$user->setEmail('foo@example.com');
|
||||
$user->setAlias('Super User');
|
||||
|
||||
$mailer = $this->getSut();
|
||||
$mailer->sendConfirmationEmailMessage($user);
|
||||
}
|
||||
|
||||
public function testSendResettingEmailMessage()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setUsername('Testing');
|
||||
$user->setEmail('foo@example.com');
|
||||
$user->setAlias('Super User');
|
||||
|
||||
$mailer = $this->getSut();
|
||||
$mailer->sendResettingEmailMessage($user);
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,17 @@
|
||||
|
||||
namespace App\Tests\Mocks\Saml;
|
||||
|
||||
use App\Saml\SamlAuth;
|
||||
use App\Configuration\SamlConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Saml\SamlAuthFactory;
|
||||
use App\Tests\Configuration\TestConfigLoader;
|
||||
use App\Tests\Mocks\AbstractMockFactory;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
class SamlAuthFactory extends AbstractMockFactory
|
||||
class SamlAuthFactoryFactory extends AbstractMockFactory
|
||||
{
|
||||
public function create(?array $connection = null, bool $fromTrustedProxy = false): SamlAuth
|
||||
public function create(?array $connection = null, bool $fromTrustedProxy = false): SamlAuthFactory
|
||||
{
|
||||
if (null === $connection) {
|
||||
$connection = [
|
||||
@@ -84,6 +87,10 @@ class SamlAuthFactory extends AbstractMockFactory
|
||||
$requestStack = new RequestStack();
|
||||
$requestStack->push($request);
|
||||
|
||||
return new SamlAuth($requestStack, $connection);
|
||||
$configuration = new SystemConfiguration(new TestConfigLoader([]), [
|
||||
'saml' => ['connection' => $connection]
|
||||
]);
|
||||
|
||||
return new SamlAuthFactory($requestStack, new SamlConfiguration($configuration));
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,14 @@ namespace App\Tests\Saml\Logout;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Saml\Logout\SamlLogoutHandler;
|
||||
use App\Saml\SamlAuth;
|
||||
use Hslavich\OneloginSamlBundle\Security\Authentication\Token\SamlToken;
|
||||
use App\Saml\SamlAuthFactory;
|
||||
use App\Saml\Token\SamlToken;
|
||||
use OneLogin\Saml2\Auth;
|
||||
use OneLogin\Saml2\Error;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
|
||||
/**
|
||||
* @covers \App\Saml\Logout\SamlLogoutHandler
|
||||
@@ -25,7 +27,7 @@ class SamlLogoutHandlerTest extends TestCase
|
||||
{
|
||||
public function testLogout()
|
||||
{
|
||||
$auth = $this->getMockBuilder(SamlAuth::class)->disableOriginalConstructor()->getMock();
|
||||
$auth = $this->getMockBuilder(Auth::class)->disableOriginalConstructor()->getMock();
|
||||
$auth->expects($this->once())->method('processSLO')->willThrowException(new Error('blub'));
|
||||
$auth->expects($this->once())->method('getSLOurl')->willReturn('');
|
||||
|
||||
@@ -33,13 +35,33 @@ class SamlLogoutHandlerTest extends TestCase
|
||||
$response = new Response();
|
||||
$token = new SamlToken([]);
|
||||
|
||||
$sut = new SamlLogoutHandler($auth);
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
$factory->expects($this->once())->method('create')->willReturn($auth);
|
||||
|
||||
$sut = new SamlLogoutHandler($factory);
|
||||
$sut->logout($request, $response, $token);
|
||||
}
|
||||
|
||||
public function testLogoutWithWrongTokenWillNotCallMethods()
|
||||
{
|
||||
$auth = $this->getMockBuilder(Auth::class)->disableOriginalConstructor()->getMock();
|
||||
$auth->expects($this->never())->method('processSLO');
|
||||
$auth->expects($this->never())->method('getSLOurl');
|
||||
|
||||
$request = new Request();
|
||||
$response = new Response();
|
||||
$token = new UsernamePasswordToken(new User(), [], 'test');
|
||||
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
$factory->expects($this->never())->method('create');
|
||||
|
||||
$sut = new SamlLogoutHandler($factory);
|
||||
$sut->logout($request, $response, $token);
|
||||
}
|
||||
|
||||
public function testLogoutWithLogoutUrl()
|
||||
{
|
||||
$auth = $this->getMockBuilder(SamlAuth::class)->disableOriginalConstructor()->getMock();
|
||||
$auth = $this->getMockBuilder(Auth::class)->disableOriginalConstructor()->getMock();
|
||||
$auth->expects($this->once())->method('processSLO')->willThrowException(new Error('blub'));
|
||||
$auth->expects($this->once())->method('getSLOurl')->willReturn('/logout');
|
||||
$auth->expects($this->once())->method('logout')->willReturnCallback(function () {
|
||||
@@ -56,7 +78,10 @@ class SamlLogoutHandlerTest extends TestCase
|
||||
$token->setUser((new User())->setUsername('tony'));
|
||||
$token->setAttribute('sessionIndex', 'foo-bar');
|
||||
|
||||
$sut = new SamlLogoutHandler($auth);
|
||||
$factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock();
|
||||
$factory->expects($this->once())->method('create')->willReturn($auth);
|
||||
|
||||
$sut = new SamlLogoutHandler($factory);
|
||||
$sut->logout($request, $response, $token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,16 @@
|
||||
|
||||
namespace App\Tests\Saml\Provider;
|
||||
|
||||
use App\Configuration\SamlConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use App\Saml\Provider\SamlProvider;
|
||||
use App\Saml\SamlTokenFactory;
|
||||
use App\Saml\Token\SamlToken;
|
||||
use App\Saml\User\SamlUserFactory;
|
||||
use App\Security\DoctrineUserProvider;
|
||||
use Hslavich\OneloginSamlBundle\Security\Authentication\Token\SamlToken;
|
||||
use App\Tests\Configuration\TestConfigLoader;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
@@ -27,7 +30,7 @@ use Symfony\Component\Security\Core\User\ChainUserProvider;
|
||||
*/
|
||||
class SamlProviderTest extends TestCase
|
||||
{
|
||||
protected function getSamlProvider($mapping = null, $loadUser = false, ?SamlUserFactory $userFactory = null): SamlProvider
|
||||
protected function getSamlProvider(array $mapping = null, ?User $user = null, ?SamlUserFactory $userFactory = null): SamlProvider
|
||||
{
|
||||
if (null === $mapping) {
|
||||
$mapping = [
|
||||
@@ -43,15 +46,21 @@ class SamlProviderTest extends TestCase
|
||||
}
|
||||
|
||||
if (null === $userFactory) {
|
||||
$userFactory = new SamlUserFactory($mapping);
|
||||
$configuration = new SystemConfiguration(new TestConfigLoader([]), [
|
||||
'saml' => $mapping
|
||||
]);
|
||||
|
||||
$userFactory = new SamlUserFactory(new SamlConfiguration($configuration));
|
||||
}
|
||||
|
||||
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['saml' => ['activate' => true]]);
|
||||
|
||||
$repository = $this->getMockBuilder(UserRepository::class)->disableOriginalConstructor()->getMock();
|
||||
if ($loadUser !== false) {
|
||||
$repository->expects($this->once())->method('loadUserByUsername')->willReturn($loadUser);
|
||||
if ($user !== null) {
|
||||
$repository->expects($this->once())->method('loadUserByUsername')->willReturn($user);
|
||||
}
|
||||
$userProvider = new ChainUserProvider([new DoctrineUserProvider($repository)]);
|
||||
$provider = new SamlProvider($repository, $userProvider, new SamlTokenFactory(), $userFactory);
|
||||
$provider = new SamlProvider($repository, $userProvider, new SamlTokenFactory(), $userFactory, $systemConfig);
|
||||
|
||||
return $provider;
|
||||
}
|
||||
|
||||
@@ -1,33 +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\Saml;
|
||||
|
||||
use App\Tests\Mocks\Saml\SamlAuthFactory;
|
||||
use OneLogin\Saml2\Utils;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Saml\SamlAuth
|
||||
*/
|
||||
class SamlAuthTest extends TestCase
|
||||
{
|
||||
public function testCreateToken()
|
||||
{
|
||||
$previous = Utils::getProxyVars();
|
||||
self::assertFalse($previous);
|
||||
|
||||
$sut = (new SamlAuthFactory($this))->create(null, true);
|
||||
|
||||
$current = Utils::getProxyVars();
|
||||
self::assertTrue($current);
|
||||
|
||||
Utils::setProxyVars($previous);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace App\Tests\Saml;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Saml\SamlTokenFactory;
|
||||
use Hslavich\OneloginSamlBundle\Security\Authentication\Token\SamlToken;
|
||||
use App\Saml\Token\SamlToken;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Saml\Security;
|
||||
|
||||
use App\Saml\Security\SamlAuthenticationSuccessHandler;
|
||||
use Hslavich\OneloginSamlBundle\Security\Authentication\Token\SamlToken;
|
||||
use App\Saml\Token\SamlToken;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
|
||||
28
tests/Saml/Token/SamlTokenTest.php
Normal file
28
tests/Saml/Token/SamlTokenTest.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\Saml\Token;
|
||||
|
||||
use App\Saml\Token\SamlToken;
|
||||
use App\Saml\Token\SamlTokenInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Saml\Token\SamlToken
|
||||
*/
|
||||
class SamlTokenTest extends TestCase
|
||||
{
|
||||
public function testCreateToken()
|
||||
{
|
||||
$sut = new SamlToken();
|
||||
|
||||
self::assertInstanceOf(SamlTokenInterface::class, $sut);
|
||||
self::assertNull($sut->getCredentials());
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,12 @@
|
||||
|
||||
namespace App\Tests\Saml\User;
|
||||
|
||||
use App\Configuration\SamlConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\User;
|
||||
use App\Saml\Token\SamlToken;
|
||||
use App\Saml\User\SamlUserFactory;
|
||||
use Hslavich\OneloginSamlBundle\Security\Authentication\Token\SamlToken;
|
||||
use App\Tests\Configuration\TestConfigLoader;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@@ -19,6 +22,15 @@ use PHPUnit\Framework\TestCase;
|
||||
*/
|
||||
class SamlUserFactoryTest extends TestCase
|
||||
{
|
||||
private function createUserFactory(array $saml): SamlUserFactory
|
||||
{
|
||||
$configuration = new SystemConfiguration(new TestConfigLoader([]), [
|
||||
'saml' => $saml
|
||||
]);
|
||||
|
||||
return new SamlUserFactory(new SamlConfiguration($configuration));
|
||||
}
|
||||
|
||||
public function testCreateUserThrowsExceptionOnMissingAttribute()
|
||||
{
|
||||
$this->expectException(\RuntimeException::class);
|
||||
@@ -42,7 +54,7 @@ class SamlUserFactoryTest extends TestCase
|
||||
$token = new SamlToken();
|
||||
$token->setAttributes($attributes);
|
||||
|
||||
$sut = new SamlUserFactory($mapping);
|
||||
$sut = $this->createUserFactory($mapping);
|
||||
$user = $sut->createUser($token);
|
||||
}
|
||||
|
||||
@@ -68,7 +80,7 @@ class SamlUserFactoryTest extends TestCase
|
||||
$token = new SamlToken();
|
||||
$token->setAttributes($attributes);
|
||||
|
||||
$sut = new SamlUserFactory($mapping);
|
||||
$sut = $this->createUserFactory($mapping);
|
||||
$user = $sut->createUser($token);
|
||||
}
|
||||
|
||||
@@ -95,7 +107,7 @@ class SamlUserFactoryTest extends TestCase
|
||||
$token = new SamlToken();
|
||||
$token->setAttributes($attributes);
|
||||
|
||||
$sut = new SamlUserFactory($mapping);
|
||||
$sut = $this->createUserFactory($mapping);
|
||||
$user = $sut->createUser($token);
|
||||
}
|
||||
|
||||
@@ -132,7 +144,7 @@ class SamlUserFactoryTest extends TestCase
|
||||
$token->setUser('foo@example.com');
|
||||
$token->setAttributes($attributes);
|
||||
|
||||
$sut = new SamlUserFactory($mapping);
|
||||
$sut = $this->createUserFactory($mapping);
|
||||
$user = $sut->createUser($token);
|
||||
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
@@ -170,7 +182,7 @@ class SamlUserFactoryTest extends TestCase
|
||||
$token->setUser('foo@example.com');
|
||||
$token->setAttributes($attributes);
|
||||
|
||||
$sut = new SamlUserFactory($mapping);
|
||||
$sut = $this->createUserFactory($mapping);
|
||||
$user = $sut->createUser($token);
|
||||
|
||||
self::assertInstanceOf(User::class, $user);
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace App\Tests\Security;
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use App\Security\DoctrineUserProvider;
|
||||
use Hslavich\OneloginSamlBundle\Security\User\SamlUserInterface;
|
||||
use KevinPapst\AdminLTEBundle\Model\UserInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
||||
@@ -59,8 +58,6 @@ class DoctrineUserProviderTest extends TestCase
|
||||
self::assertTrue($sut->supportsClass(User::class));
|
||||
self::assertTrue($sut->supportsClass('App\Entity\User'));
|
||||
self::assertFalse($sut->supportsClass(UserInterface::class));
|
||||
self::assertFalse($sut->supportsClass(SamlUserInterface::class));
|
||||
self::assertFalse($sut->supportsClass(\FOS\UserBundle\Model\User::class));
|
||||
self::assertFalse($sut->supportsClass(TestUserEntity::class));
|
||||
}
|
||||
|
||||
@@ -70,7 +67,6 @@ class DoctrineUserProviderTest extends TestCase
|
||||
$this->expectExceptionMessage('Expected an instance of App\Entity\User, but got "App\Tests\Security\TestUserEntity".');
|
||||
|
||||
$user = new TestUserEntity();
|
||||
$user->setUsername('foobar');
|
||||
|
||||
$repository = $this->getMockBuilder(UserRepository::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
|
||||
@@ -9,8 +9,31 @@
|
||||
|
||||
namespace App\Tests\Security;
|
||||
|
||||
use FOS\UserBundle\Model\User;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
class TestUserEntity extends User
|
||||
class TestUserEntity implements UserInterface
|
||||
{
|
||||
public function getRoles()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getPassword()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getSalt()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getUsername()
|
||||
{
|
||||
return 'foo';
|
||||
}
|
||||
|
||||
public function eraseCredentials()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
75
tests/Security/TokenAuthenticatorTest.php
Normal file
75
tests/Security/TokenAuthenticatorTest.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?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\Security;
|
||||
|
||||
use App\Security\TokenAuthenticator;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Security\TokenAuthenticator
|
||||
*/
|
||||
class TokenAuthenticatorTest extends TestCase
|
||||
{
|
||||
public function testRememberMe()
|
||||
{
|
||||
$factory = $this->createMock(EncoderFactoryInterface::class);
|
||||
$sut = new TokenAuthenticator($factory);
|
||||
|
||||
self::assertFalse($sut->supportsRememberMe());
|
||||
}
|
||||
|
||||
public function testSupports()
|
||||
{
|
||||
$factory = $this->createMock(EncoderFactoryInterface::class);
|
||||
$sut = new TokenAuthenticator($factory);
|
||||
|
||||
$request = new Request([], [], [], [], [], ['REQUEST_URI' => 'dfghj/api/doc/dfghj']);
|
||||
self::assertFalse($sut->supports($request));
|
||||
|
||||
$request = new Request([], [], [], [], [], ['REQUEST_URI' => '/api/fooo']);
|
||||
self::assertTrue($sut->supports($request));
|
||||
|
||||
$request = new Request([], [], [], [], [], ['REQUEST_URI' => '/api/fooo', 'HTTP_X-AUTH-SESSION' => true]);
|
||||
self::assertFalse($sut->supports($request));
|
||||
}
|
||||
|
||||
public function testGetPassword()
|
||||
{
|
||||
$factory = $this->createMock(EncoderFactoryInterface::class);
|
||||
$sut = new TokenAuthenticator($factory);
|
||||
|
||||
self::assertNull($sut->getPassword('asdfgh'));
|
||||
self::assertNull($sut->getPassword(null));
|
||||
self::assertNull($sut->getPassword([]));
|
||||
self::assertNull($sut->getPassword(['password' => '1234567890']));
|
||||
self::assertNull($sut->getPassword(['token' => null]));
|
||||
self::assertNull($sut->getPassword(['token' => 0]));
|
||||
self::assertNull($sut->getPassword(['token' => '']));
|
||||
self::assertNull($sut->getPassword(['token' => false]));
|
||||
self::assertEquals('foo-bar', $sut->getPassword(['token' => 'foo-bar']));
|
||||
}
|
||||
|
||||
public function testGetCredentials()
|
||||
{
|
||||
$factory = $this->createMock(EncoderFactoryInterface::class);
|
||||
$sut = new TokenAuthenticator($factory);
|
||||
|
||||
$request = new Request([], [], [], [], [], ['REQUEST_URI' => '/api/fooo', 'HTTP_X-AUTH-SESSION' => true]);
|
||||
self::assertEquals(['user' => null, 'token' => null], $sut->getCredentials($request));
|
||||
|
||||
$request = new Request([], [], [], [], [], ['REQUEST_URI' => '/api/fooo', 'HTTP_X-AUTH-USER' => 'foo']);
|
||||
self::assertEquals(['user' => 'foo', 'token' => null], $sut->getCredentials($request));
|
||||
|
||||
$request = new Request([], [], [], [], [], ['REQUEST_URI' => '/api/fooo', 'HTTP_X-AUTH-USER' => 'foo', 'HTTP_X-AUTH-TOKEN' => 'bar']);
|
||||
self::assertEquals(['user' => 'foo', 'token' => 'bar'], $sut->getCredentials($request));
|
||||
}
|
||||
}
|
||||
98
tests/Validator/Constraints/UserValidatorTest.php
Normal file
98
tests/Validator/Constraints/UserValidatorTest.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?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\Validator\Constraints;
|
||||
|
||||
use App\Entity\User as UserEntity;
|
||||
use App\Tests\Security\TestUserEntity;
|
||||
use App\User\UserService;
|
||||
use App\Validator\Constraints\User;
|
||||
use App\Validator\Constraints\UserValidator;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Validator\Constraints\UserValidator
|
||||
*/
|
||||
class UserValidatorTest extends ConstraintValidatorTestCase
|
||||
{
|
||||
protected function createValidator()
|
||||
{
|
||||
$userService = $this->createMock(UserService::class);
|
||||
|
||||
return new UserValidator($userService);
|
||||
}
|
||||
|
||||
public function testConstraintIsInvalid()
|
||||
{
|
||||
$this->expectException(UnexpectedTypeException::class);
|
||||
|
||||
$this->validator->validate('foo', new NotBlank());
|
||||
}
|
||||
|
||||
public function testNullIsValid()
|
||||
{
|
||||
$this->validator->validate(null, new User(['message' => 'myMessage']));
|
||||
|
||||
$this->assertNoViolation();
|
||||
}
|
||||
|
||||
public function testNonUserIsValid()
|
||||
{
|
||||
$this->validator->validate(new TestUserEntity(), new User(['message' => 'myMessage']));
|
||||
|
||||
$this->assertNoViolation();
|
||||
}
|
||||
|
||||
public function testEmptyUserIsValid()
|
||||
{
|
||||
$this->validator->validate(new UserEntity(), new User(['message' => 'myMessage']));
|
||||
|
||||
$this->assertNoViolation();
|
||||
}
|
||||
|
||||
public function testUserIsValidWithEmptyRepository()
|
||||
{
|
||||
$user = new UserEntity();
|
||||
$user->setUsername('foo');
|
||||
$user->setEmail('foo@example.com');
|
||||
|
||||
$this->validator->validate($user, new User(['message' => 'myMessage']));
|
||||
|
||||
$this->assertNoViolation();
|
||||
}
|
||||
|
||||
public function testUserIsInvalidWithRepository()
|
||||
{
|
||||
$existing = $this->createMock(UserEntity::class);
|
||||
$existing->expects($this->exactly(2))->method('getId')->willReturn(123);
|
||||
|
||||
$userService = $this->createMock(UserService::class);
|
||||
$userService->expects($this->once())->method('findUserByEmail')->willReturn($existing);
|
||||
$userService->expects($this->once())->method('findUserByName')->willReturn($existing);
|
||||
|
||||
$this->validator = new UserValidator($userService);
|
||||
$this->validator->initialize($this->context);
|
||||
|
||||
$user = new UserEntity();
|
||||
$user->setUsername('foo');
|
||||
$user->setEmail('foo@example.com');
|
||||
|
||||
$this->validator->validate($user, new User());
|
||||
|
||||
$this->buildViolation('The email is already used.')
|
||||
->atPath('property.path.email')
|
||||
->setCode(User::USER_EXISTING_EMAIL)
|
||||
->buildNextViolation('The username is already used.')
|
||||
->atPath('property.path.username')
|
||||
->setCode(User::USER_EXISTING_NAME)
|
||||
->assertRaised();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user