- added "today" as selector in date-range dropdown - added feature to prevent auto-select of dropdowns with only one entry - added hint that no changes were detected in batch update - added negative invoice sums are possible (e.g. for credit notes) - fix project list is expanded after submission - fix invalid date parsing causes 500 - fix: prevent auto-select of activities in export and invoice form (in case only one global activity exists) - fix team assignments for customer and project were not saved (using API now) - fix form fieldset with legend styling (e.g. team project assignment) - fix required meta-field were forced to have a value in batch update - fix tomselect meta-field was not disabled in batch update - fix unset internal rate is shown as 0 - fix one minute rounding problem in duration-only mode with "now" being default time - fix column width and label for duration-only mode - tech debt: cleanup invoice template (remove invoice layout) - tech debt: reorder for simpler comparison with invoice form - possible BC for devs: remove unused methods from form trait - bump composer packages (includes new translations for auth screens)
143 lines
5.4 KiB
PHP
143 lines
5.4 KiB
PHP
<?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\Configuration\SamlConfiguration;
|
||
use App\Configuration\SystemConfiguration;
|
||
use App\Controller\Security\SecurityController;
|
||
use App\Entity\User;
|
||
use App\Tests\Configuration\TestConfigLoader;
|
||
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" id="username" name="_username"', $content);
|
||
$this->assertStringContainsString('<input id="password" name="_password" type="password"', $content);
|
||
$this->assertStringContainsString('">Log in</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 testLoginAlreadyLoggedIn()
|
||
{
|
||
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||
|
||
$this->request($client, '/login');
|
||
|
||
$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-important 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.');
|
||
|
||
self::createClient(); // just to bootstrap the container
|
||
$csrf = $this->createMock(CsrfTokenManagerInterface::class);
|
||
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['saml' => ['activate' => true]]);
|
||
$samlConfig = new SamlConfiguration($systemConfig);
|
||
$sut = new SecurityController($csrf, $samlConfig);
|
||
$sut->checkAction();
|
||
}
|
||
|
||
public function testLogoutAction()
|
||
{
|
||
$this->expectException(\RuntimeException::class);
|
||
$this->expectExceptionMessage('You must activate the logout in your security firewall configuration.');
|
||
|
||
self::createClient(); // just to bootstrap the container
|
||
$csrf = $this->createMock(CsrfTokenManagerInterface::class);
|
||
$systemConfig = new SystemConfiguration(new TestConfigLoader([]), ['saml' => ['activate' => true]]);
|
||
$samlConfig = new SamlConfiguration($systemConfig);
|
||
$sut = new SecurityController($csrf, $samlConfig);
|
||
$sut->logoutAction();
|
||
}
|
||
}
|