admin: Aktivitäts-Verlauf unter Reports ▸ Verlauf

Chronologisches Protokoll der Systemereignisse als neue Admin-Seite
(/admin/reports/activity) mit Filter nach Ereignistyp, Zeitraum und
Suche. Erfasst ab jetzt fortlaufend:

- Registrierungen inkl. Weg (Formular, Google, Magic-Link)
- Anmeldungen inkl. Weg (Passwort, Google, Magic-Link, Impersonation)
- PM-Statuswechsel mit Ergebnis/Begründung (zentral im Status-Log-Hook;
  KI-/Scheduler-Wechsel erscheinen als „System")
- Zahlungseingänge (Rechnungsspiegelung) und Credit-Aufladungen
- Formular-Eingänge: Kontakt, Rechtsanfrage, Widerruf, Kündigung,
  Newsletter-Anmeldung (Observer auf den Modellen)

Schreiben ist Best-Effort über den ActivityLog-Service — ein
fehlgeschlagener Verlaufseintrag bricht nie den fachlichen Ablauf.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-15 16:00:58 +00:00
parent a574898ca9
commit 3a11963990
19 changed files with 720 additions and 4 deletions

View file

@ -2,8 +2,10 @@
namespace App\Services\Auth;
use App\Enums\ActivityType;
use App\Enums\RegistrationType;
use App\Models\User;
use App\Services\ActivityLog;
/**
* Legt verifizierte Kunden-Accounts an, die über einen vertrauenswürdigen Kanal
@ -17,13 +19,18 @@ use App\Models\User;
*/
class CustomerAccountProvisioner
{
public function __construct(private readonly UserRolePermissionSyncService $roleSync) {}
public function __construct(
private readonly UserRolePermissionSyncService $roleSync,
private readonly ActivityLog $activityLog,
) {}
/**
* @param array<string, mixed> $extraAttributes Zusätzliche Spalten beim
* Anlegen (z. B. OAuth-Provider).
* @param string $channel Herkunft fürs Aktivitäts-Protokoll
* ('magic-link' oder 'google').
*/
public function provisionVerifiedCustomer(string $email, string $name, array $extraAttributes = []): User
public function provisionVerifiedCustomer(string $email, string $name, array $extraAttributes = [], string $channel = 'magic-link'): User
{
$user = User::create([
'name' => $name !== '' ? $name : $email,
@ -39,6 +46,14 @@ class CustomerAccountProvisioner
$user->forceFill(['email_verified_at' => now()])->save();
$this->roleSync->assignRoleAndSyncPermissions($user, 'customer');
$channelLabels = ['magic-link' => 'Magic-Link', 'google' => 'Google'];
$this->activityLog->record(
ActivityType::UserRegistered,
sprintf('%s (%s) wurde registriert — %s.', $user->name, $user->email, $channelLabels[$channel] ?? $channel),
user: $user,
meta: ['way' => $channel],
);
return $user;
}
}