Skip password confirmation for OAuth users (#7608)
This commit is contained in:
commit
ad013ca7da
16 changed files with 109 additions and 120 deletions
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
|
||||
class NavbarDeleteTeam extends Component
|
||||
|
|
@ -19,12 +17,8 @@ public function mount()
|
|||
|
||||
public function delete($password)
|
||||
{
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$currentTeam = currentTeam();
|
||||
|
|
|
|||
|
|
@ -2,12 +2,9 @@
|
|||
|
||||
namespace App\Livewire\Project\Database;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use Exception;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
|
@ -154,12 +151,8 @@ public function delete($password)
|
|||
{
|
||||
$this->authorize('manageBackups', $this->backup->database);
|
||||
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -2,11 +2,9 @@
|
|||
|
||||
namespace App\Livewire\Project\Database;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
|
||||
class BackupExecutions extends Component
|
||||
|
|
@ -69,12 +67,8 @@ public function cleanupDeleted()
|
|||
|
||||
public function deleteBackup($executionId, $password)
|
||||
{
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$execution = $this->backup->executions()->where('id', $executionId)->first();
|
||||
|
|
|
|||
|
|
@ -4,12 +4,9 @@
|
|||
|
||||
use App\Actions\Database\StartDatabaseProxy;
|
||||
use App\Actions\Database\StopDatabaseProxy;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\ServiceDatabase;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
|
||||
class Database extends Component
|
||||
|
|
@ -96,12 +93,8 @@ public function delete($password)
|
|||
try {
|
||||
$this->authorize('delete', $this->database);
|
||||
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->database->delete();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Livewire\Project\Service;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\LocalFileVolume;
|
||||
use App\Models\ServiceApplication;
|
||||
use App\Models\ServiceDatabase;
|
||||
|
|
@ -16,8 +15,6 @@
|
|||
use App\Models\StandalonePostgresql;
|
||||
use App\Models\StandaloneRedis;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
|
|
@ -141,12 +138,8 @@ public function delete($password)
|
|||
{
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -2,12 +2,9 @@
|
|||
|
||||
namespace App\Livewire\Project\Service;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\ServiceApplication;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
use Spatie\Url\Url;
|
||||
|
|
@ -128,12 +125,8 @@ public function delete($password)
|
|||
try {
|
||||
$this->authorize('delete', $this->application);
|
||||
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->application->delete();
|
||||
|
|
|
|||
|
|
@ -3,13 +3,10 @@
|
|||
namespace App\Livewire\Project\Shared;
|
||||
|
||||
use App\Jobs\DeleteResourceJob;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
use App\Models\ServiceDatabase;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
|
|
@ -93,12 +90,8 @@ public function mount()
|
|||
|
||||
public function delete($password)
|
||||
{
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $this->resource) {
|
||||
|
|
|
|||
|
|
@ -5,12 +5,9 @@
|
|||
use App\Actions\Application\StopApplicationOneServer;
|
||||
use App\Actions\Docker\GetContainersStatus;
|
||||
use App\Events\ApplicationStatusChanged;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
|
|
@ -140,12 +137,8 @@ public function addServer(int $network_id, int $server_id)
|
|||
public function removeServer(int $network_id, int $server_id, $password)
|
||||
{
|
||||
try {
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->resource->destination->server->id == $server_id && $this->resource->destination->id == $network_id) {
|
||||
|
|
|
|||
|
|
@ -2,11 +2,8 @@
|
|||
|
||||
namespace App\Livewire\Project\Shared\Storages;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\LocalPersistentVolume;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
|
|
@ -84,12 +81,8 @@ public function delete($password)
|
|||
{
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->storage->delete();
|
||||
|
|
|
|||
|
|
@ -3,11 +3,8 @@
|
|||
namespace App\Livewire\Server;
|
||||
|
||||
use App\Actions\Server\DeleteServer;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
|
||||
class Delete extends Component
|
||||
|
|
@ -29,12 +26,8 @@ public function mount(string $server_uuid)
|
|||
|
||||
public function delete($password)
|
||||
{
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$this->authorize('delete', $this->server);
|
||||
|
|
|
|||
|
|
@ -2,11 +2,8 @@
|
|||
|
||||
namespace App\Livewire\Server\Security;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
|
|
@ -44,13 +41,9 @@ public function toggleTerminal($password)
|
|||
throw new \Exception('Only team administrators and owners can modify terminal access.');
|
||||
}
|
||||
|
||||
// Verify password unless two-step confirmation is disabled
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
// Verify password
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle the terminal setting
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use App\Rules\ValidIpOrCidr;
|
||||
use Auth;
|
||||
use Hash;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
|
|
@ -157,9 +155,7 @@ public function instantSave()
|
|||
|
||||
public function toggleTwoStepConfirmation($password): bool
|
||||
{
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
namespace App\Livewire\Team;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
|
||||
class AdminView extends Component
|
||||
|
|
@ -58,12 +55,8 @@ public function delete($id, $password)
|
|||
return redirect()->route('dashboard');
|
||||
}
|
||||
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! auth()->user()->isInstanceAdmin()) {
|
||||
|
|
|
|||
|
|
@ -443,4 +443,13 @@ public function hasEmailChangeRequest(): bool
|
|||
&& $this->email_change_code_expires_at
|
||||
&& Carbon::now()->lessThan($this->email_change_code_expires_at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user has a password set.
|
||||
* OAuth users are created without passwords.
|
||||
*/
|
||||
public function hasPassword(): bool
|
||||
{
|
||||
return ! empty($this->password);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
|
|
@ -3308,3 +3309,57 @@ function formatContainerStatus(string $status): string
|
|||
return str($status)->headline()->value();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if password confirmation should be skipped.
|
||||
* Returns true if:
|
||||
* - Two-step confirmation is globally disabled
|
||||
* - User has no password (OAuth users)
|
||||
*
|
||||
* Used by modal-confirmation.blade.php to determine if password step should be shown.
|
||||
*
|
||||
* @return bool True if password confirmation should be skipped
|
||||
*/
|
||||
function shouldSkipPasswordConfirmation(): bool
|
||||
{
|
||||
// Skip if two-step confirmation is globally disabled
|
||||
if (data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip if user has no password (OAuth users)
|
||||
if (! Auth::user()?->hasPassword()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify password for two-step confirmation.
|
||||
* Skips verification if:
|
||||
* - Two-step confirmation is globally disabled
|
||||
* - User has no password (OAuth users)
|
||||
*
|
||||
* @param mixed $password The password to verify (may be array if skipped by frontend)
|
||||
* @param \Livewire\Component|null $component Optional Livewire component to add errors to
|
||||
* @return bool True if verification passed (or skipped), false if password is incorrect
|
||||
*/
|
||||
function verifyPasswordConfirmation(mixed $password, ?Livewire\Component $component = null): bool
|
||||
{
|
||||
// Skip if password confirmation should be skipped
|
||||
if (shouldSkipPasswordConfirmation()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Verify the password
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
if ($component) {
|
||||
$component->addError('password', 'The provided password is incorrect.');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,17 +29,23 @@
|
|||
|
||||
@php
|
||||
use App\Models\InstanceSettings;
|
||||
// Global setting to disable ALL two-step confirmation (text + password)
|
||||
$disableTwoStepConfirmation = data_get(InstanceSettings::get(), 'disable_two_step_confirmation');
|
||||
// Skip ONLY password confirmation for OAuth users (they have no password)
|
||||
$skipPasswordConfirmation = shouldSkipPasswordConfirmation();
|
||||
if ($temporaryDisableTwoStepConfirmation) {
|
||||
$disableTwoStepConfirmation = false;
|
||||
$skipPasswordConfirmation = false;
|
||||
}
|
||||
// When password step is skipped, Step 2 becomes final - change button text from "Continue" to "Confirm"
|
||||
$effectiveStep2ButtonText = ($skipPasswordConfirmation && $step2ButtonText === 'Continue') ? 'Confirm' : $step2ButtonText;
|
||||
@endphp
|
||||
|
||||
<div {{ $ignoreWire ? 'wire:ignore' : '' }} x-data="{
|
||||
modalOpen: false,
|
||||
step: {{ empty($checkboxes) ? 2 : 1 }},
|
||||
initialStep: {{ empty($checkboxes) ? 2 : 1 }},
|
||||
finalStep: {{ $confirmWithPassword && !$disableTwoStepConfirmation ? 3 : 2 }},
|
||||
finalStep: {{ $confirmWithPassword && !$skipPasswordConfirmation ? 3 : 2 }},
|
||||
deleteText: '',
|
||||
password: '',
|
||||
actions: @js($actions),
|
||||
|
|
@ -50,7 +56,7 @@
|
|||
})(),
|
||||
userConfirmationText: '',
|
||||
confirmWithText: @js($confirmWithText && !$disableTwoStepConfirmation),
|
||||
confirmWithPassword: @js($confirmWithPassword && !$disableTwoStepConfirmation),
|
||||
confirmWithPassword: @js($confirmWithPassword && !$skipPasswordConfirmation),
|
||||
submitAction: @js($submitAction),
|
||||
dispatchAction: @js($dispatchAction),
|
||||
passwordError: '',
|
||||
|
|
@ -59,6 +65,7 @@
|
|||
dispatchEventType: @js($dispatchEventType),
|
||||
dispatchEventMessage: @js($dispatchEventMessage),
|
||||
disableTwoStepConfirmation: @js($disableTwoStepConfirmation),
|
||||
skipPasswordConfirmation: @js($skipPasswordConfirmation),
|
||||
resetModal() {
|
||||
this.step = this.initialStep;
|
||||
this.deleteText = '';
|
||||
|
|
@ -68,7 +75,7 @@
|
|||
$wire.$refresh();
|
||||
},
|
||||
step1ButtonText: @js($step1ButtonText),
|
||||
step2ButtonText: @js($step2ButtonText),
|
||||
step2ButtonText: @js($effectiveStep2ButtonText),
|
||||
step3ButtonText: @js($step3ButtonText),
|
||||
validatePassword() {
|
||||
if (this.confirmWithPassword && !this.password) {
|
||||
|
|
@ -92,10 +99,14 @@
|
|||
const paramsMatch = this.submitAction.match(/\((.*?)\)/);
|
||||
const params = paramsMatch ? paramsMatch[1].split(',').map(param => param.trim()) : [];
|
||||
|
||||
if (this.confirmWithPassword) {
|
||||
params.push(this.password);
|
||||
// Always pass password parameter (empty string if password confirmation is skipped)
|
||||
// This ensures consistent method signature for backend Livewire methods
|
||||
params.push(this.confirmWithPassword ? this.password : '');
|
||||
|
||||
// Only pass selectedActions if there are checkboxes with selections
|
||||
if (this.selectedActions.length > 0) {
|
||||
params.push(this.selectedActions);
|
||||
}
|
||||
params.push(this.selectedActions);
|
||||
return $wire[methodName](...params)
|
||||
.then(result => {
|
||||
if (result === true) {
|
||||
|
|
@ -316,7 +327,7 @@ class="w-auto" isError
|
|||
if (dispatchEvent) {
|
||||
$wire.dispatch(dispatchEventType, dispatchEventMessage);
|
||||
}
|
||||
if (confirmWithPassword && !disableTwoStepConfirmation) {
|
||||
if (confirmWithPassword && !skipPasswordConfirmation) {
|
||||
step++;
|
||||
} else {
|
||||
modalOpen = false;
|
||||
|
|
@ -330,7 +341,7 @@ class="w-auto" isError
|
|||
</div>
|
||||
|
||||
<!-- Step 3: Password confirmation -->
|
||||
@if (!$disableTwoStepConfirmation)
|
||||
@if (!$skipPasswordConfirmation)
|
||||
<div x-show="step === 3 && confirmWithPassword">
|
||||
<x-callout type="danger" title="Final Confirmation" class="mb-4">
|
||||
Please enter your password to confirm this destructive action.
|
||||
|
|
|
|||
Loading…
Reference in a new issue