++ consolidamento funzionalità Backup
This commit is contained in:
@@ -52,8 +52,17 @@ class Profile extends Component
|
||||
]);
|
||||
|
||||
// Il cast `hashed` sul modello User cifra il valore in fase di salvataggio.
|
||||
//
|
||||
// Si spegne anche `password_change_required`: oggi chi ha quel flag
|
||||
// viene dirottato dal middleware e questa pagina non la raggiunge
|
||||
// nemmeno, ma la condizione che il flag esprime — "questa password non
|
||||
// e' piu' un segreto" — la soddisfa qualunque cambio, non solo quello
|
||||
// fatto dalla schermata obbligatoria. Lasciarlo acceso qui
|
||||
// significherebbe che un domani, allentando il middleware, l'utente
|
||||
// resterebbe bloccato dopo aver gia' fatto quello che gli si chiedeva.
|
||||
auth()->user()->update([
|
||||
'password' => $this->password,
|
||||
'password_change_required' => false,
|
||||
]);
|
||||
|
||||
$this->reset(['current_password', 'password', 'password_confirmation']);
|
||||
|
||||
@@ -48,15 +48,29 @@ class BackupManager extends Component
|
||||
*/
|
||||
public string $passwordConferma = '';
|
||||
|
||||
/** Messaggio mostrato in cima quando un avvio viene rifiutato. */
|
||||
public string $erroreOperazione = '';
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->authorize('settings.manage');
|
||||
|
||||
// Riaggancia un'operazione gia' in corso. Senza, ricaricare la pagina
|
||||
// durante un backup lungo farebbe sparire la barra, e un azzeramento
|
||||
// fermo in attesa di conferma diventerebbe irraggiungibile: nessuno
|
||||
// potrebbe piu' ne' confermarlo ne' annullarlo.
|
||||
$this->operationId = app(BackupOperationState::class)->corrente();
|
||||
$this->aggiorna();
|
||||
}
|
||||
|
||||
public function avviaBackup(): void
|
||||
{
|
||||
$this->authorize('settings.manage');
|
||||
|
||||
if (! $this->postoLibero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->operationId = $this->nuovaOperazione(BackupOperationState::TIPO_BACKUP);
|
||||
|
||||
CreateBackupArchive::dispatch($this->operationId, false);
|
||||
@@ -64,6 +78,32 @@ class BackupManager extends Component
|
||||
$this->aggiorna();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vero se non c'e' gia' un'operazione in corso.
|
||||
*
|
||||
* Backup, ripristino e azzeramento lavorano tutti sullo stesso database e
|
||||
* sullo stesso disco: farne partire due insieme — due schede, due
|
||||
* amministratori — non li rallenta soltanto, li fa sovrascrivere a vicenda.
|
||||
*/
|
||||
private function postoLibero(): bool
|
||||
{
|
||||
$inCorso = app(BackupOperationState::class)->corrente();
|
||||
|
||||
if ($inCorso === null) {
|
||||
$this->erroreOperazione = '';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Si aggancia a quella in corso invece di limitarsi a rifiutare: chi ha
|
||||
// premuto il pulsante vuole comunque vedere a che punto e'.
|
||||
$this->operationId = $inCorso;
|
||||
$this->aggiorna();
|
||||
$this->erroreOperazione = 'C\'e\' gia\' un\'operazione in corso: attendi che finisca prima di avviarne un\'altra.';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Primo tempo dell'azzeramento: si costruisce il backup e lo si scarica.
|
||||
* La cancellazione non parte da qui — serve il secondo tempo,
|
||||
@@ -79,6 +119,10 @@ class BackupManager extends Component
|
||||
'confermaReset.required' => 'Scrivi "' . self::CONFERMA_AZZERAMENTO . '" per confermare.']
|
||||
);
|
||||
|
||||
if (! $this->postoLibero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->confermaReset = '';
|
||||
$this->operationId = $this->nuovaOperazione(BackupOperationState::TIPO_RESET);
|
||||
|
||||
@@ -316,6 +360,21 @@ class BackupManager extends Component
|
||||
&& in_array($this->operazione['status'] ?? '', ['queued', 'running'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ogni quanto reinterrogare lo stato.
|
||||
*
|
||||
* Mentre un job lavora servono aggiornamenti fitti, la barra deve muoversi.
|
||||
* In attesa-download invece si aspetta una persona, che puo' metterci
|
||||
* minuti: continuare a bussare ogni 750ms vorrebbe dire migliaia di
|
||||
* richieste inutili se qualcuno lascia la scheda aperta e se ne va.
|
||||
*/
|
||||
public function getIntervalloPollProperty(): string
|
||||
{
|
||||
return ($this->operazione['fase'] ?? null) === BackupOperationState::FASE_ATTESA_DOWNLOAD
|
||||
? '5s'
|
||||
: '750ms';
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.settings.backup-manager');
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace App\Livewire\Territori;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
use App\Models\Territorio;
|
||||
use App\Services\TerritorioThumbnailService;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class TerritorioCestino extends Component
|
||||
{
|
||||
@@ -36,10 +38,36 @@ class TerritorioCestino extends Component
|
||||
activity()->causedBy(auth()->user())
|
||||
->withProperties(['numero' => $territorio->numero])
|
||||
->log('force_deleted_territorio');
|
||||
|
||||
// I file vanno via con la riga. Cancellare solo il record lascerebbe la
|
||||
// mappa e la miniatura sul volume senza piu' nulla che le riferisca:
|
||||
// invisibili in ogni schermata, non raggiungibili da nessuna
|
||||
// cancellazione futura, e comunque dentro ogni backup successivo.
|
||||
// Prima della riga, non dopo: se la cancellazione dei file fallisce,
|
||||
// il territorio resta nel cestino e l'operazione si puo' ritentare.
|
||||
$this->rimuoviFile($territorio);
|
||||
|
||||
$territorio->forceDelete();
|
||||
session()->flash('success', 'Territorio eliminato definitivamente.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Rimuove mappa e miniatura di un territorio dal disco `public`.
|
||||
*
|
||||
* Stessa coppia di cancellazioni che fa TerritorioEdit quando si sostituisce
|
||||
* il PDF; qui e' definitiva perche' non resta una riga a cui riattaccarle.
|
||||
*/
|
||||
private function rimuoviFile(Territorio $territorio): void
|
||||
{
|
||||
if ($territorio->pdf_path) {
|
||||
Storage::disk('public')->delete($territorio->pdf_path);
|
||||
}
|
||||
|
||||
if ($territorio->thumbnail_path) {
|
||||
app(TerritorioThumbnailService::class)->delete($territorio->thumbnail_path);
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.territori.territorio-cestino', [
|
||||
|
||||
Reference in New Issue
Block a user