CluPilotCloud/tests/Feature/Auth
nexxo 92dd6cc2d8 Refuse a two-factor completion for a revoked operator
completeLogin() re-checks isActive()/isOperator() immediately before signing
in, not only at the password step. The two-factor challenge previously only
confirmed the operator row still existed (Operator::find() + a null check),
so disabling an operator or revoking every console role in the window between
the password step and the pending code did not stop the login from
completing — the realistic case is an owner locking someone out mid-login,
not a contrived one.

One check, in the static method both OperatorLogin's direct exit and
OperatorTwoFactorChallenge::verify() already share, rather than a second copy
in the challenge. completeLogin() now returns bool instead of void: false
means refused, and neither the guard nor the session was touched. Each caller
turns that into a ValidationException in its own vocabulary — 'email' /
auth.failed for the direct exit (already unreachable in practice, since
authenticate() just checked the same two conditions synchronously; kept for
defense in depth), 'code' / auth.not_an_operator for the challenge, since the
code entered may be genuinely correct and reusing "wrong code" would mislead.
2026-07-28 15:47:39 +02:00
..
BrandFactsTest.php Say EU and stop there, as the approved template does 2026-07-28 09:19:24 +02:00
LoginTest.php feat(portal): Fortify auth + Login/2FA/Dashboard + component kit 2026-07-25 01:20:25 +02:00
OperatorLoginTest.php Refuse a two-factor completion for a revoked operator 2026-07-28 15:47:39 +02:00
OperatorTwoFactorChallengeTest.php Refuse a two-factor completion for a revoked operator 2026-07-28 15:47:39 +02:00
RegisterTest.php Refuse a portal login for an address that already belongs to an operator 2026-07-28 14:42:16 +02:00
TwoFactorChallengeTest.php feat(portal): Fortify auth + Login/2FA/Dashboard + component kit 2026-07-25 01:20:25 +02:00