Files
termanager2/app/Livewire/Settings/BackupManager.php
Francesco Picone 426a95211d Revisione blocchi 2 e 3: file protetti, ripristino atomico, import sicuri
Blocco 2
- Esiti delle azioni Livewire come avvisi (trait Avvisa) invece di flash
  che comparivano alla pagina dopo.
- PDF, miniature e versioni dei territori non più serviti da nginx su
  /storage: TerritorioFileController con login, permessi e cache privata.
- Ripristino tutto o niente: verifica dell'archivio, una transazione con
  import, piantine, blocco account e scambio dei file annullabile.
- Backup formato 2 con piantine, storico PDF e area KML.
- Posto unico preso in un passo (Cache::lock) e rispettato anche da
  import XML e PDF.
- Import PDF da cartella: abbinamento corretto (1-A, 12 B, ambigui),
  caricamento a lotti, file non PDF ignorati, PDF sostituito nello storico.
- L'import XML elimina i file dei territori che non usa più; comando
  territori:file-orfani per quelli accumulati prima.

Blocco 3
- Password attuale richiesta al cambio volontario; AuthenticateSession
  chiude le sessioni aperte altrove.
- Niente nomi dei proclamatori in chiaro nel registro attività.
- Export XML senza remember_token; chi riceve l'hash dal file deve
  cambiare password.
- Campagne: ultimo giorno incluso, percentuale sui territori distinti.
- Coda: retry_after 960 s, stop_grace_period 16m, Redis volatile-lru,
  impostazioni rilette a ogni job.
- Azzeramento che cancella anche piantine, area KML e anteprime.
- Pulsanti profilo e menu che non si nascondevano; icona del sito.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:01:41 +02:00

116 lines
3.5 KiB
PHP

<?php
namespace App\Livewire\Settings;
use App\Jobs\CreateBackupArchive;
use App\Livewire\Concerns\SegueOperazioneBackup;
use App\Services\BackupOperationState;
use Livewire\Component;
/**
* Le due zone che si usano tutti i giorni: creare il pacchetto di backup e
* ripristinarlo.
*
* Il lavoro vero sta nei job; qui si avvia e si interroga lo stato. L'avanzamento
* e le righe di log non compaiono piu' in questa sezione: finiscono nella console
* unica agganciata in fondo alla pagina, che le riceve per eventi (vedi il trait
* SegueOperazioneBackup). Qui restano solo i comandi e l'esito.
*
* L'azzeramento sta in ZonaPericolosa, che e' un componente a se' perche' deve
* comparire in fondo alla pagina, dopo tutte le altre zone: dentro questa
* sezione finiva a meta' pagina, fra il ripristino e l'import.
*/
class BackupManager extends Component
{
use SegueOperazioneBackup;
public function mount(): void
{
$this->authorize('settings.manage');
$this->agganciaOperazioneCorrente();
}
/**
* Backup e ripristino si raccontano da qui; l'azzeramento e' della zona
* pericolosa. Vedi SegueOperazioneBackup::tipiSeguiti().
*/
protected function tipiSeguiti(): array
{
return [BackupOperationState::TIPO_BACKUP, BackupOperationState::TIPO_RESTORE];
}
public function avviaBackup(): void
{
$this->authorize('settings.manage');
if (! $this->postoLibero()) {
return;
}
$operationId = $this->nuovaOperazione(BackupOperationState::TIPO_BACKUP);
if ($operationId === null) {
return;
}
$this->operationId = $operationId;
CreateBackupArchive::dispatch($this->operationId, false);
$this->aggiorna();
$this->avvisaZonaPericolosa();
}
/**
* Aggancia un'operazione avviata fuori da Livewire: il ripristino parte da un
* upload XHR e restituisce il proprio id in JSON.
*/
public function seguiOperazione(string $operationId): void
{
$this->authorize('settings.manage');
$this->operationId = $operationId;
$this->logSpediti = 0;
$this->aggiorna();
$this->avvisaZonaPericolosa();
}
/**
* Il posto e' uno solo: la zona pericolosa deve sapere che e' occupato,
* altrimenti continuerebbe a offrire il proprio pulsante durante un backup o
* un ripristino.
*
* L'evento e' indirizzato, non gridato: senza ->to() tornerebbe anche a
* questo componente, che si riaggancerebbe a un'operazione appena
* agganciata — una richiesta in piu' a ogni avvio, per niente.
*/
private function avvisaZonaPericolosa(): void
{
$this->dispatch('operazione-avviata')->to(ZonaPericolosa::class);
}
/**
* L'azzeramento avviato dalla zona pericolosa non passa da qui, ma occupa lo
* stesso posto: senza riagganciarsi, questa sezione resterebbe convinta che
* sia libero e offrirebbe il pulsante "Crea backup" durante una
* cancellazione.
*/
#[\Livewire\Attributes\On('operazione-avviata')]
public function agganciaAltrove(): void
{
$this->agganciaOperazioneCorrente();
}
/** Vero quando l'archivio di questa operazione e' scaricabile. */
public function getArchivioProntoProperty(): bool
{
return ($this->operazione['result']['file'] ?? null) !== null;
}
public function render()
{
return view('livewire.settings.backup-manager');
}
}