Problem: Ein eingeloggter Nutzer ohne admin/editor/customer-Rolle wird per redirectUsersTo auf die Startseite geleitet und haengt dort fest. Ursache sind Alt-Konten, deren Rollen-Zuweisung nie lief (frueher Import bzw. ein nach dem User-Insert fehlgeschlagener Rollen-Sync). - Neues Command users:backfill-portal-role (--role, --dry-run): weist aktiven, komplett rollenlosen Nutzern die customer-Rolle zu. api-only-Konten haben bereits eine Rolle und bleiben unangetastet; inaktive werden uebersprungen. - legacy:import ruft den Backfill nach dem User-Schritt automatisch auf (self-heal, da updateOrCreate + Rollen-Sync nicht atomar sind). Analyse-Ergebnis nebenbei: In der aktuellen DB war nur genau 1 echter Fall (bereits gefixt); die zuvor genannten ~167 waren fast alle api-only (gewollt ohne Portal-Zugriff). Command laeuft daher jetzt sauber auf 0. Test: BackfillPortalRoleTest (customer-Zuweisung, Rollen-Erhalt bei customer/api-only, Ueberspringen Inaktiver, dry-run). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
62 lines
2.1 KiB
PHP
62 lines
2.1 KiB
PHP
<?php
|
||
|
||
namespace App\Console\Commands;
|
||
|
||
use App\Models\User;
|
||
use App\Services\Auth\UserRolePermissionSyncService;
|
||
use Illuminate\Console\Command;
|
||
|
||
/**
|
||
* Weist aktiven, komplett rollenlosen Nutzern eine Portal-Rolle zu.
|
||
*
|
||
* Hintergrund: Guest-/Auth-Redirects lenken einen eingeloggten Nutzer ohne
|
||
* admin/editor/customer-Rolle auf die Startseite (bootstrap/app.php →
|
||
* redirectUsersTo). Legacy-Importe oder ein fehlgeschlagener Rollen-Sync nach
|
||
* dem User-Insert können solche „hängenden" Konten erzeugen. Dieser Nachlauf
|
||
* heilt sie. api-only-Konten besitzen bereits eine Rolle und werden bewusst
|
||
* NICHT angefasst (kein Portal-Zugriff gewollt).
|
||
*/
|
||
class BackfillPortalRole extends Command
|
||
{
|
||
protected $signature = 'users:backfill-portal-role
|
||
{--role=customer : Zuzuweisende Rolle}
|
||
{--dry-run : Nur zählen, nichts schreiben}';
|
||
|
||
protected $description = 'Weist aktiven, rollenlosen Nutzern eine Portal-Rolle (Standard: customer) zu.';
|
||
|
||
public function handle(UserRolePermissionSyncService $roleSync): int
|
||
{
|
||
$role = (string) $this->option('role');
|
||
$dryRun = (bool) $this->option('dry-run');
|
||
|
||
$ids = User::query()
|
||
->where('is_active', true)
|
||
->whereDoesntHave('roles')
|
||
->pluck('id');
|
||
|
||
if ($ids->isEmpty()) {
|
||
$this->info('Keine aktiven rollenlosen Nutzer gefunden – nichts zu tun.');
|
||
|
||
return self::SUCCESS;
|
||
}
|
||
|
||
if ($dryRun) {
|
||
$this->warn("[DRY-RUN] {$ids->count()} aktive rollenlose Nutzer würden die Rolle '{$role}' erhalten.");
|
||
|
||
return self::SUCCESS;
|
||
}
|
||
|
||
$assigned = 0;
|
||
|
||
foreach ($ids->chunk(500) as $chunk) {
|
||
User::query()->whereIn('id', $chunk)->get()->each(function (User $user) use ($roleSync, $role, &$assigned): void {
|
||
$roleSync->assignRoleAndSyncPermissions($user, $role);
|
||
$assigned++;
|
||
});
|
||
}
|
||
|
||
$this->info("{$assigned} aktiven rollenlosen Nutzern die Rolle '{$role}' zugewiesen.");
|
||
|
||
return self::SUCCESS;
|
||
}
|
||
}
|