diff --git a/app/Jobs/ApiTokenExpirationWarningJob.php b/app/Jobs/ApiTokenExpirationWarningJob.php index 810919c6a..e7b34248e 100644 --- a/app/Jobs/ApiTokenExpirationWarningJob.php +++ b/app/Jobs/ApiTokenExpirationWarningJob.php @@ -42,6 +42,9 @@ public function handle(): void } $warningSentAt = now(); + + $team->notify(new ApiTokenExpiringNotification($token)); + $markedAsSent = PersonalAccessToken::query() ->whereKey($token->getKey()) ->whereNotNull('expires_at') @@ -55,7 +58,6 @@ public function handle(): void } $token->forceFill(['api_token_expiration_warning_sent_at' => $warningSentAt]); - $team->notify(new ApiTokenExpiringNotification($token)); } }); } diff --git a/tests/Feature/ApiTokenExpirationWarningTest.php b/tests/Feature/ApiTokenExpirationWarningTest.php index 67380f047..beea1f126 100644 --- a/tests/Feature/ApiTokenExpirationWarningTest.php +++ b/tests/Feature/ApiTokenExpirationWarningTest.php @@ -6,6 +6,7 @@ use App\Models\User; use App\Notifications\ApiTokenExpiringNotification; use Carbon\Carbon; +use Illuminate\Contracts\Notifications\Dispatcher; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Notification; @@ -50,6 +51,21 @@ function createTokenExpiring(User $user, Team $team, ?Carbon $expiresAt, ?Carbon expect($token->fresh()->api_token_expiration_warning_sent_at)->not->toBeNull(); }); + test('does not mark token as warned when notification fails', function () { + $token = createTokenExpiring($this->user, $this->team, now()->addHours(23)); + $dispatcher = Mockery::mock(Dispatcher::class); + $dispatcher->shouldReceive('send') + ->once() + ->andThrow(new RuntimeException('Notification failed')); + + $this->app->instance(Dispatcher::class, $dispatcher); + + expect(fn () => (new ApiTokenExpirationWarningJob)->handle()) + ->toThrow(RuntimeException::class, 'Notification failed'); + + expect($token->fresh()->api_token_expiration_warning_sent_at)->toBeNull(); + }); + test('database marker prevents duplicate warnings on repeat runs', function () { createTokenExpiring($this->user, $this->team, now()->addHours(12));