++ add backup totale applicativo
This commit is contained in:
77
resources/views/auth/password-change.blade.php
Normal file
77
resources/views/auth/password-change.blade.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<x-layouts.guest title="Cambio password">
|
||||
<div class="bg-white rounded-xl shadow-lg border border-gray-200 p-6 space-y-5">
|
||||
<div>
|
||||
<h1 class="text-xl font-bold text-gray-900">
|
||||
{{ $forced ? 'Imposta una nuova password' : 'Cambia password' }}
|
||||
</h1>
|
||||
<p class="mt-1 text-sm text-gray-500">
|
||||
Account: <span class="font-medium text-gray-700 break-all">{{ $user->email }}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@if(session('success'))
|
||||
<div class="rounded-lg bg-green-50 border border-green-200 px-4 py-2.5 text-sm text-green-800">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($forced)
|
||||
<div class="rounded-lg border border-amber-300 bg-amber-50 px-4 py-3 text-sm text-amber-800">
|
||||
<strong>Ripristino da backup eseguito.</strong>
|
||||
Il pacchetto di backup contiene le password di tutti gli account, quindi
|
||||
le vecchie credenziali non sono piu’ considerate sicure. Scegli una
|
||||
nuova password per continuare: fino ad allora il resto dell’applicazione
|
||||
resta bloccato.
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($errors->any())
|
||||
<div class="rounded-lg bg-red-50 border border-red-200 px-4 py-2.5 text-sm text-red-800">
|
||||
<ul class="list-disc list-inside space-y-0.5">
|
||||
@foreach($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('password.change.store') }}" class="space-y-4">
|
||||
@csrf
|
||||
|
||||
{{-- L'email in un campo nascosto: senza, i gestori di password non
|
||||
sanno a quale account associare la credenziale che salvano. --}}
|
||||
<input type="hidden" name="email" autocomplete="username" value="{{ $user->email }}">
|
||||
|
||||
<div>
|
||||
<label for="password" class="block text-sm font-medium text-gray-700">Nuova password</label>
|
||||
<input type="password" name="password" id="password" required autofocus autocomplete="new-password"
|
||||
class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||
<p class="mt-1 text-xs text-gray-500">Almeno 8 caratteri.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="password_confirmation" class="block text-sm font-medium text-gray-700">Conferma nuova password</label>
|
||||
<input type="password" name="password_confirmation" id="password_confirmation" required autocomplete="new-password"
|
||||
class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||
</div>
|
||||
|
||||
<button type="submit"
|
||||
class="w-full inline-flex items-center justify-center px-4 py-2.5 text-sm font-medium text-white rounded-lg transition"
|
||||
style="background:#4f46e5" onmouseover="this.style.background='#4338ca'" onmouseout="this.style.background='#4f46e5'">
|
||||
Salva la nuova password
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="flex justify-between text-xs text-gray-500 pt-1 border-t border-gray-100">
|
||||
@if($forced)
|
||||
<span>Non sei tu? Esci e accedi con un altro account.</span>
|
||||
@else
|
||||
<a href="{{ route('dashboard') }}" class="hover:text-indigo-600">Torna alla home</a>
|
||||
@endif
|
||||
<form method="POST" action="{{ route('logout') }}">
|
||||
@csrf
|
||||
<button type="submit" class="hover:text-indigo-600">Esci</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</x-layouts.guest>
|
||||
@@ -144,9 +144,9 @@
|
||||
Tipologie
|
||||
</a>
|
||||
<a href="{{ route('xml.exchange') }}"
|
||||
class="flex items-center gap-3 px-3 py-2 text-sm font-medium rounded-lg {{ request()->routeIs('xml.*') ? 'bg-indigo-50 text-indigo-700' : 'text-gray-700 hover:bg-gray-100' }}">
|
||||
class="flex items-center gap-3 px-3 py-2 text-sm font-medium rounded-lg {{ request()->routeIs('xml.*', 'backup.*') ? 'bg-indigo-50 text-indigo-700' : 'text-gray-700 hover:bg-gray-100' }}">
|
||||
<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 16v4m0 0l-3-3m3 3l3-3M4 12a8 8 0 1116 0v1a3 3 0 01-3 3h-1M7 16H6a2 2 0 01-2-2v-2"/></svg>
|
||||
Import
|
||||
Backup e import
|
||||
</a>
|
||||
</div>
|
||||
@endcan
|
||||
|
||||
@@ -1,7 +1,64 @@
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-gray-900">Import</h1>
|
||||
<p class="text-sm text-gray-500 mt-1">Centro importazioni: PDF territori, conversione legacy SQL, import XML ed export XML.</p>
|
||||
<h1 class="text-2xl font-bold text-gray-900">Backup e import</h1>
|
||||
<p class="text-sm text-gray-500 mt-1">Backup completo dell’applicazione, import PDF territori, conversione legacy SQL, import ed export XML.</p>
|
||||
</div>
|
||||
|
||||
{{-- Backup completo: e' la sezione che serve nel 99% dei casi, quindi sta
|
||||
in cima. Le sezioni XML piu' sotto restano per gli usi parziali e per
|
||||
la conversione dei dump legacy. --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 space-y-5">
|
||||
<div>
|
||||
<h2 class="text-lg font-semibold text-gray-900">Backup completo (.zip)</h2>
|
||||
<p class="text-xs text-gray-500 mt-1">
|
||||
Un unico pacchetto con <strong>tutti</strong> i dati dell’applicazione — utenti compresi —
|
||||
e <strong>tutti i file caricati</strong>: PDF dei territori, miniature e logo.
|
||||
E’ l’archivio da conservare per rimettere in piedi l’installazione da zero.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-lg border border-amber-300 bg-amber-50 p-3 text-xs text-amber-800">
|
||||
<strong>Dati sensibili.</strong> Il pacchetto include gli utenti con le password (hash), i nomi dei
|
||||
proclamatori in chiaro e le mappe dei territori. Conservalo in un luogo sicuro e non condividerlo.
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-center">
|
||||
<a href="{{ route('backup.download') }}"
|
||||
style="display:inline-flex;align-items:center;gap:6px;justify-content:center;min-height:40px;background:#059669;color:#fff;border:1px solid #065f46;border-radius:10px;padding:10px 14px;font-size:14px;font-weight:500;text-decoration:none;">
|
||||
<svg style="width:16px;height:16px;" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3M3 17v3a1 1 0 001 1h16a1 1 0 001-1v-3"/></svg>
|
||||
Scarica backup completo
|
||||
</a>
|
||||
<p class="text-xs text-gray-500">La preparazione dell’archivio puo’ richiedere qualche minuto se ci sono molti PDF.</p>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-gray-200 pt-5">
|
||||
<h3 class="text-sm font-semibold text-gray-900">Ripristina da backup</h3>
|
||||
<p class="mt-1 text-xs text-gray-500">
|
||||
Carica un pacchetto .zip generato qui sopra. Il ripristino <strong>sostituisce</strong> i dati
|
||||
gestionali correnti e tutti i file caricati.
|
||||
</p>
|
||||
|
||||
<div class="mt-3 rounded-lg border border-red-300 bg-red-50 p-3 text-xs text-red-800">
|
||||
<strong>Al termine tutti dovranno cambiare password</strong>, amministratore compreso: il pacchetto
|
||||
contiene le password di ogni account, quindi dopo un ripristino le vecchie non sono piu’ da
|
||||
considerarsi segrete. Verrai portato subito sulla schermata di cambio password.
|
||||
</div>
|
||||
|
||||
<form action="{{ route('backup.restore') }}" method="POST" enctype="multipart/form-data" class="mt-4 space-y-4"
|
||||
onsubmit="return confirm('Confermi il ripristino? I dati gestionali e i file correnti verranno sostituiti, e tutti gli utenti dovranno impostare una nuova password.');">
|
||||
@csrf
|
||||
<div>
|
||||
<input name="backupZip" type="file" accept=".zip,application/zip"
|
||||
class="block w-full text-sm text-gray-600 file:mr-3 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-medium file:bg-red-50 file:text-red-700 hover:file:bg-red-100">
|
||||
@error('backupZip') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<button type="submit"
|
||||
style="display:inline-flex;align-items:center;justify-content:center;min-height:40px;background:#dc2626;color:#fff;border:1px solid #991b1b;border-radius:10px;padding:10px 14px;font-size:14px;font-weight:500;">
|
||||
Ripristina backup
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 space-y-4"
|
||||
@@ -341,8 +398,12 @@
|
||||
@endif
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 space-y-4">
|
||||
<h2 class="text-lg font-semibold text-gray-900">Export XML</h2>
|
||||
<p class="text-xs text-gray-500">Esporta <strong>tutti</strong> i dati correnti dell'app in XML (backup completo, reimportabile).</p>
|
||||
<h2 class="text-lg font-semibold text-gray-900">Export XML (solo dati)</h2>
|
||||
<p class="text-xs text-gray-500">
|
||||
Esporta <strong>tutti</strong> i dati correnti dell'app in XML, reimportabile qui sopra.
|
||||
<strong>Non</strong> include i file caricati: ripristinando solo questo, i territori restano
|
||||
senza PDF né miniature. Per un backup davvero completo usa il pacchetto .zip in cima alla pagina.
|
||||
</p>
|
||||
|
||||
<div class="rounded-lg border border-amber-300 bg-amber-50 p-3 text-xs text-amber-800">
|
||||
<strong>Dati sensibili.</strong> Il file include gli utenti con le password (hash) e i nomi dei proclamatori in chiaro.
|
||||
|
||||
Reference in New Issue
Block a user