tests(unit): add RequireTwoFactorAuthenticationTest
This commit is contained in:
parent
790f109e66
commit
64110d84af
9 changed files with 373 additions and 7 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -47,6 +47,7 @@ yarn-error.log
|
||||||
# PHP
|
# PHP
|
||||||
/vendor
|
/vendor
|
||||||
.php_cs.cache
|
.php_cs.cache
|
||||||
|
.phpunit.result.cache
|
||||||
|
|
||||||
#-------------------#
|
#-------------------#
|
||||||
# Operating Systems #
|
# Operating Systems #
|
||||||
|
|
|
@ -6,7 +6,7 @@ use Exception;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use LaravelWebauthn\Facades\Webauthn;
|
use LaravelWebauthn\Facades\Webauthn;
|
||||||
use LaravelWebauthn\Models\WebauthnKey;
|
use Pterodactyl\Models\WebauthnKey;
|
||||||
use Webauthn\PublicKeyCredentialCreationOptions;
|
use Webauthn\PublicKeyCredentialCreationOptions;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Pterodactyl\Transformers\Api\Client\WebauthnKeyTransformer;
|
use Pterodactyl\Transformers\Api\Client\WebauthnKeyTransformer;
|
||||||
|
|
|
@ -5,7 +5,6 @@ namespace Pterodactyl\Models;
|
||||||
use Pterodactyl\Rules\Username;
|
use Pterodactyl\Rules\Username;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Auth\Authenticatable;
|
use Illuminate\Auth\Authenticatable;
|
||||||
use LaravelWebauthn\Models\WebauthnKey;
|
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Auth\Passwords\CanResetPassword;
|
use Illuminate\Auth\Passwords\CanResetPassword;
|
||||||
|
@ -42,7 +41,7 @@ use Pterodactyl\Notifications\SendPasswordReset as ResetPasswordNotification;
|
||||||
* @property \Pterodactyl\Models\Server[]|\Illuminate\Database\Eloquent\Collection $servers
|
* @property \Pterodactyl\Models\Server[]|\Illuminate\Database\Eloquent\Collection $servers
|
||||||
* @property \Pterodactyl\Models\UserSSHKey|\Illuminate\Database\Eloquent\Collection $sshKeys
|
* @property \Pterodactyl\Models\UserSSHKey|\Illuminate\Database\Eloquent\Collection $sshKeys
|
||||||
* @property \Pterodactyl\Models\RecoveryToken[]|\Illuminate\Database\Eloquent\Collection $recoveryTokens
|
* @property \Pterodactyl\Models\RecoveryToken[]|\Illuminate\Database\Eloquent\Collection $recoveryTokens
|
||||||
* @property \LaravelWebauthn\Models\WebauthnKey[]|\Illuminate\Database\Eloquent\Collection $webauthnKeys
|
* @property \Pterodactyl\Models\WebauthnKey[]|\Illuminate\Database\Eloquent\Collection $webauthnKeys
|
||||||
*/
|
*/
|
||||||
class User extends Model implements
|
class User extends Model implements
|
||||||
AuthenticatableContract,
|
AuthenticatableContract,
|
||||||
|
|
16
app/Models/WebauthnKey.php
Normal file
16
app/Models/WebauthnKey.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
|
||||||
|
class WebauthnKey extends \LaravelWebauthn\Models\WebauthnKey
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
public function user(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Transformers\Api\Client;
|
namespace Pterodactyl\Transformers\Api\Client;
|
||||||
|
|
||||||
use LaravelWebauthn\Models\WebauthnKey;
|
use Pterodactyl\Models\WebauthnKey;
|
||||||
|
|
||||||
class WebauthnKeyTransformer extends BaseClientTransformer
|
class WebauthnKeyTransformer extends BaseClientTransformer
|
||||||
{
|
{
|
||||||
|
|
|
@ -77,8 +77,15 @@ return [
|
||||||
'charset' => 'utf8mb4',
|
'charset' => 'utf8mb4',
|
||||||
'collation' => 'utf8mb4_unicode_ci',
|
'collation' => 'utf8mb4_unicode_ci',
|
||||||
'prefix' => '',
|
'prefix' => '',
|
||||||
'strict' => false,
|
'strict' => env('TESTING_DB_STRICT_MODE', false),
|
||||||
'timezone' => env('DB_TIMEZONE', Time::getMySQLTimezoneOffset(env('APP_TIMEZONE', 'UTC'))),
|
'timezone' => env('TESTING_DB_TIMEZONE', Time::getMySQLTimezoneOffset(env('APP_TIMEZONE', 'UTC'))),
|
||||||
|
'sslmode' => env('TESTING_DB_SSLMODE', 'prefer'),
|
||||||
|
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||||
|
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||||
|
PDO::MYSQL_ATTR_SSL_CERT => env('MYSQL_ATTR_SSL_CERT'),
|
||||||
|
PDO::MYSQL_ATTR_SSL_KEY => env('MYSQL_ATTR_SSL_KEY'),
|
||||||
|
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('MYSQL_ATTR_SSL_VERIFY_SERVER_CERT', true),
|
||||||
|
]) : [],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
24
database/Factories/WebauthnKeyFactory.php
Normal file
24
database/Factories/WebauthnKeyFactory.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Pterodactyl\Models\WebauthnKey;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
class WebauthnKeyFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name of the factory's corresponding model.
|
||||||
|
*/
|
||||||
|
protected $model = WebauthnKey::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->faker->name,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,6 +43,7 @@ trait RequestMockHelpers
|
||||||
*/
|
*/
|
||||||
public function generateRequestUserModel(array $args = []): User
|
public function generateRequestUserModel(array $args = []): User
|
||||||
{
|
{
|
||||||
|
/** @var \Pterodactyl\Models\User $user */
|
||||||
$user = User::factory()->make($args);
|
$user = User::factory()->make($args);
|
||||||
$this->setRequestUserModel($user);
|
$this->setRequestUserModel($user);
|
||||||
|
|
||||||
|
@ -70,8 +71,9 @@ trait RequestMockHelpers
|
||||||
/**
|
/**
|
||||||
* Set the active request object to be an instance of a mocked request.
|
* Set the active request object to be an instance of a mocked request.
|
||||||
*/
|
*/
|
||||||
protected function buildRequestMock()
|
protected function buildRequestMock($uri = '/')
|
||||||
{
|
{
|
||||||
|
// $this->request = Request::create($uri);
|
||||||
$this->request = m::mock($this->requestMockClass);
|
$this->request = m::mock($this->requestMockClass);
|
||||||
if (!$this->request instanceof Request) {
|
if (!$this->request instanceof Request) {
|
||||||
throw new InvalidArgumentException('Request mock class must be an instance of ' . Request::class . ' when mocked.');
|
throw new InvalidArgumentException('Request mock class must be an instance of ' . Request::class . ' when mocked.');
|
||||||
|
|
|
@ -0,0 +1,317 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Http\Middleware;
|
||||||
|
|
||||||
|
use Mockery as m;
|
||||||
|
use Pterodactyl\Models\User;
|
||||||
|
use Pterodactyl\Models\WebauthnKey;
|
||||||
|
use Prologue\Alerts\AlertsMessageBag;
|
||||||
|
use Pterodactyl\Tests\Unit\Http\Middleware\MiddlewareTestCase;
|
||||||
|
use Pterodactyl\Http\Middleware\RequireTwoFactorAuthentication;
|
||||||
|
use Pterodactyl\Exceptions\Http\TwoFactorAuthRequiredException;
|
||||||
|
|
||||||
|
class RequireTwoFactorAuthenticationTest extends MiddlewareTestCase
|
||||||
|
{
|
||||||
|
private $alerts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup tests.
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->alerts = m::mock(AlertsMessageBag::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNoRequirement__userWithout_2fa()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_NONE);
|
||||||
|
|
||||||
|
$user = $this->generateRequestUserModel(['use_totp' => false]);
|
||||||
|
|
||||||
|
$this->assertFalse($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNoRequirement__userWithTotp_2fa()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_NONE);
|
||||||
|
|
||||||
|
$user = $this->generateRequestUserModel(['use_totp' => true]);
|
||||||
|
|
||||||
|
$this->assertTrue($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNoRequirement__userWithWebauthn_2fa()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_NONE);
|
||||||
|
|
||||||
|
/** @var \Pterodactyl\Models\User $user */
|
||||||
|
$user = User::factory()
|
||||||
|
->has(WebauthnKey::factory()->count(1))
|
||||||
|
->create(['use_totp' => false]);
|
||||||
|
$this->setRequestUserModel($user);
|
||||||
|
|
||||||
|
$this->assertFalse($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
$this->assertNotEmpty($user->webauthnKeys);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNoRequirement__guestUser()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_NONE);
|
||||||
|
|
||||||
|
$this->setRequestUserModel();
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/auth/login');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn('auth.login');
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAllRequirement__userWithout_2fa()
|
||||||
|
{
|
||||||
|
$this->expectException(TwoFactorAuthRequiredException::class);
|
||||||
|
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ALL);
|
||||||
|
|
||||||
|
$user = $this->generateRequestUserModel(['use_totp' => false]);
|
||||||
|
|
||||||
|
$this->assertFalse($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAllRequirement__userWithTotp_2fa()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ALL);
|
||||||
|
|
||||||
|
$user = $this->generateRequestUserModel(['use_totp' => true]);
|
||||||
|
|
||||||
|
$this->assertTrue($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAllRequirement__ruserWithWebauthn_2fa()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ALL);
|
||||||
|
|
||||||
|
/** @var \Pterodactyl\Models\User $user */
|
||||||
|
$user = User::factory()
|
||||||
|
->has(WebauthnKey::factory()->count(1))
|
||||||
|
->create(['use_totp' => false]);
|
||||||
|
$this->setRequestUserModel($user);
|
||||||
|
|
||||||
|
$this->assertFalse($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
$this->assertNotEmpty($user->webauthnKeys);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAllRequirement__guestUser()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ALL);
|
||||||
|
|
||||||
|
$this->setRequestUserModel();
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/auth/login');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn('auth.login');
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminRequirement__userWithout_2fa()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ADMIN);
|
||||||
|
|
||||||
|
$user = $this->generateRequestUserModel(['use_totp' => false]);
|
||||||
|
|
||||||
|
$this->assertFalse($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
$this->assertFalse($user->root_admin);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminRequirement__adminUserWithout_2fa()
|
||||||
|
{
|
||||||
|
$this->expectException(TwoFactorAuthRequiredException::class);
|
||||||
|
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ADMIN);
|
||||||
|
|
||||||
|
$user = $this->generateRequestUserModel(['use_totp' => false, 'root_admin' => true]);
|
||||||
|
|
||||||
|
$this->assertFalse($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
$this->assertTrue($user->root_admin);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminRequirement__userWithTotp_2fa()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ADMIN);
|
||||||
|
|
||||||
|
$user = $this->generateRequestUserModel(['use_totp' => true]);
|
||||||
|
|
||||||
|
$this->assertTrue($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
$this->assertFalse($user->root_admin);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminRequirement__adminUserWithTotp_2fa()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ADMIN);
|
||||||
|
|
||||||
|
$user = $this->generateRequestUserModel(['use_totp' => true, 'root_admin' => true]);
|
||||||
|
|
||||||
|
$this->assertTrue($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
$this->assertTrue($user->root_admin);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminRequirement__userWithWebauthn_2fa()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ADMIN);
|
||||||
|
|
||||||
|
/** @var \Pterodactyl\Models\User $user */
|
||||||
|
$user = User::factory()->has(WebauthnKey::factory()->count(1))->create(['use_totp' => false]);
|
||||||
|
$this->setRequestUserModel($user);
|
||||||
|
|
||||||
|
$this->assertFalse($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
$this->assertFalse($user->root_admin);
|
||||||
|
$this->assertNotEmpty($user->webauthnKeys);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminRequirement__adminUserWithWebauthn_2fa()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ADMIN);
|
||||||
|
|
||||||
|
/** @var \Pterodactyl\Models\User $user */
|
||||||
|
$user = User::factory()
|
||||||
|
->has(WebauthnKey::factory()->count(1))
|
||||||
|
->create(['use_totp' => false, 'root_admin' => true]);
|
||||||
|
$this->setRequestUserModel($user);
|
||||||
|
|
||||||
|
$this->assertFalse($user->use_totp);
|
||||||
|
$this->assertEmpty($user->totp_secret);
|
||||||
|
$this->assertEmpty($user->totp_authenticated_at);
|
||||||
|
$this->assertTrue($user->root_admin);
|
||||||
|
$this->assertNotEmpty($user->webauthnKeys);
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn(null);
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminRequirement__guestUser()
|
||||||
|
{
|
||||||
|
// Disable the 2FA requirement
|
||||||
|
config()->set('pterodactyl.auth.2fa_required', RequireTwoFactorAuthentication::LEVEL_ADMIN);
|
||||||
|
|
||||||
|
$this->setRequestUserModel();
|
||||||
|
|
||||||
|
$this->request->shouldReceive('getRequestUri')->withNoArgs()->andReturn('/auth/login');
|
||||||
|
$this->request->shouldReceive('route->getName')->withNoArgs()->andReturn('auth.login');
|
||||||
|
$this->request->shouldReceive('isJson')->withNoArgs()->andReturn(true);
|
||||||
|
|
||||||
|
$this->getMiddleware()->handle($this->request, $this->getClosureAssertions());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getMiddleware(): RequireTwoFactorAuthentication
|
||||||
|
{
|
||||||
|
return new RequireTwoFactorAuthentication($this->alerts);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue