diff --git a/app/Http/Controllers/SubscriptionController.php b/app/Http/Controllers/SubscriptionController.php index 51ba417..450842b 100644 --- a/app/Http/Controllers/SubscriptionController.php +++ b/app/Http/Controllers/SubscriptionController.php @@ -21,8 +21,8 @@ public function checkout(Request $request) { $priceId = $request->input('price_id'); - if (! $priceId) { - return back()->with('error', 'Please select a plan.'); + if (! $priceId || ! str_starts_with($priceId, 'pri_')) { + return back()->with('error', 'Please select a valid plan.'); } $checkout = $request->user()->checkout($priceId) diff --git a/resources/js/pages/pricing.tsx b/resources/js/pages/pricing.tsx index 86ef5b4..5b7856a 100644 --- a/resources/js/pages/pricing.tsx +++ b/resources/js/pages/pricing.tsx @@ -26,7 +26,20 @@ export default function Pricing() { const { auth, checkout: checkoutData } = usePage<{ auth: Auth; checkout?: Record }>().props; useEffect(() => { - if (checkoutData) { + if (window.Paddle) { + window.Paddle.Initialize({ + token: import.meta.env.VITE_PADDLE_CLIENT_SIDE_TOKEN, + eventCallback: (event: any) => { + if (event.name === 'checkout.closed') { + router.reload({ only: ['auth', 'checkout'] }); + } + }, + }); + } + }, []); + + useEffect(() => { + if (checkoutData && window.Paddle) { window.Paddle.Checkout.open(checkoutData); } }, [checkoutData]); diff --git a/routes/web.php b/routes/web.php index e69d6b3..32df73b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -8,6 +8,7 @@ use App\Http\Controllers\RegistryController; use App\Http\Controllers\SubscriptionController; use App\Http\Controllers\ThemesController; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::get('/', HomePageController::class)->name('home'); @@ -32,8 +33,14 @@ Route::post('/r/upload', [RegistryController::class, 'upload']); Route::post('/r/upload-raw', [RegistryController::class, 'uploadRaw']); -Route::middleware(['auth', 'verified', 'role:super-admin|admin'])->group(function () { - Route::inertia('dashboard', 'dashboard')->name('dashboard'); +Route::middleware(['auth', 'verified'])->group(function () { + Route::get('dashboard', function (Request $request) { + if ($request->user()->hasAnyRole(['super-admin', 'admin']) || $request->user()->subscribed()) { + return Inertia\Inertia::render('dashboard'); + } + + abort(403); + })->name('dashboard'); }); require __DIR__.'/settings.php'; diff --git a/tests/Feature/DashboardTest.php b/tests/Feature/DashboardTest.php index 8a168cc..24a52bb 100644 --- a/tests/Feature/DashboardTest.php +++ b/tests/Feature/DashboardTest.php @@ -41,3 +41,24 @@ $response = $this->get(route('dashboard')); $response->assertForbidden(); }); + +test('authenticated subscribed users can visit the dashboard', function () { + $this->seed(RolesAndPermissionsSeeder::class); + $user = User::factory()->create(); + $user->assignRole('guest'); + + // Mock the subscribed method + $user->subscriptions()->create([ + 'type' => 'default', + 'paddle_id' => 'sub_123', + 'status' => 'active', + 'trial_ends_at' => null, + 'paused_at' => null, + 'ends_at' => null, + ]); + + $this->actingAs($user); + + $response = $this->get(route('dashboard')); + $response->assertOk(); +}); diff --git a/tests/Feature/SubscriptionTest.php b/tests/Feature/SubscriptionTest.php index a867d6a..a958309 100644 --- a/tests/Feature/SubscriptionTest.php +++ b/tests/Feature/SubscriptionTest.php @@ -32,4 +32,31 @@ public function test_subscription_edit_page_is_accessible_to_authenticated_user( $response->assertStatus(200); } + + public function test_checkout_requires_valid_price_id() + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->post('/settings/subscription/checkout', [ + 'price_id' => 'invalid_id', + ]); + + $response->assertSessionHas('error', 'Please select a valid plan.'); + } + + public function test_checkout_returns_paddle_options() + { + $this->markTestSkipped('Paddle API interaction requires valid API keys or more extensive mocking.'); + + config(['cashier.api_key' => 'test_api_key']); + config(['cashier.seller_id' => 'test_seller_id']); + + $user = User::factory()->create(); + + $response = $this->actingAs($user)->post('/settings/subscription/checkout', [ + 'price_id' => 'pri_123', + ]); + + $response->assertSessionHas('checkout'); + } }