Merge pull request #24 from Laragear/feat/trait_tests
[1.x] Adds tests for trait, fixing some methods.
This commit is contained in:
@@ -7,7 +7,6 @@ use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
use JetBrains\PhpStorm\ArrayShape;
|
||||
use Laragear\WebAuthn\Models\WebAuthnCredential;
|
||||
use function in_array;
|
||||
|
||||
/**
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \Laragear\WebAuthn\Models\WebAuthnCredential> $webAuthnCredentials
|
||||
@@ -39,20 +38,17 @@ trait WebAuthnAuthentication
|
||||
*/
|
||||
public function flushCredentials(string ...$except): void
|
||||
{
|
||||
if ($this->relationLoaded('webAuthnCredentials') && $this->webAuthnCredentials instanceof Collection) {
|
||||
$partitioned = $this->webAuthnCredentials
|
||||
->partition(static function (WebAuthnCredential $credential) use ($except): bool {
|
||||
return in_array($credential->getKey(), $except, true);
|
||||
});
|
||||
|
||||
$partitioned->first()->each->delete();
|
||||
|
||||
$this->setRelation('webAuthnCredentials', $partitioned->last());
|
||||
if (! $this->relationLoaded('webAuthnCredentials')) {
|
||||
$this->webAuthnCredentials()->whereKeyNot($except)->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->webAuthnCredentials()->whereKeyNot($except)->delete();
|
||||
if ($this->webAuthnCredentials instanceof Collection && $this->webAuthnCredentials->isNotEmpty()) {
|
||||
$this->webAuthnCredentials->whereNotIn('id', $except)->each->delete();
|
||||
|
||||
$this->setRelation('webAuthnCredentials', $this->webAuthnCredentials->whereIn('id', $except));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,13 +61,14 @@ trait WebAuthnAuthentication
|
||||
{
|
||||
if ($this->relationLoaded('webAuthnCredentials') && $this->webAuthnCredentials instanceof Collection) {
|
||||
$this->webAuthnCredentials
|
||||
->each(static function (WebAuthnCredential $credential) use ($except): bool {
|
||||
if ($credential->isEnabled() && in_array($credential->getKey(), $except, true)) {
|
||||
->when($except)->whereNotIn('id', $except)
|
||||
->each(static function (WebAuthnCredential $credential): void {
|
||||
if ($credential->isEnabled()) {
|
||||
$credential->disable();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$this->webAuthnCredentials()->whereKeyNot($except)->update(['disabled_at' => Date::now()]);
|
||||
$this->webAuthnCredentials()->whereKeyNot($except)->whereEnabled()->update(['disabled_at' => Date::now()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
260
tests/WebAuthnAuthenticationTest.php
Normal file
260
tests/WebAuthnAuthenticationTest.php
Normal file
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Laragear\WebAuthn\Models\WebAuthnCredential;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use function now;
|
||||
|
||||
class WebAuthnAuthenticationTest extends TestCase
|
||||
{
|
||||
protected Stubs\WebAuthnAuthenticatableUser $user;
|
||||
|
||||
protected function afterRefreshingDatabase(): void
|
||||
{
|
||||
$this->user = Stubs\WebAuthnAuthenticatableUser::forceCreate([
|
||||
'name' => FakeAuthenticator::ATTESTATION_USER['displayName'],
|
||||
'email' => FakeAuthenticator::ATTESTATION_USER['name'],
|
||||
'password' => 'test_password',
|
||||
]);
|
||||
|
||||
$this->user->webAuthnCredentials()->make()->forceFill([
|
||||
'id' => 'test_id',
|
||||
'user_id' => Uuid::NIL,
|
||||
'counter' => 0,
|
||||
'rp_id' => 'http://localhost',
|
||||
'origin' => 'http://localhost:8000',
|
||||
'aaguid' => Uuid::NIL,
|
||||
'public_key' => 'test_key',
|
||||
'attestation_format' => 'none',
|
||||
])->save();
|
||||
}
|
||||
|
||||
public function test_shows_webauthn_data(): void
|
||||
{
|
||||
static::assertSame([
|
||||
'name' => FakeAuthenticator::ATTESTATION_USER['name'],
|
||||
'displayName' => FakeAuthenticator::ATTESTATION_USER['displayName'],
|
||||
], $this->user->webAuthnData());
|
||||
}
|
||||
|
||||
public function test_flushes_all_credentials(): void
|
||||
{
|
||||
$this->user->webAuthnCredentials()->make()->forceFill([
|
||||
'id' => 'test_id_2',
|
||||
'user_id' => Uuid::NIL,
|
||||
'counter' => 10,
|
||||
'rp_id' => 'http://localhost',
|
||||
'origin' => 'http://localhost:8000',
|
||||
'aaguid' => Uuid::NIL,
|
||||
'public_key' => 'test_key',
|
||||
'attestation_format' => 'none',
|
||||
'disabled_at' => now()
|
||||
])->save();
|
||||
|
||||
$this->user->flushCredentials();
|
||||
|
||||
$this->assertDatabaseCount(WebAuthnCredential::class, 0);
|
||||
}
|
||||
|
||||
public function test_flushes_all_credentials_using_loaded_relation(): void
|
||||
{
|
||||
$this->user->webAuthnCredentials()->make()->forceFill([
|
||||
'id' => 'test_id_2',
|
||||
'user_id' => Uuid::NIL,
|
||||
'counter' => 10,
|
||||
'rp_id' => 'http://localhost',
|
||||
'origin' => 'http://localhost:8000',
|
||||
'aaguid' => Uuid::NIL,
|
||||
'public_key' => 'test_key',
|
||||
'attestation_format' => 'none',
|
||||
'disabled_at' => now()
|
||||
])->save();
|
||||
|
||||
$this->user->load('webAuthnCredentials');
|
||||
|
||||
static::assertCount(2, $this->user->webAuthnCredentials);
|
||||
|
||||
$this->user->flushCredentials();
|
||||
|
||||
static::assertEmpty($this->user->webAuthnCredentials);
|
||||
|
||||
$this->assertDatabaseCount(WebAuthnCredential::class, 0);
|
||||
}
|
||||
|
||||
public function test_flushes_all_credentials_except_given_id(): void
|
||||
{
|
||||
$this->user->webAuthnCredentials()->make()->forceFill([
|
||||
'id' => 'test_id_2',
|
||||
'user_id' => Uuid::NIL,
|
||||
'counter' => 10,
|
||||
'rp_id' => 'http://localhost',
|
||||
'origin' => 'http://localhost:8000',
|
||||
'aaguid' => Uuid::NIL,
|
||||
'public_key' => 'test_key',
|
||||
'attestation_format' => 'none',
|
||||
'disabled_at' => now()
|
||||
])->save();
|
||||
|
||||
$this->user->flushCredentials('test_id_2');
|
||||
|
||||
$this->assertDatabaseCount(WebAuthnCredential::class, 1);
|
||||
$this->assertDatabaseMissing(WebAuthnCredential::class, [
|
||||
'id' => 'test_id'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_flushes_all_credentials_using_loaded_relation_except_given_id(): void
|
||||
{
|
||||
$this->user->webAuthnCredentials()->make()->forceFill([
|
||||
'id' => 'test_id_2',
|
||||
'user_id' => Uuid::NIL,
|
||||
'counter' => 10,
|
||||
'rp_id' => 'http://localhost',
|
||||
'origin' => 'http://localhost:8000',
|
||||
'aaguid' => Uuid::NIL,
|
||||
'public_key' => 'test_key',
|
||||
'attestation_format' => 'none',
|
||||
'disabled_at' => now()
|
||||
])->save();
|
||||
|
||||
$this->user->load('webAuthnCredentials');
|
||||
|
||||
static::assertCount(2, $this->user->webAuthnCredentials);
|
||||
|
||||
$this->user->flushCredentials('test_id_2');
|
||||
|
||||
static::assertCount(1, $this->user->webAuthnCredentials);
|
||||
static::assertTrue($this->user->webAuthnCredentials->contains('id', 'test_id_2'));
|
||||
|
||||
$this->assertDatabaseCount(WebAuthnCredential::class, 1);
|
||||
$this->assertDatabaseMissing(WebAuthnCredential::class, [
|
||||
'id' => 'test_id'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_disables_all_credentials(): void
|
||||
{
|
||||
$this->travelTo(Carbon::now()->startOfSecond());
|
||||
|
||||
$this->user->webAuthnCredentials()->make()->forceFill([
|
||||
'id' => 'test_id_2',
|
||||
'user_id' => Uuid::NIL,
|
||||
'counter' => 10,
|
||||
'rp_id' => 'http://localhost',
|
||||
'origin' => 'http://localhost:8000',
|
||||
'aaguid' => Uuid::NIL,
|
||||
'public_key' => 'test_key',
|
||||
'attestation_format' => 'none',
|
||||
'disabled_at' => now()->subMinute()
|
||||
])->save();
|
||||
|
||||
$this->user->disableAllCredentials();
|
||||
|
||||
$this->assertDatabaseCount(WebAuthnCredential::class, 2);
|
||||
$this->assertDatabaseHas(WebAuthnCredential::class, [
|
||||
'id' => 'test_id',
|
||||
'disabled_at' => now()->toDateTimeString(),
|
||||
]);
|
||||
$this->assertDatabaseHas(WebAuthnCredential::class, [
|
||||
'id' => 'test_id_2',
|
||||
'disabled_at' => now()->subMinute()->toDateTimeString(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_disables_all_credentials_with_loaded_relation(): void
|
||||
{
|
||||
$this->travelTo(Carbon::now()->startOfSecond());
|
||||
|
||||
$this->user->webAuthnCredentials()->make()->forceFill([
|
||||
'id' => 'test_id_2',
|
||||
'user_id' => Uuid::NIL,
|
||||
'counter' => 10,
|
||||
'rp_id' => 'http://localhost',
|
||||
'origin' => 'http://localhost:8000',
|
||||
'aaguid' => Uuid::NIL,
|
||||
'public_key' => 'test_key',
|
||||
'attestation_format' => 'none',
|
||||
'disabled_at' => now()->subMinute()
|
||||
])->save();
|
||||
|
||||
$this->user->load('webAuthnCredentials');
|
||||
|
||||
$this->user->disableAllCredentials();
|
||||
|
||||
static::assertTrue($this->user->webAuthnCredentials->firstWhere('id', 'test_id')->isDisabled());
|
||||
static::assertTrue($this->user->webAuthnCredentials->firstWhere('id', 'test_id_2')->isDisabled());
|
||||
|
||||
$this->assertDatabaseCount(WebAuthnCredential::class, 2);
|
||||
$this->assertDatabaseHas(WebAuthnCredential::class, [
|
||||
'id' => 'test_id',
|
||||
'disabled_at' => now()->toDateTimeString(),
|
||||
]);
|
||||
$this->assertDatabaseHas(WebAuthnCredential::class, [
|
||||
'id' => 'test_id_2',
|
||||
'disabled_at' => now()->subMinute()->toDateTimeString(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_disables_all_credentials_except_one(): void
|
||||
{
|
||||
$this->travelTo(Carbon::now()->startOfSecond());
|
||||
|
||||
$this->user->webAuthnCredentials()->make()->forceFill([
|
||||
'id' => 'test_id_2',
|
||||
'user_id' => Uuid::NIL,
|
||||
'counter' => 10,
|
||||
'rp_id' => 'http://localhost',
|
||||
'origin' => 'http://localhost:8000',
|
||||
'aaguid' => Uuid::NIL,
|
||||
'public_key' => 'test_key',
|
||||
'attestation_format' => 'none',
|
||||
])->save();
|
||||
|
||||
$this->user->disableAllCredentials('test_id');
|
||||
|
||||
$this->assertDatabaseCount(WebAuthnCredential::class, 2);
|
||||
$this->assertDatabaseHas(WebAuthnCredential::class, [
|
||||
'id' => 'test_id',
|
||||
'disabled_at' => null,
|
||||
]);
|
||||
$this->assertDatabaseHas(WebAuthnCredential::class, [
|
||||
'id' => 'test_id_2',
|
||||
'disabled_at' => now()->toDateTimeString(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_disables_all_credentials_with_loaded_relation_except_one(): void
|
||||
{
|
||||
$this->travelTo(Carbon::now()->startOfSecond());
|
||||
|
||||
$this->user->webAuthnCredentials()->make()->forceFill([
|
||||
'id' => 'test_id_2',
|
||||
'user_id' => Uuid::NIL,
|
||||
'counter' => 10,
|
||||
'rp_id' => 'http://localhost',
|
||||
'origin' => 'http://localhost:8000',
|
||||
'aaguid' => Uuid::NIL,
|
||||
'public_key' => 'test_key',
|
||||
'attestation_format' => 'none',
|
||||
])->save();
|
||||
|
||||
$this->user->load('webAuthnCredentials');
|
||||
|
||||
$this->user->disableAllCredentials('test_id_2');
|
||||
|
||||
static::assertTrue($this->user->webAuthnCredentials->firstWhere('id', 'test_id')->isDisabled());
|
||||
static::assertFalse($this->user->webAuthnCredentials->firstWhere('id', 'test_id_2')->isDisabled());
|
||||
|
||||
$this->assertDatabaseCount(WebAuthnCredential::class, 2);
|
||||
$this->assertDatabaseHas(WebAuthnCredential::class, [
|
||||
'id' => 'test_id',
|
||||
'disabled_at' => now()->toDateTimeString(),
|
||||
]);
|
||||
$this->assertDatabaseHas(WebAuthnCredential::class, [
|
||||
'id' => 'test_id_2',
|
||||
'disabled_at' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user