security/api/betrieb: Fortify-2FA-Nebenwege gesperrt, Policy nur für aktive Super-Admins, Nachprüfungen aus dem Umsetzungsaudit (Block 7, U08–U10, U13, 7.1, 7.2, 7.5)

- Fortifys sieben 2FA-Verwaltungsrouten antworten mit 404 (Middleware über
  fortify.middleware); die Sicherheitsseite verlangt weiter den zweiten Faktor (U09)
- PressReleasePolicy/CompanyPolicy::before() bejahen nur aktive Super-Admins (7.2)
- API-Update prüft bei Portalwechsel die bestehende Kategorie gegen das neue Portal (U10)
- Aggregation: Zeitbudget 480 s unter dem Lock von 600 s, Marke nur unter
  Zeilensperre vom erwarteten Stand aus, sonst Fehler-Exit (U13)
- Newsletter-Bereinigungsmigration behält je Paar die sent-Zeile (U08)
- E-Mail-Wechsel stößt den Rechte-Sync sofort an; company-memberships:audit
  --classify zeigt vorher die Kandidaten und begrenzt mit --before (7.1)
- Detailseite wählt bei Slug-Kollision wie der Melde-Resolver (7.5)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-09-18 12:03:04 +00:00
parent c46dfd3b83
commit 05cf53e17d
18 changed files with 447 additions and 26 deletions

View file

@ -4,6 +4,7 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\Auth\ContactAccessService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@ -14,7 +15,7 @@ class ConfirmEmailChangeController extends Controller
* signierten Link aus der Mail an die NEUE Adresse geklickt hat.
* Bis dahin bleibt die alte Adresse aktiv (kein Aussperren bei Tippfehlern).
*/
public function __invoke(Request $request, User $user, string $hash): RedirectResponse
public function __invoke(Request $request, User $user, string $hash, ContactAccessService $contactAccess): RedirectResponse
{
abort_unless($request->user()->is($user), 403);
@ -39,6 +40,11 @@ class ConfirmEmailChangeController extends Controller
'pending_email' => null,
])->save();
// Die Firmenrechte hängen an der Adresse (Audit 7.1): automatische
// Rechte der alten Adresse sofort zurücknehmen, passende der neuen
// vergeben – nicht erst beim nächsten Login.
$contactAccess->syncMembershipsForEmail($user);
return redirect()->route('me.security')
->with('security-status', __('Ihre E-Mail-Adresse wurde erfolgreich geändert.'));
}