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