Skip to content

chore: Cherry-pick FormValidation migration + background user import onto develop - #537

Merged
hellopablo merged 7 commits into
developfrom
chore/cherry-pick-form-validation
Sep 6, 2026
Merged

chore: Cherry-pick FormValidation migration + background user import onto develop#537
hellopablo merged 7 commits into
developfrom
chore/cherry-pick-form-validation

Conversation

@hellopablo

Copy link
Copy Markdown
Member

Summary

Cherry-picks the full module-auth batch from feature/pre-new-admin, depends on nails/common#558.

  • 1c0aca2 (5d25d8a) refactor: Migrate legacy form validation to buildValidator()
  • 1b5c127 (63bca4f) refactor: Load language lines via the Translation service
  • 48222e4 (3a8dd87) refactor: Read cross-field values via the validation Context in import rules
  • fe2cb24 (7a47ee8) feat: Add Identity and Identifier validators and use them across the auth forms
  • 28c5b58 (4b31413) refactor: Read the target user via Context in the merge validator
  • 9ad8cc9 (be4baf0) chore: Boot Nails in the PHPUnit bootstrap
  • b6b4fdb (df55b33) feat: Move user import processing to background

The first 6 commits are the same validation-engine migration as the other modules in this cherry-pick series. The last one is a large, separate feature (54 files) moving CSV user-import processing to a background worker/cron job, added late to this batch — flagging for closer review than the rest.

Conflicts resolved

Most auto-merged cleanly despite touching Login.php, PasswordForgotten.php, Register.php, MfaDevice.php, MfaQuestion.php, Accounts.php, Merge.php, Init.php — all independently changed on develop. Verified each merge result by checking imports resolve, referenced variables are declared, and (for the Identity/Identifier validators) that the new classes are correctly imported and called.

Three required manual fixes in df55b33:

  1. Permission string → class. develop uses class-based permissions (userHasPermission(SomeClass::class) — a plain string throws PermissionException in nails/module-admin's Permission service). Fixed in two places: Admin\Controller\Import::PERMISSION and Api\Controller\Import::requirePermission(), both now return Permission\Users\Create::class (matching the pattern already used elsewhere on develop, e.g. admin/views/Accounts/edit/inc-actions.php).
  2. Migration number collision. develop is already at Migration19; the incoming Migration18.php (creating user_import/user_import_item tables) collided with develop's existing Migration18 (which itself exists specifically to reconcile pre-new-admin→develop migration numbering). Restored develop's Migration18 untouched and moved the new schema into Migration20.php.
  3. composer.json constraints. Added nails/module-api (used by the new Api\Controller\Import, not previously required), nails/module-cron (require) and nails/module-queue (require-dev + suggest) — all as dev-develop to match this repo's existing constraint style, not the incoming dev-feature/pre-new-admin. Confirmed all three have the classes this feature needs already on their own develop branches.

Also dropped two now-unused imports (use Nails\Auth\Model\User; from develop's side, use Nails\Auth\Controller\BaseAdmin; from the incoming side) that neither survives the merged Admin\Controller\Import.

Verification

(against nails/common's branch and every other dependency's develop — or, for module-admin/module-cdn, their own open cherry-pick PRs — synced into vendor/)

  • PRIVATE_KEY=abc123 ./vendor/bin/phpunit: 148/148 tests passing, 300 assertions.
  • phpstan: 1 error, identical to develop baseline (pre-existing, unrelated variable.undefined) — no regressions.
  • composer validate: composer.json is valid (lock-file staleness is expected/pre-existing in this local environment, not addressed here).

Do not merge yet — holding for review, and this one especially given its size.

🤖 Generated with Claude Code

hellopablo and others added 7 commits September 6, 2026 20:52
Replaces the deprecated `set_rules`/`set_message`/`run()` calls in admin account creation, social sign-on data capture, MFA device setup and MFA question setup with `buildValidator()`. Where the old code relied on `trim` being written back into `$_POST`, the success paths now read `getValidatedData()`. Forced `fv_*` message overrides are dropped where they matched the validator's defaults.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 5d25d8a)
Replaces `get_instance()->lang->load(...)` with `Factory::service('Translation')->load(...)`, which works outside a CodeIgniter request.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 63bca4f)
…ort rules

The password rule read `group_id` through the FormValidation service's CodeIgniter `validation_data` property; it now receives a `Context` and reads the row being validated directly, which also removes the last reason the rules needed the service at all.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 3a8dd87)
…the auth forms

`Nails\Auth\Validator\User\Identity` owns the email/username rules (required, format, length, uniqueness, per `APP_NATIVE_LOGIN_USING`) and the "already registered" message; `Identifier` owns the login identifier rule. Registration, social sign-on data capture, admin account creation, login and forgotten-password previously each rebuilt these rules with small differences; they now extend the shared validators via `addRules()`/`setRules()`. Both classes are unit tested with the uniqueness rule stubbed, so no database is needed.

Behaviour notes: registration and social sign-on now also enforce `alpha_dash_period` and `max_length[150]` on usernames (previously admin-only); admin account creation's "already registered" message now carries the forgotten-password link and uses the `auth_register_*_is_unique` lines rather than `fv_*_already_registered`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 7a47ee8)
The merge rule compared against `$oInput->post('user_id')`; it now reads the field from the data being validated via `Context::getValue()`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 4b31413)
`tests/bootstrap.php` now calls `Nails\Testing::bootstrapModule()` (and `phpunit.xml` supplies the `PRIVATE_KEY` it needs), matching `nails/common` and the other modules, so tests can use the Factory, services and models without CodeIgniter. The `Validator\User` tests depend on this and failed on CI with "No containers registered for nails/common".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit be4baf0)
LArge refactor to improve the handling of importing suers. Anything but modest CSVs would cause timeouts with no sane path to recovery or reporting. This commit overhauls this feature to add that, and more.

(cherry picked from commit df55b33)
@hellopablo
hellopablo merged commit 2ff16ef into develop Sep 6, 2026
5 of 10 checks passed
@hellopablo
hellopablo deleted the chore/cherry-pick-form-validation branch September 6, 2026 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant