2018-10-08 19:30:37 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Engelsystem\Test\Unit\Helpers;
|
|
|
|
|
|
|
|
use Engelsystem\Helpers\Authenticator;
|
2023-01-28 00:41:29 +01:00
|
|
|
use Engelsystem\Http\Request;
|
2022-11-06 12:41:52 +01:00
|
|
|
use Engelsystem\Models\Group;
|
|
|
|
use Engelsystem\Models\Privilege;
|
2018-10-08 19:30:37 +02:00
|
|
|
use Engelsystem\Models\User\User;
|
2018-11-27 12:01:36 +01:00
|
|
|
use Engelsystem\Test\Unit\HasDatabase;
|
2018-10-08 19:30:37 +02:00
|
|
|
use Engelsystem\Test\Unit\Helpers\Stub\UserModelImplementation;
|
|
|
|
use Engelsystem\Test\Unit\ServiceProviderTest;
|
|
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
2018-10-11 01:26:34 +02:00
|
|
|
use Psr\Http\Message\ServerRequestInterface;
|
2018-10-08 19:30:37 +02:00
|
|
|
use Symfony\Component\HttpFoundation\Session\Session;
|
2023-01-28 00:41:29 +01:00
|
|
|
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
|
2018-10-08 19:30:37 +02:00
|
|
|
|
|
|
|
class AuthenticatorTest extends ServiceProviderTest
|
|
|
|
{
|
2018-11-27 12:01:36 +01:00
|
|
|
use HasDatabase;
|
|
|
|
|
2018-10-08 19:30:37 +02:00
|
|
|
/**
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::user
|
2023-01-28 00:41:29 +01:00
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::__construct
|
2018-10-08 19:30:37 +02:00
|
|
|
*/
|
2023-01-28 00:41:29 +01:00
|
|
|
public function testUserNotAuthorized(): void
|
2018-10-08 19:30:37 +02:00
|
|
|
{
|
2023-01-28 00:41:29 +01:00
|
|
|
$request = new Request();
|
|
|
|
$session = new Session(new MockArraySessionStorage());
|
2018-10-08 19:30:37 +02:00
|
|
|
/** @var UserModelImplementation|MockObject $userRepository */
|
|
|
|
$userRepository = new UserModelImplementation();
|
2023-01-28 00:41:29 +01:00
|
|
|
$this->app->instance('request', $request);
|
2018-10-08 19:30:37 +02:00
|
|
|
|
2018-10-11 01:26:34 +02:00
|
|
|
$auth = new Authenticator($request, $session, $userRepository);
|
2023-01-28 00:41:29 +01:00
|
|
|
$user = $auth->user();
|
|
|
|
|
|
|
|
$this->assertNull($user);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::user
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::userFromSession
|
|
|
|
*/
|
|
|
|
public function testUserViaFromSession(): void
|
|
|
|
{
|
|
|
|
$this->initDatabase();
|
2018-10-08 19:30:37 +02:00
|
|
|
|
2023-01-28 00:41:29 +01:00
|
|
|
$request = new Request();
|
|
|
|
$session = new Session(new MockArraySessionStorage());
|
2018-10-08 19:30:37 +02:00
|
|
|
|
2023-01-28 00:41:29 +01:00
|
|
|
$session->set('user_id', 42);
|
|
|
|
User::factory()->create(['id' => 42]);
|
2018-10-08 19:30:37 +02:00
|
|
|
|
2023-01-28 00:41:29 +01:00
|
|
|
$auth = new Authenticator($request, $session, new User());
|
|
|
|
$user = $auth->user();
|
2018-10-08 19:30:37 +02:00
|
|
|
|
2023-01-28 00:41:29 +01:00
|
|
|
$this->assertInstanceOf(User::class, $user);
|
|
|
|
$this->assertEquals(42, $user->id);
|
|
|
|
|
|
|
|
// Cached in user()
|
|
|
|
$user2 = $auth->user();
|
|
|
|
$this->assertEquals($user, $user2);
|
|
|
|
|
|
|
|
// Cached in userFromSession()
|
|
|
|
$user3 = $auth->userFromSession();
|
|
|
|
$this->assertEquals($user, $user3);
|
2018-10-08 19:30:37 +02:00
|
|
|
}
|
2018-10-11 01:26:34 +02:00
|
|
|
|
|
|
|
/**
|
2023-01-28 00:41:29 +01:00
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::user
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::userFromApi
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::userByHeaders
|
2018-10-11 01:26:34 +02:00
|
|
|
*/
|
2023-01-28 00:41:29 +01:00
|
|
|
public function testUserViaFromApi(): void
|
2018-10-11 01:26:34 +02:00
|
|
|
{
|
2023-01-28 00:41:29 +01:00
|
|
|
$this->initDatabase();
|
|
|
|
|
|
|
|
$request = new Request();
|
|
|
|
$session = new Session(new MockArraySessionStorage());
|
|
|
|
|
|
|
|
$request = $request->withHeader('Authorization', 'Bearer F00Bar');
|
|
|
|
$request = $request->withAttribute('route-api', true);
|
|
|
|
$this->app->instance('request', $request);
|
|
|
|
User::factory()->create(['api_key' => 'F00Bar']);
|
2018-10-11 01:26:34 +02:00
|
|
|
|
2023-01-28 00:41:29 +01:00
|
|
|
$auth = new Authenticator($request, $session, new User());
|
|
|
|
$user = $auth->user();
|
2018-10-11 01:26:34 +02:00
|
|
|
|
2023-01-28 00:41:29 +01:00
|
|
|
$this->assertInstanceOf(User::class, $user);
|
|
|
|
$this->assertEquals('F00Bar', $user->api_key);
|
2018-10-11 01:26:34 +02:00
|
|
|
|
2023-01-28 00:41:29 +01:00
|
|
|
// Cached in userFromApi()
|
|
|
|
$user2 = $auth->userFromApi();
|
|
|
|
$this->assertEquals($user, $user2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::userFromSession
|
|
|
|
*/
|
|
|
|
public function testUserFromSessionNotFound(): void
|
|
|
|
{
|
|
|
|
$this->initDatabase();
|
|
|
|
|
|
|
|
$request = new Request();
|
|
|
|
$session = new Session(new MockArraySessionStorage());
|
|
|
|
|
|
|
|
$auth = new Authenticator($request, $session, new User());
|
|
|
|
|
|
|
|
$user = $auth->userFromSession();
|
|
|
|
$this->assertNull($user);
|
|
|
|
|
|
|
|
$session->set('user_id', 42);
|
|
|
|
$user2 = $auth->userFromSession();
|
|
|
|
$this->assertNull($user2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::userFromApi
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::userByQueryParam
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::userByApiKey
|
|
|
|
*/
|
|
|
|
public function testUserFromApiByQueryParam(): void
|
|
|
|
{
|
|
|
|
$this->initDatabase();
|
|
|
|
|
|
|
|
$request = new Request();
|
|
|
|
$session = new Session(new MockArraySessionStorage());
|
|
|
|
|
|
|
|
$request = $request->withQueryParams(['key' => 'F00Bar']);
|
|
|
|
|
|
|
|
$auth = new Authenticator($request, $session, new User());
|
|
|
|
|
|
|
|
// User not found
|
|
|
|
$user = $auth->userFromApi();
|
|
|
|
$this->assertNull($user);
|
|
|
|
|
|
|
|
// User exists
|
|
|
|
User::factory()->create(['api_key' => 'F00Bar']);
|
|
|
|
$user2 = $auth->userFromApi();
|
|
|
|
$this->assertInstanceOf(User::class, $user2);
|
|
|
|
$this->assertEquals('F00Bar', $user2->api_key);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::userByHeaders
|
|
|
|
*/
|
|
|
|
public function testUserByHeaders(): void
|
|
|
|
{
|
|
|
|
$this->initDatabase();
|
2018-10-11 01:26:34 +02:00
|
|
|
|
2023-01-28 00:41:29 +01:00
|
|
|
$request = new Request();
|
|
|
|
$request = $request->withAttribute('route-api', true);
|
|
|
|
$session = new Session(new MockArraySessionStorage());
|
|
|
|
$this->app->instance('request', $request);
|
|
|
|
|
|
|
|
$auth = new Authenticator($request, $session, new User());
|
|
|
|
|
|
|
|
// Header not set
|
|
|
|
$user = $auth->userFromApi();
|
|
|
|
$this->assertNull($user);
|
|
|
|
|
|
|
|
// User not found
|
|
|
|
$request = $request->withHeader('x-api-key', 'SomeWrongKey');
|
|
|
|
$auth = new Authenticator($request, $session, new User());
|
|
|
|
$user = $auth->userFromApi();
|
|
|
|
$this->assertNull($user);
|
|
|
|
|
|
|
|
$request = $request->withHeader('x-api-key', 'F00Bar');
|
|
|
|
$auth = new Authenticator($request, $session, new User());
|
|
|
|
User::factory()->create(['api_key' => 'F00Bar']);
|
|
|
|
$user = $auth->user();
|
|
|
|
$this->assertInstanceOf(User::class, $user);
|
|
|
|
$this->assertEquals('F00Bar', $user->api_key);
|
2018-10-11 01:26:34 +02:00
|
|
|
}
|
2018-11-12 14:41:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::can
|
|
|
|
*/
|
2022-12-14 19:15:20 +01:00
|
|
|
public function testCan(): void
|
2018-11-12 14:41:23 +01:00
|
|
|
{
|
2022-11-06 12:41:52 +01:00
|
|
|
$this->initDatabase();
|
|
|
|
|
2018-11-12 14:41:23 +01:00
|
|
|
/** @var ServerRequestInterface|MockObject $request */
|
|
|
|
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
|
|
|
/** @var Session|MockObject $session */
|
|
|
|
$session = $this->createMock(Session::class);
|
|
|
|
/** @var UserModelImplementation|MockObject $userRepository */
|
|
|
|
$userRepository = new UserModelImplementation();
|
2022-11-06 12:41:52 +01:00
|
|
|
/** @var User $user */
|
|
|
|
$user = User::factory()->create();
|
|
|
|
/** @var Group $group */
|
|
|
|
$group = Group::factory()->create();
|
|
|
|
/** @var Privilege $privilege */
|
|
|
|
$privilege = Privilege::factory()->create(['name' => 'bar']);
|
|
|
|
|
|
|
|
$user->groups()->attach($group);
|
|
|
|
$group->privileges()->attach($privilege);
|
2018-11-12 14:41:23 +01:00
|
|
|
|
2018-11-27 12:01:36 +01:00
|
|
|
$session->expects($this->once())
|
2018-11-12 14:41:23 +01:00
|
|
|
->method('get')
|
2018-11-27 12:01:36 +01:00
|
|
|
->with('user_id')
|
2018-11-12 14:41:23 +01:00
|
|
|
->willReturn(42);
|
|
|
|
$session->expects($this->once())
|
|
|
|
->method('remove')
|
2018-11-27 12:01:36 +01:00
|
|
|
->with('user_id');
|
2018-11-12 14:41:23 +01:00
|
|
|
|
|
|
|
/** @var Authenticator|MockObject $auth */
|
|
|
|
$auth = $this->getMockBuilder(Authenticator::class)
|
|
|
|
->setConstructorArgs([$request, $session, $userRepository])
|
2022-11-06 12:41:52 +01:00
|
|
|
->onlyMethods(['user'])
|
2018-11-12 14:41:23 +01:00
|
|
|
->getMock();
|
|
|
|
$auth->expects($this->exactly(2))
|
|
|
|
->method('user')
|
|
|
|
->willReturnOnConsecutiveCalls(null, $user);
|
|
|
|
|
2022-11-06 12:41:52 +01:00
|
|
|
Group::factory()->create(['id' => $auth->getGuestRole()]);
|
|
|
|
|
2018-11-12 14:41:23 +01:00
|
|
|
// No user, no permissions
|
|
|
|
$this->assertFalse($auth->can('foo'));
|
|
|
|
|
|
|
|
// User exists, has permissions
|
|
|
|
$this->assertTrue($auth->can('bar'));
|
|
|
|
|
|
|
|
// Permissions cached
|
|
|
|
$this->assertTrue($auth->can('bar'));
|
|
|
|
}
|
2018-11-27 12:01:36 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::authenticate
|
|
|
|
*/
|
2022-12-14 19:15:20 +01:00
|
|
|
public function testAuthenticate(): void
|
2018-11-27 12:01:36 +01:00
|
|
|
{
|
|
|
|
$this->initDatabase();
|
|
|
|
|
|
|
|
/** @var ServerRequestInterface|MockObject $request */
|
|
|
|
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
|
|
|
/** @var Session|MockObject $session */
|
|
|
|
$session = $this->createMock(Session::class);
|
|
|
|
$userRepository = new User();
|
|
|
|
|
2021-06-29 00:27:57 +02:00
|
|
|
User::factory([
|
2018-11-27 12:01:36 +01:00
|
|
|
'name' => 'lorem',
|
|
|
|
'password' => password_hash('testing', PASSWORD_DEFAULT),
|
|
|
|
'email' => 'lorem@foo.bar',
|
2021-06-29 00:27:57 +02:00
|
|
|
])->create();
|
|
|
|
User::factory([
|
2018-11-27 12:01:36 +01:00
|
|
|
'name' => 'ipsum',
|
|
|
|
'password' => '',
|
2021-06-29 00:27:57 +02:00
|
|
|
])->create();
|
2018-11-27 12:01:36 +01:00
|
|
|
|
|
|
|
$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
|
|
|
|
*/
|
2022-12-14 19:15:20 +01:00
|
|
|
public function testVerifyPassword(): void
|
2018-11-27 12:01:36 +01:00
|
|
|
{
|
|
|
|
$this->initDatabase();
|
|
|
|
$password = password_hash('testing', PASSWORD_ARGON2I);
|
2021-06-29 00:27:57 +02:00
|
|
|
/** @var User $user */
|
|
|
|
$user = User::factory([
|
2018-11-27 12:01:36 +01:00
|
|
|
'name' => 'lorem',
|
|
|
|
'password' => $password,
|
2021-06-29 00:27:57 +02:00
|
|
|
])->create();
|
2018-11-27 12:01:36 +01:00
|
|
|
|
|
|
|
/** @var Authenticator|MockObject $auth */
|
|
|
|
$auth = $this->getMockBuilder(Authenticator::class)
|
|
|
|
->disableOriginalConstructor()
|
2019-11-06 12:29:58 +01:00
|
|
|
->onlyMethods(['setPassword'])
|
2018-11-27 12:01:36 +01:00
|
|
|
->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
|
|
|
|
*/
|
2022-12-14 19:15:20 +01:00
|
|
|
public function testSetPassword(): void
|
2018-11-27 12:01:36 +01:00
|
|
|
{
|
|
|
|
$this->initDatabase();
|
2021-06-29 00:27:57 +02:00
|
|
|
/** @var User $user */
|
|
|
|
$user = User::factory([
|
2018-11-27 12:01:36 +01:00
|
|
|
'name' => 'ipsum',
|
|
|
|
'password' => '',
|
2021-06-29 00:27:57 +02:00
|
|
|
])->create();
|
2018-11-27 12:01:36 +01:00
|
|
|
$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
|
|
|
|
*/
|
2022-12-14 19:15:20 +01:00
|
|
|
public function testPasswordAlgorithm(): void
|
2018-11-27 12:01:36 +01:00
|
|
|
{
|
|
|
|
$auth = $this->getAuthenticator();
|
|
|
|
|
|
|
|
$auth->setPasswordAlgorithm(PASSWORD_ARGON2I);
|
|
|
|
$this->assertEquals(PASSWORD_ARGON2I, $auth->getPasswordAlgorithm());
|
|
|
|
}
|
|
|
|
|
2022-11-06 12:41:52 +01:00
|
|
|
/**
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::setDefaultRole
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::getDefaultRole
|
|
|
|
*/
|
2022-12-14 19:15:20 +01:00
|
|
|
public function testDefaultRole(): void
|
2022-11-06 12:41:52 +01:00
|
|
|
{
|
|
|
|
$auth = $this->getAuthenticator();
|
|
|
|
|
|
|
|
$auth->setDefaultRole(1337);
|
|
|
|
$this->assertEquals(1337, $auth->getDefaultRole());
|
|
|
|
}
|
|
|
|
|
2019-07-28 15:33:01 +02:00
|
|
|
/**
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::setGuestRole
|
|
|
|
* @covers \Engelsystem\Helpers\Authenticator::getGuestRole
|
|
|
|
*/
|
2022-12-14 19:15:20 +01:00
|
|
|
public function testGuestRole(): void
|
2019-07-28 15:33:01 +02:00
|
|
|
{
|
|
|
|
$auth = $this->getAuthenticator();
|
|
|
|
|
|
|
|
$auth->setGuestRole(42);
|
|
|
|
$this->assertEquals(42, $auth->getGuestRole());
|
|
|
|
}
|
|
|
|
|
2022-12-14 19:15:20 +01:00
|
|
|
protected function getAuthenticator(): Authenticator
|
2018-11-27 12:01:36 +01:00
|
|
|
{
|
2022-11-06 12:41:52 +01:00
|
|
|
return new class extends Authenticator {
|
2018-11-27 12:01:36 +01:00
|
|
|
/** @noinspection PhpMissingParentConstructorInspection */
|
2019-11-10 23:26:23 +01:00
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
}
|
2018-11-27 12:01:36 +01:00
|
|
|
};
|
|
|
|
}
|
2018-10-08 19:30:37 +02:00
|
|
|
}
|