feat: #2092153 Add drush commands to inspect and recover IP restrictions
Adds two drush commands aimed at the locked-out-administrator scenario from
the issue: you still have shell access but the IP restriction stops you
logging in, and drush user:login cannot help because the firewall signs
the one-time session straight back out.
restrict_by_ip:status [ip] [--user=NAME] lists the configured global,
per-user and role ranges as a table and, when given an IP, reports whether
each range matches and whether a login from that IP would be allowed
(mirroring the firewall's global-or-user logic). Ranges altered at runtime
by hook_restrict_by_ip_ranges_alter() implementations are not reflected,
and the command says so in its help.
restrict_by_ip:allow <cidr> [--user=NAME] appends a range to the global
allow list, or to a user's ranges field with --user. Input is validated
with the module's own IPTools, so a bad range fails the command instead of
locking the site down harder. Since the per-user ranges moved to a base
field (#3283846), plain drush config:set can no longer manage those; this
command covers both storages. Re-adding a range that is already allowed
reports it as already in place instead of a repeat success.
Commands are Drush 13 attribute-based classes in src/Drush/Commands with AutowireTrait, so there is no drush.services.yml and no hard dependency on drush; drush/drush ^13 is added to require-dev for the kernel tests. The README gains a "Locked out?" section documenting the commands plus the raw config:set recipes (including the quirk that clearing login_range needs '{}' because drush cannot parse '[]').
Tested: kernel tests cover both commands (validation, dedup, unknown user, status table with and without an IP); also verified end to end with real drush on a local site.
#ai-assisted
Closes #2092153