From 39a1f708a1f207cc3c5fdb83075554aac466d762 Mon Sep 17 00:00:00 2001 From: nexxo Date: Sat, 25 Jul 2026 18:29:35 +0200 Subject: [PATCH] fix(auth): reject signup with an existing customer email (account-claim guard) Co-Authored-By: Claude Opus 4.8 --- app/Actions/Fortify/CreateNewUser.php | 5 +++++ tests/Feature/Auth/RegisterTest.php | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/app/Actions/Fortify/CreateNewUser.php b/app/Actions/Fortify/CreateNewUser.php index ee2d712..cf4e428 100644 --- a/app/Actions/Fortify/CreateNewUser.php +++ b/app/Actions/Fortify/CreateNewUser.php @@ -2,6 +2,7 @@ namespace App\Actions\Fortify; +use App\Models\Customer; use App\Models\User; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; @@ -30,6 +31,10 @@ class CreateNewUser implements CreatesNewUsers 'email', 'max:255', Rule::unique(User::class), + // Never let public signup claim an existing (possibly not-yet- + // provisioned) customer's email — ensureUser() would later link + // that account and hand over the customer's portal. + Rule::unique(Customer::class, 'email'), ], 'password' => $this->passwordRules(), ])->validate(); diff --git a/tests/Feature/Auth/RegisterTest.php b/tests/Feature/Auth/RegisterTest.php index 7444c6e..af4bdd4 100644 --- a/tests/Feature/Auth/RegisterTest.php +++ b/tests/Feature/Auth/RegisterTest.php @@ -24,6 +24,17 @@ it('registers a new account and signs in', function () { $this->assertAuthenticatedAs($user); }); +it('refuses to register with an existing customer email (account-claim guard)', function () { + \App\Models\Customer::factory()->create(['email' => 'claim@signup.test']); + + $this->post(route('register.store'), [ + 'name' => 'Claimer', 'email' => 'claim@signup.test', + 'password' => 'password1234', 'password_confirmation' => 'password1234', + ])->assertSessionHasErrors('email'); + + expect(User::query()->where('email', 'claim@signup.test')->exists())->toBeFalse(); +}); + it('rejects a mismatched password confirmation', function () { $this->post(route('register.store'), [ 'name' => 'X',