From 66d8398e973f17bbb42986331774e5320ed8bd43 Mon Sep 17 00:00:00 2001 From: Kevin Adametz Date: Fri, 11 Sep 2026 10:34:38 +0000 Subject: [PATCH] api: Token-Gate erkennt aktive Stripe-Abos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neukunden, die per Stripe buchen (STR-Kreis), konnten keine API-Tokens erstellen: ApiAccessEligibilityService prüfte nur user_payment_options (MAN-Kreis) und die letzte Legacy-Rechnung, nicht das Cashier-Abo. Jetzt zählt subscribed() wie in User::hasActiveBooking() ebenfalls. Auslöser: Ticket press@intratec.us (Starter, STR-00008 bezahlt, „Create tokens" trotzdem gesperrt). Co-Authored-By: Claude Opus 5 (1M context) --- .../Api/ApiAccessEligibilityService.php | 15 ++++++++--- .../ApiAccessEligibilityServiceTest.php | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/app/Services/Api/ApiAccessEligibilityService.php b/app/Services/Api/ApiAccessEligibilityService.php index 520cd96e..647f9378 100644 --- a/app/Services/Api/ApiAccessEligibilityService.php +++ b/app/Services/Api/ApiAccessEligibilityService.php @@ -4,6 +4,12 @@ namespace App\Services\Api; use App\Models\User; +/** + * Token-Gate des hybriden Rechnungsmodells: freigeschaltet ist, wer ein + * aktives Stripe-Abo (Cashier, STR-Kreis), eine laufende Zahlungsoption + * (MAN-Kreis/Bestandsschutz) oder eine bezahlte letzte Legacy-Rechnung hat — + * spiegelbildlich zu User::hasActiveBooking(). + */ class ApiAccessEligibilityService { public function canCreateToken(User $user): bool @@ -17,16 +23,19 @@ class ApiAccessEligibilityService return 'Ihr Benutzerkonto ist nicht aktiv. API-Tokens können nur für aktive Benutzer erstellt werden.'; } - if ($user->hasActivePaymentOption() || $this->hasPaidLegacyInvoice($user)) { + if ($user->subscribed() || $user->hasActivePaymentOption() || $this->hasPaidLegacyInvoice($user)) { return null; } - return 'API-Tokens werden erst freigeschaltet, wenn ein aktiver Zahlungsstatus oder freigegebener Bestandsschutz vorliegt.'; + return 'API-Tokens werden erst freigeschaltet, wenn ein aktives Abo, ein aktiver Zahlungsstatus oder freigegebener Bestandsschutz vorliegt.'; } + /** + * Legacy-Pfad für Altkunden ohne Zahlungsoption: die zuletzt gestellte + * Legacy-Rechnung muss bezahlt sein. + */ private function hasPaidLegacyInvoice(User $user): bool { - // Bewusstes Verhalten dieses Gates: ohne Legacy-Rechnung kein Zugang. return $user->latestLegacyInvoice()?->status === 'paid'; } } diff --git a/tests/Feature/ApiAccessEligibilityServiceTest.php b/tests/Feature/ApiAccessEligibilityServiceTest.php index a3880999..f2d24365 100644 --- a/tests/Feature/ApiAccessEligibilityServiceTest.php +++ b/tests/Feature/ApiAccessEligibilityServiceTest.php @@ -46,6 +46,33 @@ test('token gate denies when latest legacy invoice is unpaid even if an older on expect((new ApiAccessEligibilityService)->canCreateToken($user))->toBeFalse(); }); +test('token gate grants access for an active stripe subscription', function () { + $user = User::factory()->create(['is_active' => true]); + $user->subscriptions()->create([ + 'type' => 'default', + 'stripe_id' => 'sub_test_api_gate', + 'stripe_status' => 'active', + 'stripe_price' => 'price_starter', + 'quantity' => 1, + ]); + + expect((new ApiAccessEligibilityService)->canCreateToken($user))->toBeTrue(); +}); + +test('token gate denies for a stripe subscription that has ended', function () { + $user = User::factory()->create(['is_active' => true]); + $user->subscriptions()->create([ + 'type' => 'default', + 'stripe_id' => 'sub_test_api_gate_ended', + 'stripe_status' => 'canceled', + 'stripe_price' => 'price_starter', + 'quantity' => 1, + 'ends_at' => now()->subDay(), + ]); + + expect((new ApiAccessEligibilityService)->canCreateToken($user))->toBeFalse(); +}); + test('token gate denies when there is no legacy invoice and no active payment option', function () { $user = User::factory()->create(['is_active' => true]);