anomaly/suspension_security_check-extension
An Anomaly extension that adds suspension-aware security checks to Laravel applications, helping block suspended accounts from protected areas and enforce safer access control. Easy to install and configure, it quickly integrates with existing Anomaly projects and authentication workflows.
This is a PyroCMS 3 addon, not a standalone Laravel package. It extends the anomaly/users-module and registers a security check that runs during the Users module login flow to reject suspended/blocked accounts. Treat it as a module extension, not a library you use in arbitrary controllers.
Minimal steps:
composer require anomaly/suspension_security_check-extension or drop it in addons/anomaly/suspension_security_check-extension), then run composer dump-autoload.php artisan addon:install anomaly.suspension_security_check-extension (or via Admin → Addons → Extensions). Composer installing it is not enough; PyroCMS extensions are opt-in and must be enabled before they register anything.php artisan cache:clear (and addon:dump if your version supports it) so the addon manifest is rebuilt.First use case to verify it works:
Where to look first:
src/*ExtensionServiceProvider.php — proves how it registers (usually pushing a SecurityCheck into the Users module's security-check collection).SecurityCheck implementation) — this is the actual gate; it's typically small and worth reading in full.anomaly/users-module User\Security\* directory — to understand the SecurityCheck contract, the SecurityCheckResult, execution order, and the default message/redirect behavior.How it hooks in. The extension does not intercept login itself; it registers a security check that the Users module's login form/controller iterates before authenticating. So the leverage point is the built-in login flow, plus any custom flow where you invoke the check yourself. Typical registration looks like the provider binding a SuspensionSecurityCheck into the module's check collection; verify the exact method on the provider, since that determines whether the check is always-on or config-gated.
Day-to-day usage pattern. Use this as the single authoritative gate for suspended accounts across web login. Then, wherever you also authenticate users — API token endpoints, social login, custom login controllers — resolve and run the same check manually before issuing a session/token. Do not assume the extension covers those paths; by default it only hooks the Users module login.
Testing pattern (the most valuable day-to-day use). Add a feature test around the login route:
// suspended user is rejected
$user = factory(UserModel::class)->create(['suspended' => true]);
$this->post('/login', ['email' => $user->email, 'password' => 'secret'])
->assertSessionHasErrors(); // or assert redirect back with message
$this->assertGuest();
// active user still logs in (regression guard)
This is the pattern to repeat every time you upgrade the Users module — the check's behavior is your contract.
Composing with your own checks. If you add custom security checks (email-domain allowlist, IP gating, 2FA state), be deliberate about order. Put suspension first so blocked accounts get the "blocked" message rather than a downstream failure, and so a compromised/blocked user can't probe other checks.
Custom messaging / logging. The check class is small; extending it (or overriding the binding) is the intended extension point to change the message, log the attempt, or trigger an event (e.g., alert on repeated blocked logins). This is usually more practical than forking the addon.
Admin UX pairing. Wire it to whatever suspension mechanism you use. If you rely on the Users module's own suspend action, the check should read the same field; if you have a custom blocked/suspended_until column, confirm the check reads that attribute, or subclass it.
addon:list (or Admin → Extensions) and re-run after deploys.cache:clear (and addon:dump) or the check silently won't register.Auth::login() all skip the Users module login flow. Enforce the check explicitly at those boundaries.suspended vs a status enum). Add a temporary Log::info() inside the check to confirm it runs and what value it sees.How can I help you explore Laravel packages today?