++ gruppi: email fittizia iniziale+cognome per il sorvegliante; sciolto il gruppo l'utenza si elimina
- L'utenza del sorvegliante ha un'email fittizia creata dall'app: iniziale del nome e cognome @termanager.it (ffontana@termanager.it), come gli altri utenti. Via il nome utente: login di nuovo per email. - Sciolto il gruppo l'utenza si elimina, il sorvegliante torna un proclamatore come gli altri: assegnazioni a chi scioglie, registro a nome "Sorvegliante del gruppo ...". Via le utenze disattivate. - User::eliminaConservandoStorico(): l'eliminazione della pagina Utenti in un metodo solo, usato anche dallo scioglimento. - Migrazione 000030: elimina le utenze gia' disattivate, toglie users.username e users.disattivato_at, email di nuovo obbligatoria. - XML, informativa privacy, README, HANDOFF e test aggiornati. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,12 +21,15 @@ use InvalidArgumentException;
|
||||
*/
|
||||
class GruppiServizio
|
||||
{
|
||||
/** Il dominio delle email fittizie dei sorveglianti (iniziale+cognome@…). */
|
||||
public const DOMINIO_EMAIL = 'termanager.it';
|
||||
|
||||
/**
|
||||
* Crea il gruppo e l'utenza del sorvegliante: nome utente ricavato dal
|
||||
* nome del gruppo (niente email), ruolo "sorvegliante", password
|
||||
* temporanea da cambiare al primo accesso. Restituisce il gruppo e la
|
||||
* password temporanea, da mostrare una volta sola all'amministratore
|
||||
* insieme al nome utente ($gruppo->sorvegliante->utente->username).
|
||||
* Crea il gruppo e l'utenza del sorvegliante: email fittizia ricavata dal
|
||||
* suo nome (emailFittizia), ruolo "sorvegliante", password temporanea da
|
||||
* cambiare al primo accesso, nessuna conferma dell'email. Restituisce il
|
||||
* gruppo e la password temporanea, da mostrare una volta sola
|
||||
* all'amministratore insieme all'email.
|
||||
*
|
||||
* @param int[] $membri id dei proclamatori, oltre al sorvegliante
|
||||
* @return array{0: GruppoServizio, 1: string}
|
||||
@@ -46,29 +49,25 @@ class GruppiServizio
|
||||
if ($sorvegliante->gruppo_servizio_id) {
|
||||
throw new InvalidArgumentException("{$sorvegliante->nome_completo} fa già parte di un altro gruppo.");
|
||||
}
|
||||
// Chi è stato sorvegliante di un gruppo sciolto ha già un'utenza,
|
||||
// disattivata: si riattiva quella (un proclamatore, un'utenza).
|
||||
$esistente = $sorvegliante->utente()->first();
|
||||
if ($esistente && ! $esistente->isDisattivato()) {
|
||||
if ($sorvegliante->utente()->exists()) {
|
||||
throw new InvalidArgumentException("{$sorvegliante->nome_completo} ha già un'utenza.");
|
||||
}
|
||||
|
||||
$password = Str::password(12, symbols: false);
|
||||
|
||||
$gruppo = DB::transaction(function () use ($nome, $sorvegliante, $membri, $password, $esistente) {
|
||||
$gruppo = DB::transaction(function () use ($nome, $sorvegliante, $membri, $password) {
|
||||
$gruppo = GruppoServizio::create(['nome' => $nome, 'sorvegliante_id' => $sorvegliante->id]);
|
||||
$sorvegliante->update(['gruppo_servizio_id' => $gruppo->id]);
|
||||
$this->aggiungiMembri($gruppo, $membri);
|
||||
|
||||
$utente = $esistente ?? new User(['proclamatore_id' => $sorvegliante->id]);
|
||||
$utente->forceFill([
|
||||
$utente = User::create([
|
||||
'name' => $sorvegliante->nome_completo,
|
||||
'username' => self::nomeUtente($nome),
|
||||
'email' => self::emailFittizia($sorvegliante),
|
||||
'password' => $password,
|
||||
'password_change_required' => true,
|
||||
'disattivato_at' => null,
|
||||
])->save();
|
||||
$utente->syncRoles(['sorvegliante']);
|
||||
'proclamatore_id' => $sorvegliante->id,
|
||||
]);
|
||||
$utente->assignRole('sorvegliante');
|
||||
|
||||
activity()->causedBy(auth()->user())->performedOn($gruppo)
|
||||
->withProperties(['sorvegliante_id' => $sorvegliante->id, 'utente_id' => $utente->id])
|
||||
@@ -81,20 +80,27 @@ class GruppiServizio
|
||||
}
|
||||
|
||||
/**
|
||||
* Il nome utente dal nome del gruppo: minuscole, senza accenti, parole
|
||||
* unite da un punto ("Gruppo Noce" → "gruppo.noce"); se è già preso, un
|
||||
* numero in coda ("zisa2"). Mai una chiocciola: al login distingue il
|
||||
* nome utente dall'email.
|
||||
* L'email fittizia del sorvegliante, con cui entra: iniziale del nome e
|
||||
* cognome, minuscoli, senza accenti, spazi né apostrofi, sul dominio
|
||||
* dell'app (Francesco Fontana → ffontana@termanager.it, Francesco
|
||||
* D'Angelo → fdangelo@…). Se è già presa, un numero in coda
|
||||
* (ffontana2@…). Non riceve posta: il sorvegliante non conferma l'email.
|
||||
*/
|
||||
public static function nomeUtente(string $nomeGruppo): string
|
||||
public static function emailFittizia(Proclamatore $proclamatore): string
|
||||
{
|
||||
$base = Str::limit(Str::slug($nomeGruppo, '.') ?: 'gruppo', 50, '');
|
||||
$nome = $base;
|
||||
for ($n = 2; User::where('username', $nome)->exists(); $n++) {
|
||||
$nome = $base . $n;
|
||||
$pulisci = fn (string $testo) => preg_replace('/[^a-z0-9]/', '', Str::lower(Str::ascii($testo)));
|
||||
|
||||
$base = Str::limit(mb_substr($pulisci((string) $proclamatore->nome), 0, 1) . $pulisci((string) $proclamatore->cognome), 60, '');
|
||||
if ($base === '') {
|
||||
$base = "sorvegliante{$proclamatore->id}";
|
||||
}
|
||||
|
||||
return $nome;
|
||||
$email = "{$base}@" . self::DOMINIO_EMAIL;
|
||||
for ($n = 2; User::where('email', $email)->exists(); $n++) {
|
||||
$email = "{$base}{$n}@" . self::DOMINIO_EMAIL;
|
||||
}
|
||||
|
||||
return $email;
|
||||
}
|
||||
|
||||
/** @param int[] $ids */
|
||||
@@ -250,8 +256,10 @@ class GruppiServizio
|
||||
* I territori del pacchetto non ancora dati tornano in reparto; quelli
|
||||
* già dati restano ai membri come assegnazioni qualsiasi, che conservano
|
||||
* solo il nome del gruppo (gruppo_nome). I membri restano senza gruppo.
|
||||
* L'utenza del sorvegliante si disattiva e libera il nome utente; resta
|
||||
* perché è l'autrice delle assegnazioni che ha fatto.
|
||||
* L'utenza del sorvegliante si elimina: torna un proclamatore come gli
|
||||
* altri. Le assegnazioni che aveva fatto o fatto rientrare passano a chi
|
||||
* scioglie il gruppo; nel registro le sue voci restano, a nome
|
||||
* "Sorvegliante del gruppo …", senza dati personali.
|
||||
*/
|
||||
public function sciogli(GruppoServizio $gruppo, ?string $motivo = null): void
|
||||
{
|
||||
@@ -269,30 +277,39 @@ class GruppiServizio
|
||||
Assegnazione::where('gruppo_servizio_id', $gruppo->id)->update(['gruppo_servizio_id' => null]);
|
||||
|
||||
$utente = User::where('proclamatore_id', $gruppo->sorvegliante_id)->first();
|
||||
if ($utente) {
|
||||
$utente->removeRole('sorvegliante');
|
||||
// Il nome utente del gruppo si libera; al suo posto uno che
|
||||
// identifica l'utenza (backup XML) e con cui non si entra.
|
||||
$utente->forceFill([
|
||||
'disattivato_at' => now(),
|
||||
'remember_token' => null,
|
||||
'username' => "ex.sorvegliante.{$utente->id}",
|
||||
])->save();
|
||||
}
|
||||
|
||||
activity()->causedBy(auth()->user())->performedOn($gruppo)
|
||||
->withProperties(array_filter([
|
||||
'gruppo' => $gruppo->nome,
|
||||
'territori_liberati' => $liberati->all(),
|
||||
'utente_disattivato' => $utente?->id,
|
||||
'utente_eliminato' => $utente?->id,
|
||||
'motivo' => $motivo,
|
||||
], fn ($v) => $v !== null))
|
||||
->log('gruppo_sciolto');
|
||||
|
||||
if ($utente) {
|
||||
$utente->eliminaConservandoStorico($this->subentrante($utente), "Sorvegliante del gruppo {$gruppo->nome}", null);
|
||||
}
|
||||
|
||||
$gruppo->delete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Chi prende le assegnazioni fatte dal sorvegliante quando la sua utenza
|
||||
* si elimina: chi sta sciogliendo il gruppo, altrimenti il primo
|
||||
* amministratore.
|
||||
*/
|
||||
private function subentrante(User $sorvegliante): User
|
||||
{
|
||||
$chi = auth()->user();
|
||||
if ($chi instanceof User && $chi->id !== $sorvegliante->id) {
|
||||
return $chi;
|
||||
}
|
||||
|
||||
return User::role('amministratore')->orderBy('id')->firstOrFail();
|
||||
}
|
||||
|
||||
private function attivo(GruppoServizio $gruppo): void
|
||||
{
|
||||
if (! $gruppo->exists || ! GruppoServizio::whereKey($gruppo->id)->exists()) {
|
||||
|
||||
Reference in New Issue
Block a user