diff --git a/app/Filament/Resources/Coupons/Tables/CouponsTable.php b/app/Filament/Resources/Coupons/Tables/CouponsTable.php index 99d68c9..167fc2b 100644 --- a/app/Filament/Resources/Coupons/Tables/CouponsTable.php +++ b/app/Filament/Resources/Coupons/Tables/CouponsTable.php @@ -4,6 +4,7 @@ namespace App\Filament\Resources\Coupons\Tables; use App\Filament\Tables\Filters\CreatedAtDateFilter; use Filament\Actions\ViewAction; +use Filament\Actions\DeleteAction; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; @@ -37,6 +38,7 @@ class CouponsTable ]) ->recordActions([ ViewAction::make(), + DeleteAction::make(), ]); } } diff --git a/app/Http/Controllers/VerificationController.php b/app/Http/Controllers/VerificationController.php index 643817a..316139f 100644 --- a/app/Http/Controllers/VerificationController.php +++ b/app/Http/Controllers/VerificationController.php @@ -120,17 +120,86 @@ class VerificationController extends Controller public function congratulations(): View|RedirectResponse { - if (! session()->has('coupon_code') && ! request()->cookie(self::DEVICE_COOKIE_NAME)) { + // #region agent log + $debugLog = static function (string $hypothesisId, string $message, array $data = []): void { + file_put_contents( + base_path('.cursor/debug-c4d726.log'), + json_encode([ + 'sessionId' => 'c4d726', + 'hypothesisId' => $hypothesisId, + 'location' => 'VerificationController::congratulations', + 'message' => $message, + 'data' => $data, + 'timestamp' => (int) round(microtime(true) * 1000), + ]).PHP_EOL, + FILE_APPEND + ); + }; + // #endregion + + $hasSessionCoupon = session()->has('coupon_code'); + $hasDeviceCookie = (bool) request()->cookie(self::DEVICE_COOKIE_NAME); + $sessionCode = session()->get('coupon_code'); + + // #region agent log + $debugLog('A', 'entry_state', [ + 'hasSessionCoupon' => $hasSessionCoupon, + 'hasDeviceCookie' => $hasDeviceCookie, + 'sessionCodePresent' => $sessionCode !== null && $sessionCode !== '', + 'verifyPhone' => session()->get('verify_phone'), + ]); + // #endregion + + if (! $hasSessionCoupon && ! $hasDeviceCookie) { + // #region agent log + $debugLog('B', 'redirect_no_session_or_cookie', []); + // #endregion + return redirect()->route('verification.index'); } - $code = session()->get('coupon_code'); + $code = null; + + if ($sessionCode && Coupon::query()->where('code', $sessionCode)->exists()) { + $code = $sessionCode; + + // #region agent log + $debugLog('E', 'session_code_db_validation', [ + 'codeFromSession' => $sessionCode, + 'existsInDb' => true, + ]); + // #endregion + } elseif ($sessionCode) { + session()->forget('coupon_code'); + + // #region agent log + $debugLog('E', 'session_code_db_validation', [ + 'codeFromSession' => $sessionCode, + 'existsInDb' => false, + 'action' => 'forgot_stale_session_code', + ]); + // #endregion + } if (! $code) { $phone = $this->phoneFromDeviceCookie(); + // #region agent log + $debugLog('C', 'cookie_phone_lookup', [ + 'phoneFromCookie' => $phone, + ]); + // #endregion + if ($phone) { $coupon = Coupon::query()->where('phone', $phone)->first(); + + // #region agent log + $debugLog('C', 'db_lookup_from_cookie', [ + 'phone' => $phone, + 'couponFound' => $coupon !== null, + ]); + // #endregion + if ($coupon) { $code = $coupon->code; session()->put('coupon_code', $code); @@ -139,7 +208,16 @@ class VerificationController extends Controller } if (! $code && session()->has('verify_phone')) { - $coupon = Coupon::query()->where('phone', session()->get('verify_phone'))->first(); + $verifyPhone = session()->get('verify_phone'); + $coupon = Coupon::query()->where('phone', $verifyPhone)->first(); + + // #region agent log + $debugLog('D', 'db_lookup_from_verify_phone', [ + 'verifyPhone' => $verifyPhone, + 'couponFound' => $coupon !== null, + ]); + // #endregion + if ($coupon) { $code = $coupon->code; session()->put('coupon_code', $code); @@ -147,11 +225,21 @@ class VerificationController extends Controller } if (! $code) { + // #region agent log + $debugLog('E', 'redirect_no_valid_code', []); + // #endregion + return redirect() ->route('verification.index') ->withoutCookie(self::DEVICE_COOKIE_NAME); } + // #region agent log + $debugLog('A', 'rendering_view', [ + 'code' => $code, + ]); + // #endregion + return view('verification.congratulations', [ 'code' => $code, ]); diff --git a/tests/Feature/VerificationFlowTest.php b/tests/Feature/VerificationFlowTest.php index 21dac10..1ea5299 100644 --- a/tests/Feature/VerificationFlowTest.php +++ b/tests/Feature/VerificationFlowTest.php @@ -146,6 +146,14 @@ class VerificationFlowTest extends TestCase ->assertSee($coupon->code); } + public function test_congratulations_redirects_when_session_coupon_missing_from_db(): void + { + $this->withSession(['coupon_code' => '9_STALE']) + ->get(route('verification.congratulations')) + ->assertRedirect(route('verification.index')) + ->assertSessionMissing('coupon_code'); + } + public function test_send_otp_is_rate_limited(): void { for ($i = 0; $i < 3; $i++) {