fix(api-tokens): mark expiration warning after notification

Ensure failed token expiration warning notifications do not persist the warning marker, allowing the job to retry later.
This commit is contained in:
Andras Bacsai 2026-05-13 10:28:32 +02:00
parent 3911a0305c
commit 1522c510cf
2 changed files with 19 additions and 1 deletions

View file

@ -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));
}
});
}

View file

@ -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));