summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorIgor Scheller <igor.scheller@igorshp.de>2018-11-27 12:01:36 +0100
committerIgor Scheller <igor.scheller@igorshp.de>2019-07-08 01:57:59 +0200
commitbcce2625a8cb0b630d945c6849014049869e10ce (patch)
tree2031911a85a7a6a85015ff77ca8f9b326fa1da8e /tests
parentfd4303f336173101b84ba21650e451ad536828fe (diff)
Implemented AuthController for login
* Moved /login functionality to AuthController * Refactored password handling logic to use the Authenticator
Diffstat (limited to 'tests')
-rw-r--r--tests/Unit/Controllers/AuthControllerTest.php132
-rw-r--r--tests/Unit/Controllers/Stub/ControllerImplementation.php8
-rw-r--r--tests/Unit/Helpers/AuthenticatorServiceProviderTest.php9
-rw-r--r--tests/Unit/Helpers/AuthenticatorTest.php125
-rw-r--r--tests/Unit/Http/UrlGeneratorServiceProviderTest.php5
5 files changed, 254 insertions, 25 deletions
diff --git a/tests/Unit/Controllers/AuthControllerTest.php b/tests/Unit/Controllers/AuthControllerTest.php
index c5349cda..0fad3b6d 100644
--- a/tests/Unit/Controllers/AuthControllerTest.php
+++ b/tests/Unit/Controllers/AuthControllerTest.php
@@ -3,40 +3,154 @@
namespace Engelsystem\Test\Unit\Controllers;
use Engelsystem\Controllers\AuthController;
+use Engelsystem\Helpers\Authenticator;
+use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
use Engelsystem\Http\UrlGeneratorInterface;
+use Engelsystem\Models\User\Settings;
+use Engelsystem\Models\User\User;
+use Engelsystem\Test\Unit\HasDatabase;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class AuthControllerTest extends TestCase
{
+ use HasDatabase;
+
/**
* @covers \Engelsystem\Controllers\AuthController::__construct
- * @covers \Engelsystem\Controllers\AuthController::logout
+ * @covers \Engelsystem\Controllers\AuthController::login
*/
- public function testLogout()
+ public function testLogin()
{
/** @var Response|MockObject $response */
$response = $this->createMock(Response::class);
/** @var SessionInterface|MockObject $session */
- $session = $this->getMockForAbstractClass(SessionInterface::class);
/** @var UrlGeneratorInterface|MockObject $url */
- $url = $this->getMockForAbstractClass(UrlGeneratorInterface::class);
+ /** @var Authenticator|MockObject $auth */
+ list(, $session, $url, $auth) = $this->getMocks();
- $session->expects($this->once())
- ->method('invalidate');
+ $response->expects($this->once())
+ ->method('withView')
+ ->with('pages/login')
+ ->willReturn($response);
+
+ $controller = new AuthController($response, $session, $url, $auth);
+ $controller->login();
+ }
+
+ /**
+ * @covers \Engelsystem\Controllers\AuthController::postLogin
+ * @covers \Engelsystem\Controllers\AuthController::authenticateUser
+ */
+ public function testPostLogin()
+ {
+ $this->initDatabase();
+ $request = new Request();
+ /** @var Response|MockObject $response */
+ $response = $this->createMock(Response::class);
+ /** @var SessionInterface|MockObject $session */
+ /** @var UrlGeneratorInterface|MockObject $url */
+ /** @var Authenticator|MockObject $auth */
+ list(, $session, $url, $auth) = $this->getMocks();
+
+ $user = new User([
+ 'name' => 'foo',
+ 'password' => '',
+ 'email' => '',
+ 'api_key' => '',
+ 'last_login_at' => null,
+ ]);
+ $user->forceFill(['id' => 42,]);
+ $user->save();
+
+ $settings = new Settings(['language' => 'de_DE', 'theme' => '']);
+ $settings->user()
+ ->associate($user)
+ ->save();
+
+ $auth->expects($this->exactly(2))
+ ->method('authenticate')
+ ->with('foo', 'bar')
+ ->willReturnOnConsecutiveCalls(null, $user);
+
+ $response->expects($this->exactly(3))
+ ->method('withView')
+ ->withConsecutive(
+ ['pages/login', ['errors' => ['auth.no-nickname'], 'show_password_recovery' => true]],
+ ['pages/login', ['errors' => ['auth.no-password'], 'show_password_recovery' => true]],
+ ['pages/login', ['errors' => ['auth.not-found'], 'show_password_recovery' => true]])
+ ->willReturn($response);
$response->expects($this->once())
->method('redirectTo')
- ->with('https://foo.bar/');
+ ->with('news')
+ ->willReturn($response);
+
+ $session->expects($this->once())
+ ->method('invalidate');
+
+ $session->expects($this->exactly(2))
+ ->method('set')
+ ->withConsecutive(
+ ['user_id', 42],
+ ['locale', 'de_DE']
+ );
+
+ $controller = new AuthController($response, $session, $url, $auth);
+ $controller->postLogin($request);
+
+ $request = new Request(['login' => 'foo']);
+ $controller->postLogin($request);
+
+ $request = new Request(['login' => 'foo', 'password' => 'bar']);
+ // No user found
+ $controller->postLogin($request);
+ // Authenticated user
+ $controller->postLogin($request);
+
+ $this->assertNotNull($user->last_login_at);
+ }
+
+ /**
+ * @covers \Engelsystem\Controllers\AuthController::logout
+ */
+ public function testLogout()
+ {
+ /** @var Response $response */
+ /** @var SessionInterface|MockObject $session */
+ /** @var UrlGeneratorInterface|MockObject $url */
+ /** @var Authenticator|MockObject $auth */
+ list($response, $session, $url, $auth) = $this->getMocks();
+
+ $session->expects($this->once())
+ ->method('invalidate');
$url->expects($this->once())
->method('to')
->with('/')
->willReturn('https://foo.bar/');
- $controller = new AuthController($response, $session, $url);
- $controller->logout();
+ $controller = new AuthController($response, $session, $url, $auth);
+ $return = $controller->logout();
+
+ $this->assertEquals(['https://foo.bar/'], $return->getHeader('location'));
+ }
+
+ /**
+ * @return array
+ */
+ protected function getMocks()
+ {
+ $response = new Response();
+ /** @var SessionInterface|MockObject $session */
+ $session = $this->getMockForAbstractClass(SessionInterface::class);
+ /** @var UrlGeneratorInterface|MockObject $url */
+ $url = $this->getMockForAbstractClass(UrlGeneratorInterface::class);
+ /** @var Authenticator|MockObject $auth */
+ $auth = $this->createMock(Authenticator::class);
+
+ return [$response, $session, $url, $auth];
}
}
diff --git a/tests/Unit/Controllers/Stub/ControllerImplementation.php b/tests/Unit/Controllers/Stub/ControllerImplementation.php
index 01d9f250..a8bf538c 100644
--- a/tests/Unit/Controllers/Stub/ControllerImplementation.php
+++ b/tests/Unit/Controllers/Stub/ControllerImplementation.php
@@ -14,12 +14,4 @@ class ControllerImplementation extends BaseController
'dolor',
],
];
-
- /**
- * @param array $permissions
- */
- public function setPermissions(array $permissions)
- {
- $this->permissions = $permissions;
- }
}
diff --git a/tests/Unit/Helpers/AuthenticatorServiceProviderTest.php b/tests/Unit/Helpers/AuthenticatorServiceProviderTest.php
index b1767ebc..ab9b23ec 100644
--- a/tests/Unit/Helpers/AuthenticatorServiceProviderTest.php
+++ b/tests/Unit/Helpers/AuthenticatorServiceProviderTest.php
@@ -3,6 +3,7 @@
namespace Engelsystem\Test\Unit\Helpers;
use Engelsystem\Application;
+use Engelsystem\Config\Config;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Helpers\AuthenticatorServiceProvider;
use Engelsystem\Http\Request;
@@ -19,11 +20,19 @@ class AuthenticatorServiceProviderTest extends ServiceProviderTest
$app = new Application();
$app->bind(ServerRequestInterface::class, Request::class);
+ $config = new Config();
+ $config->set('password_algorithm', PASSWORD_DEFAULT);
+ $app->instance('config', $config);
+
$serviceProvider = new AuthenticatorServiceProvider($app);
$serviceProvider->register();
$this->assertInstanceOf(Authenticator::class, $app->get(Authenticator::class));
$this->assertInstanceOf(Authenticator::class, $app->get('authenticator'));
$this->assertInstanceOf(Authenticator::class, $app->get('auth'));
+
+ /** @var Authenticator $auth */
+ $auth = $app->get(Authenticator::class);
+ $this->assertEquals(PASSWORD_DEFAULT, $auth->getPasswordAlgorithm());
}
}
diff --git a/tests/Unit/Helpers/AuthenticatorTest.php b/tests/Unit/Helpers/AuthenticatorTest.php
index 400278f2..83dc72ad 100644
--- a/tests/Unit/Helpers/AuthenticatorTest.php
+++ b/tests/Unit/Helpers/AuthenticatorTest.php
@@ -4,6 +4,7 @@ namespace Engelsystem\Test\Unit\Helpers;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Models\User\User;
+use Engelsystem\Test\Unit\HasDatabase;
use Engelsystem\Test\Unit\Helpers\Stub\UserModelImplementation;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit\Framework\MockObject\MockObject;
@@ -12,6 +13,8 @@ use Symfony\Component\HttpFoundation\Session\Session;
class AuthenticatorTest extends ServiceProviderTest
{
+ use HasDatabase;
+
/**
* @covers \Engelsystem\Helpers\Authenticator::__construct(
* @covers \Engelsystem\Helpers\Authenticator::user
@@ -29,7 +32,7 @@ class AuthenticatorTest extends ServiceProviderTest
$session->expects($this->exactly(3))
->method('get')
- ->with('uid')
+ ->with('user_id')
->willReturnOnConsecutiveCalls(
null,
42,
@@ -114,16 +117,13 @@ class AuthenticatorTest extends ServiceProviderTest
/** @var User|MockObject $user */
$user = $this->createMock(User::class);
- $user->expects($this->once())
- ->method('save');
-
- $session->expects($this->exactly(2))
+ $session->expects($this->once())
->method('get')
- ->with('uid')
+ ->with('user_id')
->willReturn(42);
$session->expects($this->once())
->method('remove')
- ->with('uid');
+ ->with('user_id');
/** @var Authenticator|MockObject $auth */
$auth = $this->getMockBuilder(Authenticator::class)
@@ -151,4 +151,115 @@ class AuthenticatorTest extends ServiceProviderTest
// Permissions cached
$this->assertTrue($auth->can('bar'));
}
+
+ /**
+ * @covers \Engelsystem\Helpers\Authenticator::authenticate
+ */
+ public function testAuthenticate()
+ {
+ $this->initDatabase();
+
+ /** @var ServerRequestInterface|MockObject $request */
+ $request = $this->getMockForAbstractClass(ServerRequestInterface::class);
+ /** @var Session|MockObject $session */
+ $session = $this->createMock(Session::class);
+ $userRepository = new User();
+
+ (new User([
+ 'name' => 'lorem',
+ 'password' => password_hash('testing', PASSWORD_DEFAULT),
+ 'email' => 'lorem@foo.bar',
+ 'api_key' => '',
+ ]))->save();
+ (new User([
+ 'name' => 'ipsum',
+ 'password' => '',
+ 'email' => 'ipsum@foo.bar',
+ 'api_key' => '',
+ ]))->save();
+
+ $auth = new Authenticator($request, $session, $userRepository);
+ $this->assertNull($auth->authenticate('not-existing', 'foo'));
+ $this->assertNull($auth->authenticate('ipsum', 'wrong-password'));
+ $this->assertInstanceOf(User::class, $auth->authenticate('lorem', 'testing'));
+ $this->assertInstanceOf(User::class, $auth->authenticate('lorem@foo.bar', 'testing'));
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Authenticator::verifyPassword
+ */
+ public function testVerifyPassword()
+ {
+ $this->initDatabase();
+ $password = password_hash('testing', PASSWORD_ARGON2I);
+ $user = new User([
+ 'name' => 'lorem',
+ 'password' => $password,
+ 'email' => 'lorem@foo.bar',
+ 'api_key' => '',
+ ]);
+ $user->save();
+
+ /** @var Authenticator|MockObject $auth */
+ $auth = $this->getMockBuilder(Authenticator::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setPassword'])
+ ->getMock();
+
+ $auth->expects($this->once())
+ ->method('setPassword')
+ ->with($user, 'testing');
+ $auth->setPasswordAlgorithm(PASSWORD_BCRYPT);
+
+ $this->assertFalse($auth->verifyPassword($user, 'randomStuff'));
+ $this->assertTrue($auth->verifyPassword($user, 'testing'));
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Authenticator::setPassword
+ */
+ public function testSetPassword()
+ {
+ $this->initDatabase();
+ $user = new User([
+ 'name' => 'ipsum',
+ 'password' => '',
+ 'email' => 'ipsum@foo.bar',
+ 'api_key' => '',
+ ]);
+ $user->save();
+
+ $auth = $this->getAuthenticator();
+ $auth->setPasswordAlgorithm(PASSWORD_ARGON2I);
+
+ $auth->setPassword($user, 'FooBar');
+ $this->assertTrue($user->isClean());
+
+ $this->assertTrue(password_verify('FooBar', $user->password));
+ $this->assertFalse(password_needs_rehash($user->password, PASSWORD_ARGON2I));
+ }
+
+ /**
+ * @covers \Engelsystem\Helpers\Authenticator::setPasswordAlgorithm
+ * @covers \Engelsystem\Helpers\Authenticator::getPasswordAlgorithm
+ */
+ public function testPasswordAlgorithm()
+ {
+ $auth = $this->getAuthenticator();
+
+ $auth->setPasswordAlgorithm(PASSWORD_ARGON2I);
+ $this->assertEquals(PASSWORD_ARGON2I, $auth->getPasswordAlgorithm());
+ }
+
+ /**
+ * @return Authenticator
+ */
+ protected function getAuthenticator()
+ {
+ return new class extends Authenticator
+ {
+ /** @noinspection PhpMissingParentConstructorInspection */
+ public function __construct() { }
+ };
+ }
}
diff --git a/tests/Unit/Http/UrlGeneratorServiceProviderTest.php b/tests/Unit/Http/UrlGeneratorServiceProviderTest.php
index 61bf3e7c..6d18f160 100644
--- a/tests/Unit/Http/UrlGeneratorServiceProviderTest.php
+++ b/tests/Unit/Http/UrlGeneratorServiceProviderTest.php
@@ -19,7 +19,7 @@ class UrlGeneratorServiceProviderTest extends ServiceProviderTest
$urlGenerator = $this->getMockBuilder(UrlGenerator::class)
->getMock();
- $app = $this->getApp();
+ $app = $this->getApp(['make', 'instance', 'bind']);
$this->setExpects($app, 'make', [UrlGenerator::class], $urlGenerator);
$app->expects($this->exactly(2))
@@ -29,6 +29,9 @@ class UrlGeneratorServiceProviderTest extends ServiceProviderTest
['http.urlGenerator', $urlGenerator],
[UrlGeneratorInterface::class, $urlGenerator]
);
+ $app->expects($this->once())
+ ->method('bind')
+ ->with(UrlGeneratorInterface::class, UrlGenerator::class);
$serviceProvider = new UrlGeneratorServiceProvider($app);
$serviceProvider->register();