mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
fix(auth): remove the unused Fortify profile route that bypassed the SSO email lock
PUT /user/profile-information changed the email with no SSO check and no verification. The profile page has its own verified email change, so the Fortify feature, its action and its binding are removed.
This commit is contained in:
@@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Laravel\Fortify\Contracts\UpdatesUserProfileInformation;
|
||||
|
||||
class UpdateUserProfileInformation implements UpdatesUserProfileInformation
|
||||
{
|
||||
/**
|
||||
* Validate and update the given user's profile information.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
public function update(User $user, array $input): void
|
||||
{
|
||||
$changedFields = collect(['name', 'email'])
|
||||
->filter(fn (string $field): bool => $user->{$field} !== $input[$field])
|
||||
->values()
|
||||
->all();
|
||||
Validator::make($input, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
|
||||
'email' => [
|
||||
'required',
|
||||
'string',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique('users')->ignore($user->id),
|
||||
],
|
||||
])->validateWithBag('updateProfileInformation');
|
||||
|
||||
if (
|
||||
$input['email'] !== $user->email &&
|
||||
$user instanceof MustVerifyEmail
|
||||
) {
|
||||
$this->updateVerifiedUser($user, $input);
|
||||
} else {
|
||||
$user->fill([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
])->save();
|
||||
}
|
||||
|
||||
if ($changedFields !== []) {
|
||||
auditLog('ui.user.profile_updated', [
|
||||
'team_id' => $user->currentTeam()?->id,
|
||||
'resource' => 'user',
|
||||
'user_name' => $user->name,
|
||||
'changed_fields' => $changedFields,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given verified user's profile information.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
protected function updateVerifiedUser(User $user, array $input): void
|
||||
{
|
||||
$user->fill([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
'email_verified_at' => null,
|
||||
])->save();
|
||||
|
||||
$user->sendEmailVerificationNotification();
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ namespace App\Providers;
|
||||
use App\Actions\Fortify\CreateNewUser;
|
||||
use App\Actions\Fortify\ResetUserPassword;
|
||||
use App\Actions\Fortify\UpdateUserPassword;
|
||||
use App\Actions\Fortify\UpdateUserProfileInformation;
|
||||
use App\Models\OauthSetting;
|
||||
use App\Models\TeamInvitation;
|
||||
use App\Models\User;
|
||||
@@ -115,7 +114,6 @@ class FortifyServiceProvider extends ServiceProvider
|
||||
});
|
||||
Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
|
||||
|
||||
Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
|
||||
Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
|
||||
|
||||
Fortify::confirmPasswordView(function () {
|
||||
|
||||
@@ -136,7 +136,6 @@ return [
|
||||
Features::registration(),
|
||||
Features::resetPasswords(),
|
||||
// Features::emailVerification(),
|
||||
Features::updateProfileInformation(),
|
||||
Features::updatePasswords(),
|
||||
Features::twoFactorAuthentication([
|
||||
'confirm' => true,
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\OauthIdentity;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
InstanceSettings::forceCreate(['id' => 0]);
|
||||
});
|
||||
|
||||
it('does not let a user change the email through the Fortify profile route', function (bool $hasSsoIdentity) {
|
||||
$user = User::factory()->create(['email' => 'owner@example.com']);
|
||||
if ($hasSsoIdentity) {
|
||||
OauthIdentity::create([
|
||||
'user_id' => $user->id,
|
||||
'provider' => 'github',
|
||||
'issuer' => 'github',
|
||||
'provider_user_id' => '123',
|
||||
'email' => 'owner@example.com',
|
||||
]);
|
||||
}
|
||||
|
||||
$this->actingAs($user)
|
||||
->withoutMiddleware(VerifyCsrfToken::class)
|
||||
->put('/user/profile-information', ['name' => 'Changed', 'email' => 'attacker@example.com']);
|
||||
|
||||
expect(Route::has('user-profile-information.update'))->toBeFalse()
|
||||
->and($user->fresh()->email)->toBe('owner@example.com')
|
||||
->and($user->fresh()->name)->not->toBe('Changed');
|
||||
})->with([
|
||||
'SSO user' => [true],
|
||||
'password user' => [false],
|
||||
]);
|
||||
Reference in New Issue
Block a user