Skip to content

Commit

Permalink
Merge pull request #24 from Laragear/feat/trait_tests
Browse files Browse the repository at this point in the history
[1.x] Adds tests for trait, fixing some methods.
  • Loading branch information
DarkGhostHunter authored Nov 11, 2022
2 parents afa5b62 + 89f1537 commit e2af6a8
Show file tree
Hide file tree
Showing 2 changed files with 271 additions and 14 deletions.
25 changes: 11 additions & 14 deletions src/WebAuthnAuthentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
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
Expand Down Expand Up @@ -39,20 +38,17 @@ public function webAuthnData(): array
*/
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));
}
}

/**
Expand All @@ -65,13 +61,14 @@ public function disableAllCredentials(string ...$except): void
{
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()]);
}
}

Expand Down
260 changes: 260 additions & 0 deletions tests/WebAuthnAuthenticationTest.php
Original file line number Diff line number Diff line change
@@ -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,
]);
}
}

0 comments on commit e2af6a8

Please sign in to comment.