Skip to content

Commit aa5b429

Browse files
Static analysis using larastan (#36)
* Setup larastan * Add unsage static usage to ignored larastan errors * Add known/safe PHPStan errors * Split up EmitsAuthenticationEvents * Larastan: Typehint Eloquent Builder for 'unknowns' * GH Actions: Remove continue-on-error from Larastan --------- Co-authored-by: Claudio Dekker <[email protected]>
1 parent 54e9b65 commit aa5b429

19 files changed

+193
-111
lines changed

.github/workflows/larastan.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Larastan Static Analysis
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- '*.x'
8+
pull_request:
9+
10+
jobs:
11+
larastan:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v3
17+
18+
- name: Setup PHP
19+
uses: shivammathur/setup-php@v2
20+
with:
21+
php-version: 8.1
22+
tools: composer:v2
23+
24+
- name: Install dependencies
25+
uses: nick-fields/retry@v2
26+
with:
27+
timeout_minutes: 5
28+
max_attempts: 5
29+
command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress
30+
31+
- name: Run Larastan
32+
run: vendor/bin/phpstan

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"orchestra/testbench": "^6.5|^7.0",
2222
"phpunit/phpunit": "^8.4|^9.5.8",
2323
"roave/security-advisories": "dev-latest",
24-
"symplify/monorepo-builder": "11.2.2.72"
24+
"symplify/monorepo-builder": "11.2.2.72",
25+
"nunomaduro/larastan": "^2.0"
2526
},
2627
"autoload": {
2728
"psr-4": {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace ClaudioDekker\LaravelAuth\Events\Mixins;
4+
5+
use ClaudioDekker\LaravelAuth\Events\Authenticated;
6+
use Illuminate\Contracts\Auth\Authenticatable;
7+
use Illuminate\Http\Request;
8+
use Illuminate\Support\Facades\Event;
9+
10+
trait EmitsAuthenticatedEvent
11+
{
12+
/**
13+
* Emits an event indicating that the user was fully authenticated.
14+
*/
15+
protected function emitAuthenticatedEvent(Request $request, Authenticatable $user): void
16+
{
17+
Event::dispatch(new Authenticated($request, $user));
18+
}
19+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace ClaudioDekker\LaravelAuth\Events\Mixins;
4+
5+
use Illuminate\Auth\Events\Lockout;
6+
use Illuminate\Http\Request;
7+
use Illuminate\Support\Facades\Event;
8+
9+
trait EmitsLockoutEvent
10+
{
11+
/**
12+
* Emits an event indicating that the user has been locked out for a while.
13+
*/
14+
protected function emitLockoutEvent(Request $request): void
15+
{
16+
Event::dispatch(new Lockout($request));
17+
}
18+
}

packages/core/src/Http/Concerns/Challenges/PasswordChallenge.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22

33
namespace ClaudioDekker\LaravelAuth\Http\Concerns\Challenges;
44

5-
use ClaudioDekker\LaravelAuth\Http\Concerns\EmitsAuthenticationEvents;
65
use ClaudioDekker\LaravelAuth\Http\Concerns\InteractsWithRateLimiting;
76
use Illuminate\Http\Request;
87
use Illuminate\Support\Facades\Auth;
98

109
trait PasswordChallenge
1110
{
12-
use EmitsAuthenticationEvents;
1311
use InteractsWithRateLimiting;
1412

1513
/**

packages/core/src/Http/Concerns/Challenges/PublicKeyChallenge.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
namespace ClaudioDekker\LaravelAuth\Http\Concerns\Challenges;
44

55
use ClaudioDekker\LaravelAuth\CredentialType;
6-
use ClaudioDekker\LaravelAuth\Http\Concerns\EmitsAuthenticationEvents;
76
use ClaudioDekker\LaravelAuth\Http\Concerns\InteractsWithRateLimiting;
8-
use ClaudioDekker\LaravelAuth\Http\Traits\EmailBased;
97
use ClaudioDekker\LaravelAuth\LaravelAuth;
108
use ClaudioDekker\LaravelAuth\Methods\WebAuthn\Contracts\WebAuthnContract as WebAuthn;
119
use ClaudioDekker\LaravelAuth\Methods\WebAuthn\Exceptions\InvalidPublicKeyCredentialException;
@@ -22,8 +20,6 @@
2220

2321
trait PublicKeyChallenge
2422
{
25-
use EmailBased;
26-
use EmitsAuthenticationEvents;
2723
use InteractsWithRateLimiting;
2824

2925
/**

packages/core/src/Http/Concerns/Challenges/TotpChallenge.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace ClaudioDekker\LaravelAuth\Http\Concerns\Challenges;
44

55
use ClaudioDekker\LaravelAuth\CredentialType;
6-
use ClaudioDekker\LaravelAuth\Http\Concerns\EmitsAuthenticationEvents;
76
use ClaudioDekker\LaravelAuth\Http\Concerns\InteractsWithRateLimiting;
87
use ClaudioDekker\LaravelAuth\LaravelAuth;
98
use ClaudioDekker\LaravelAuth\Methods\Totp\Contracts\TotpContract as Totp;
@@ -14,7 +13,6 @@
1413

1514
trait TotpChallenge
1615
{
17-
use EmitsAuthenticationEvents;
1816
use InteractsWithRateLimiting;
1917

2018
/**

packages/core/src/Http/Concerns/EmitsAuthenticationEvents.php

Lines changed: 0 additions & 77 deletions
This file was deleted.

packages/core/src/Http/Concerns/Login/PasskeyBasedAuthentication.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use App\Models\User;
66
use ClaudioDekker\LaravelAuth\CredentialType;
7+
use ClaudioDekker\LaravelAuth\Events\Mixins\EmitsLockoutEvent;
78
use ClaudioDekker\LaravelAuth\Http\Concerns\InteractsWithRateLimiting;
89
use ClaudioDekker\LaravelAuth\LaravelAuth;
910
use ClaudioDekker\LaravelAuth\Methods\WebAuthn\Contracts\WebAuthnContract as WebAuthn;
@@ -19,6 +20,7 @@
1920

2021
trait PasskeyBasedAuthentication
2122
{
23+
use EmitsLockoutEvent;
2224
use InteractsWithRateLimiting;
2325

2426
/**
@@ -167,7 +169,10 @@ protected function validatePasskey(Request $request, PublicKeyCredentialRequestO
167169
*/
168170
protected function resolveUserFromPasskey(Request $request, CredentialAttributes $credential): Authenticatable
169171
{
170-
return User::query()
172+
/** @var \Illuminate\Database\Eloquent\Builder $query */
173+
$query = User::query();
174+
175+
return $query
171176
->where('has_password', false)
172177
->findOrFail($credential->userHandle());
173178
}

packages/core/src/Http/Concerns/Login/PasswordBasedAuthentication.php

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44

55
use App\Models\User;
66
use ClaudioDekker\LaravelAuth\CredentialType;
7+
use ClaudioDekker\LaravelAuth\Events\Mixins\EmitsLockoutEvent;
8+
use ClaudioDekker\LaravelAuth\Events\MultiFactorChallenged;
79
use ClaudioDekker\LaravelAuth\Http\Concerns\InteractsWithRateLimiting;
810
use ClaudioDekker\LaravelAuth\LaravelAuth;
911
use Illuminate\Contracts\Auth\Authenticatable;
1012
use Illuminate\Http\Request;
1113
use Illuminate\Support\Collection;
14+
use Illuminate\Support\Facades\Event;
1215
use Illuminate\Support\Facades\Hash;
1316

1417
trait PasswordBasedAuthentication
1518
{
19+
use EmitsLockoutEvent;
1620
use InteractsWithRateLimiting;
1721

1822
/**
@@ -81,7 +85,10 @@ protected function validatePasswordBasedRequest(Request $request): void
8185
*/
8286
protected function resolvePasswordBasedUser(Request $request): ?Authenticatable
8387
{
84-
return User::query()
88+
/** @var \Illuminate\Database\Eloquent\Builder $query */
89+
$query = User::query();
90+
91+
return $query
8592
->where('has_password', true)
8693
->where($this->usernameField(), $request->input($this->usernameField()))
8794
->first();
@@ -124,6 +131,18 @@ protected function fetchMultiFactorCredentials(Authenticatable $user): Collectio
124131
->get();
125132
}
126133

134+
/**
135+
* Determines the preferred multi-factor authentication method.
136+
*/
137+
protected function determinePreferredMultiFactorMethod(Authenticatable $user, Collection $credentials): CredentialType
138+
{
139+
if ($credentials->pluck('type')->contains(CredentialType::PUBLIC_KEY)) {
140+
return CredentialType::PUBLIC_KEY;
141+
}
142+
143+
return CredentialType::TOTP;
144+
}
145+
127146
/**
128147
* Prepares the details necessary for multi-factor authentication.
129148
*/
@@ -135,14 +154,10 @@ protected function prepareMultiFactorAuthenticationDetails(Request $request, Aut
135154
}
136155

137156
/**
138-
* Determines the preferred multi-factor authentication method.
157+
* Emits an event indicating the user received a multi-factor authentication challenge.
139158
*/
140-
protected function determinePreferredMultiFactorMethod(Authenticatable $user, Collection $credentials): CredentialType
159+
protected function emitMultiFactorChallengedEvent(Request $request, Authenticatable $user): void
141160
{
142-
if ($credentials->pluck('type')->contains(CredentialType::PUBLIC_KEY)) {
143-
return CredentialType::PUBLIC_KEY;
144-
}
145-
146-
return CredentialType::TOTP;
161+
Event::dispatch(new MultiFactorChallenged($request, $user));
147162
}
148163
}

packages/core/src/Http/Concerns/Registration/PasskeyBasedRegistration.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,10 @@ protected function validatePasskeyBasedInitializationRequest(Request $request):
153153
*/
154154
protected function claimPasswordlessUser(Request $request): Authenticatable
155155
{
156-
return User::create([
156+
/** @var \Illuminate\Database\Eloquent\Builder $query */
157+
$query = User::query();
158+
159+
return $query->create([
157160
'email' => $request->input('email'),
158161
$this->usernameField() => $request->input($this->usernameField()),
159162
'name' => $request->name,
@@ -170,7 +173,10 @@ protected function claimPasswordlessUser(Request $request): Authenticatable
170173
*/
171174
protected function releaseClaimedPasswordlessUser(Request $request, $userId)
172175
{
173-
return User::where('id', $userId)->firstOrFail()->delete();
176+
/** @var \Illuminate\Database\Eloquent\Builder $query */
177+
$query = User::query();
178+
179+
return $query->where('id', $userId)->firstOrFail()->delete();
174180
}
175181

176182
/**
@@ -240,7 +246,10 @@ protected function validateAndPrepareCredentialAttributes(Request $request, Publ
240246
*/
241247
protected function resolveUserFromPasskeyCreationOptions(PublicKeyCredentialCreationOptions $options): Authenticatable
242248
{
243-
return User::findOrFail($options->user()->id());
249+
/** @var \Illuminate\Database\Eloquent\Builder $query */
250+
$query = User::query();
251+
252+
return $query->findOrFail($options->user()->id());
244253
}
245254

246255
/**

packages/core/src/Http/Concerns/Registration/PasswordBasedRegistration.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ protected function validatePasswordBasedRequest(Request $request): void
4848
*/
4949
protected function createPasswordBasedUser(Request $request): Authenticatable
5050
{
51-
return User::create([
51+
/** @var \Illuminate\Database\Eloquent\Builder $query */
52+
$query = User::query();
53+
54+
return $query->create([
5255
'email' => $request->input('email'),
5356
$this->usernameField() => $request->input($this->usernameField()),
5457
'name' => $request->name,

packages/core/src/Http/Controllers/AccountRecoveryRequestController.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace ClaudioDekker\LaravelAuth\Http\Controllers;
44

55
use App\Models\User;
6-
use ClaudioDekker\LaravelAuth\Http\Concerns\EmitsAuthenticationEvents;
6+
use ClaudioDekker\LaravelAuth\Events\Mixins\EmitsLockoutEvent;
77
use ClaudioDekker\LaravelAuth\Http\Concerns\InteractsWithRateLimiting;
88
use ClaudioDekker\LaravelAuth\Notifications\AccountRecoveryNotification;
99
use Illuminate\Contracts\Auth\Authenticatable;
@@ -13,7 +13,7 @@
1313
abstract class AccountRecoveryRequestController
1414
{
1515
use InteractsWithRateLimiting;
16-
use EmitsAuthenticationEvents;
16+
use EmitsLockoutEvent;
1717

1818
/**
1919
* Handles the situation in which account recovery has already been requested.
@@ -113,7 +113,10 @@ protected function validateRecoveryRequest(Request $request): void
113113
*/
114114
protected function getUser(Request $request)
115115
{
116-
return User::query()
116+
/** @var \Illuminate\Database\Eloquent\Builder $query */
117+
$query = User::query();
118+
119+
return $query
117120
->where('email', $request->input('email'))
118121
->first();
119122
}

0 commit comments

Comments
 (0)