Skip to content

Commit

Permalink
fix: can change email to an existing email (resolves #1826) (#1834)
Browse files Browse the repository at this point in the history
fix: can change email to an existing email
  • Loading branch information
jobara authored Jun 29, 2023
1 parent 6246a46 commit 5e0dd3c
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 9 deletions.
7 changes: 4 additions & 3 deletions app/Actions/Fortify/UpdateUserProfileInformation.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

namespace App\Actions\Fortify;

use App\Rules\UniqueUserEmail;
use App\Traits\UserEmailVerification;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Support\Str;
use Laravel\Fortify\Contracts\UpdatesUserProfileInformation;

class UpdateUserProfileInformation implements UpdatesUserProfileInformation
Expand All @@ -25,12 +26,12 @@ public function update($user, array $input): void
'string',
'email',
'max:255',
Rule::unique('users')->ignore($user->id),
new UniqueUserEmail($user->id),
],
])->validateWithBag('updateProfileInformation');

if (
$input['email'] !== $user->email &&
Str::lower($input['email']) !== $user->email &&
$user instanceof MustVerifyEmail
) {
$this->updateVerifiedUser($user, $input['email']);
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Controllers/IndividualController.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Spatie\LaravelOptions\Options;

class IndividualController extends Controller
Expand Down Expand Up @@ -307,7 +308,7 @@ public function updateCommunicationAndConsultationPreferences(UpdateIndividualCo

if (
$data['email'] !== ''
&& $data['email'] !== $user->email
&& Str::lower($data['email']) !== $user->email
&& $user instanceof MustVerifyEmail
) {
$this->updateVerifiedUser($user, $data['email']);
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Controllers/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Str;
use Spatie\LaravelOptions\Options;

class SettingsController extends Controller
Expand Down Expand Up @@ -196,7 +197,7 @@ public function updateCommunicationAndConsultationPreferences(UpdateCommunicatio
$individual = $user->individual;

if (
isset($data['email']) && $data['email'] !== $user->email && $user instanceof MustVerifyEmail
isset($data['email']) && Str::lower($data['email']) !== $user->email && $user instanceof MustVerifyEmail
) {
$this->updateVerifiedUser($user, $data['email']);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Enums\ContactPerson;
use App\Enums\EngagementFormat;
use App\Enums\MeetingType;
use App\Rules\UniqueUserEmail;
use App\Traits\ConditionallyRequireContactMethods;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
Expand Down Expand Up @@ -32,7 +33,7 @@ public function rules(): array
'string',
'email',
'max:255',
Rule::unique('users')->ignore($this->user()->id),
new UniqueUserEmail($this->user()->id),
],
'phone' => 'required_if:vrs,true|nullable|phone:CA',
'vrs' => 'nullable|boolean',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

use App\Enums\ContactPerson;
use App\Enums\MeetingType;
use App\Rules\UniqueUserEmail;
use App\Traits\ConditionallyRequireContactMethods;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Enum;
use Illuminate\Validation\Validator;

Expand All @@ -31,7 +31,7 @@ public function rules(): array
'string',
'email',
'max:255',
Rule::unique('users')->ignore($this->user()->id),
new UniqueUserEmail($this->user()->id),
],
'phone' => 'required_if:vrs,true|nullable|phone:CA',
'vrs' => 'nullable|boolean',
Expand Down
21 changes: 20 additions & 1 deletion app/Rules/UniqueUserEmail.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,28 @@

class UniqueUserEmail implements InvokableRule
{
public $id;

public $idColumn;

// Can use the $id and $idColumn to define a model to ignore. Similar to how Laravel's unique validation rule works
// see: https://laravel.com/docs/9.x/validation#rule-unique
public function __construct(mixed $id = null, ?string $idColumn = null)
{
$this->id = $id;
$this->idColumn = $idColumn ?? 'id';
}

public function __invoke($attribute, mixed $value, $fail): void
{
if (User::whereBlind($attribute, $attribute.'_index', Str::lower($value))->exists()) {
$exists = User::whereBlind($attribute, $attribute.'_index', Str::lower($value))
->when($this->id, function ($query, $role) {
$query->whereNot(function ($query) {
$query->where($this->idColumn, $this->id);
});
})
->exists();
if ($exists) {
$fail(__('A user with this email already exists.'));
}
}
Expand Down

0 comments on commit 5e0dd3c

Please sign in to comment.