Files
termanager2/app/Http/Controllers/Auth/PasswordChangeController.php
Francesco Picone d2d6b1bdce ++ cambio password obbligato: al primo accesso del sorvegliante dice "Password temporanea", non "Ripristino da backup"
users.password_temporanea distingue la password provvisoria data
dall'amministratore (creazione del gruppo, "Nuova password temporanea")
dal ripristino da backup. Migrazione 000040; si spegne a password
cambiata, il ripristino e l'import XML la spengono per tutti.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 13:52:35 +02:00

101 lines
4.5 KiB
PHP

<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Jobs\RestoreBackupArchive;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Validation\Rules\Password;
/**
* Cambio password obbligatorio, imposto dopo il ripristino di un backup o al
* primo accesso con una password temporanea data dall'amministratore
* (sorvegliante di gruppo): `password_temporanea` dice quale dei due.
*
* Volutamente NON e' un componente Livewire: la pagina deve restare
* raggiungibile mentre RequirePasswordChange respinge tutto il resto, incluse
* le richieste /livewire/update. Due rotte HTTP normali sono banali da
* escludere; distinguere quale componente sta dietro una POST di Livewire no.
*/
class PasswordChangeController extends Controller
{
public function show()
{
$user = auth()->user();
return view('auth.password-change', [
'user' => $user,
// Chi arriva qui spontaneamente (dal profilo) puo' tornare indietro;
// chi e' stato dirottato dal middleware no.
'forced' => (bool) $user->password_change_required,
// Perché: una password temporanea, oppure un ripristino da backup.
'temporanea' => (bool) $user->password_temporanea,
// Il ripristino gira in coda e non ha una sessione in cui lasciare
// un flash; deposita l'esito in cache a nome di chi l'ha avviato e
// lo si legge qui, che e' la prima pagina che quella persona vede.
//
// Si legge senza consumare, e si cancella solo a password cambiata.
// Con un pull, il messaggio non arriverebbe mai a schermo: quando e'
// il middleware a dirottare una richiesta di Livewire, il client
// segue il 302 via fetch — ed e' quella fetch a bruciare il
// messaggio — per poi rifare la stessa GET con window.location, che
// troverebbe la cache gia' vuota.
'esitoRipristino' => Cache::get(RestoreBackupArchive::CHIAVE_ESITO . $user->id),
]);
}
public function store(Request $request)
{
$user = $request->user();
// La password attuale si chiede solo a chi arriva qui di sua
// iniziativa, come fa il profilo.
//
// Dopo un ripristino no: gli hash sono quelli del backup, e la
// "password attuale" di un account e' quella che aveva all'epoca, che
// l'utente puo' benissimo non ricordare. Chiederla bloccherebbe fuori
// proprio le persone che questa schermata deve sbloccare; la garanzia li'
// e' la sessione. Fuori da quel caso, invece, bastava una sessione
// lasciata aperta per cambiare la password a qualcun altro e chiuderlo
// fuori dal suo account.
$regole = ['password' => ['required', 'confirmed', Password::min(8)]];
if (! $user->password_change_required) {
$regole['current_password'] = ['required', 'current_password'];
}
$validated = $request->validate($regole, [
'password.required' => 'Inserisci la nuova password.',
'password.confirmed' => 'Le due password non coincidono.',
'current_password.required' => 'Inserisci la password attuale.',
'current_password.current_password' => 'La password attuale non è corretta.',
]);
// Il cast `hashed` sul modello cifra il valore al salvataggio.
$user->update([
'password' => $validated['password'],
'password_change_required' => false,
'password_temporanea' => false,
]);
// La sessione corrente sopravvive al cambio, le altre no: dopo un
// ripristino le vecchie credenziali sono da considerarsi compromesse e
// una sessione aperta altrove lo e' altrettanto. Le altre le chiude
// AuthenticateSession (bootstrap/app.php) alla loro prossima richiesta,
// perche' l'hash della password e' cambiato; qui si cambia l'id di
// questa e si invalida il "ricordami".
$request->session()->regenerate();
$user->setRememberToken(null);
$user->save();
// L'esito del ripristino ha esaurito il suo scopo: e' stato letto, e la
// password richiesta e' stata impostata.
Cache::forget(RestoreBackupArchive::CHIAVE_ESITO . $user->id);
activity()->causedBy($user)->log('password changed');
return redirect()->route('dashboard')
->with('success', 'Password aggiornata. Da ora accedi con quella nuova.');
}
}