++ fix richiesta password prima di azzeramento applicazione
This commit is contained in:
@@ -5,6 +5,8 @@ namespace App\Livewire\Settings;
|
||||
use App\Jobs\CreateBackupArchive;
|
||||
use App\Jobs\ResetApplication;
|
||||
use App\Services\BackupOperationState;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Livewire\Component;
|
||||
|
||||
/**
|
||||
@@ -26,8 +28,26 @@ class BackupManager extends Component
|
||||
/** Frase da digitare per sbloccare l'azzeramento. */
|
||||
public const CONFERMA_AZZERAMENTO = 'AZZERA TUTTO';
|
||||
|
||||
/** Password sbagliate ammesse prima di bloccare l'azzeramento, e per quanto. */
|
||||
private const TENTATIVI_PASSWORD = 5;
|
||||
private const FINESTRA_TENTATIVI = 300;
|
||||
|
||||
public string $confermaReset = '';
|
||||
|
||||
/**
|
||||
* Esiste solo per dare un nome agli errori del campo password: Livewire
|
||||
* scarta dal messaggio di risposta ogni errore la cui chiave non
|
||||
* corrisponda a una proprieta' del componente (SupportValidation::dehydrate),
|
||||
* quindi senza questa riga "Password non corretta" non arriverebbe mai a
|
||||
* schermo e il pulsante sembrerebbe non fare nulla.
|
||||
*
|
||||
* NON collegarla al campo con wire:model: la password viaggia come
|
||||
* parametro di confermaAzzeramento() proprio per non finire nello
|
||||
* snapshot, che Livewire rimanda al browser a ogni risposta. Qui resta
|
||||
* sempre stringa vuota.
|
||||
*/
|
||||
public string $passwordConferma = '';
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->authorize('settings.manage');
|
||||
@@ -79,7 +99,7 @@ class BackupManager extends Component
|
||||
* resterebbe indistinguibile da uno riuscito. Chiedere all'operatore e'
|
||||
* l'unico controllo che copre anche quel caso.
|
||||
*/
|
||||
public function confermaAzzeramento(): void
|
||||
public function confermaAzzeramento(string $password = ''): void
|
||||
{
|
||||
$this->authorize('settings.manage');
|
||||
|
||||
@@ -97,6 +117,10 @@ class BackupManager extends Component
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $this->passwordConfermata($password)) {
|
||||
return;
|
||||
}
|
||||
|
||||
app(BackupOperationState::class)->update($this->operationId, function (array $state) {
|
||||
$state['fase'] = 'Azzeramento in avvio';
|
||||
$state['processed'] = 0;
|
||||
@@ -110,6 +134,56 @@ class BackupManager extends Component
|
||||
$this->aggiorna();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica la password dell'amministratore prima della cancellazione.
|
||||
*
|
||||
* A questo punto la sessione e' gia' autenticata, quindi la password non
|
||||
* serve a stabilire *chi* sia: serve a stabilire che davanti allo schermo
|
||||
* ci sia ancora quella persona. E' l'ultimo passo prima di
|
||||
* un'operazione irreversibile, e una scheda lasciata aperta su una
|
||||
* postazione condivisa e' lo scenario esatto contro cui protegge.
|
||||
*
|
||||
* La password arriva come parametro del metodo e non come proprieta' del
|
||||
* componente: le proprieta' pubbliche di Livewire vengono serializzate
|
||||
* nello snapshot e rispedite al browser a ogni risposta, e una password
|
||||
* non ha motivo di fare quel viaggio di ritorno.
|
||||
*/
|
||||
private function passwordConfermata(string $password): bool
|
||||
{
|
||||
$utente = auth()->user();
|
||||
$chiave = 'azzeramento-password:' . $utente->id;
|
||||
|
||||
// Senza un limite, la richiesta di password su una sessione dirottata
|
||||
// sarebbe solo un rallentamento: si proverebbero le password comuni a
|
||||
// raffica. Il blocco e' sull'azione, non sull'account, quindi nessuno
|
||||
// resta chiuso fuori dall'applicazione.
|
||||
if (RateLimiter::tooManyAttempts($chiave, self::TENTATIVI_PASSWORD)) {
|
||||
$this->addError('passwordConferma', sprintf(
|
||||
'Troppi tentativi. Riprova fra %d secondi.',
|
||||
RateLimiter::availableIn($chiave)
|
||||
));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($password === '') {
|
||||
$this->addError('passwordConferma', 'Inserisci la tua password per confermare.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! Hash::check($password, $utente->getAuthPassword())) {
|
||||
RateLimiter::hit($chiave, self::FINESTRA_TENTATIVI);
|
||||
$this->addError('passwordConferma', 'Password non corretta.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
RateLimiter::clear($chiave);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Annulla un azzeramento fermo in attesa di conferma. Il backup resta
|
||||
* scaricabile: e' comunque un backup valido.
|
||||
|
||||
Reference in New Issue
Block a user