WALL #2 6b: native queue/trigger (remote-cron runner endpoint)#83
Closed
eilandert wants to merge 5 commits into
Closed
WALL #2 6b: native queue/trigger (remote-cron runner endpoint)#83eilandert wants to merge 5 commits into
eilandert wants to merge 5 commits into
Conversation
Foundation for porting the mailer-dependent tail (auth lost-password / reset-password, mailbox email-settings) off the ZF1 Zend_Mail path. Inert: nothing calls it yet, mirroring how each WALL #2 resource builder landed. - composer: require symfony/mailer ^8.0 (matches the locked symfony 8.1 band; pulls symfony/mime + event-dispatcher + egulias/email-validator). - src/Kernel/Mail/Mailer.php: framework-free sender. Turns the resources.mail.transport.* ini block (type smtp|sendmail, host, port, ssl tls|ssl|none, username/password, verify_peer[_name]) into a configured symfony transport and sends a Mime\Email. Transport-building decision is a pure, testable resolveConfig(); buildTransport() makes the real transport. ssl=ssl -> implicit TLS (465); ssl=tls/starttls -> opportunistic STARTTLS (587); omitted -> plaintext. verify_peer/_name routed through FILTER_VALIDATE_BOOLEAN so the ini "0" string disables verification. - Container::mailer(): lazily builds the Mailer from options[resources][mail][transport]. No Bootstrap change (reads options()). - tests/test-kernel-mailer.php (26 asserts) + regression.yml step. src/ stays free of the legacy framework prefix (guard green).
Ports OSS_Controller_Trait_Auth::lostPasswordAction/resetPasswordAction onto
the native kernel, sending through the slice-6b-1 Mailer instead of Zend_Mail.
The last two browser auth routes leave ZF1.
- AbstractController: mailer() (native getMailer) + renderEmail() (body-only
Smarty render, no page chrome) for the auth/email/* templates.
- AuthController::lostPasswordAction: anti-enumeration (identical response
whether or not the username exists); 40-char token stored as an expiring
(2h, max 5) tokens.password_reset indexed preference; reset link mailed via
the html email template. Captcha honoured when
resources.auth.oss.lost_password.use_captcha is on — fresh OSS_Captcha_Image
per render, typed text validated (as a field rule) against the SUBMITTED
captcha id; image-click requests a new one (requestnewimage) and
short-circuits before validation. The captcha PNG route (auth/captcha-image)
stays ZF1 via the dispatcher fallback (de-Zended in 6c).
- AuthController::resetPasswordAction: GET (from the emailed link) prefills
username + token from the path; valid POST checks the token against the live
reset-token preferences, sets the new hash, clears all tokens, zeroes any
failed-login counter, mails a confirmation, redirects to login. All failure
paths share one generic message.
- sendAuthEmail() honours resources.auth.oss.email_format (html|plaintext|both)
and sets From/To from identity.mailer.* + the admin email/formatted-name,
mirroring resolveTemplate() + the legacy actions.
- New native views auth/native-{lost,reset}-password.phtml (FormRenderer +
captcha image/refresh; no Zend_Form JS validator).
No NATIVE_CONTROLLERS / Kernel change (auth already native; the dispatcher
invokes the new action methods). src/ stays free of the legacy prefix.
Honouring resources.auth.oss.lost_password.use_captcha on the native
lost-password page surfaced two native-bootstrap gaps in the reused ZF1 captcha
(OSS_Captcha_Image extends Zend_Captcha_Image). Both fixed in the ZF1-zone entry
point / the unscanned OSS lib; slice 6c de-Zends the captcha and removes these.
- OSS_Utils::getIniOption(): null-guard the ZF1 front-controller bootstrap param
(null under the native bootstrap) and fall back to the merged options the
native entry publishes in Zend_Registry. Without it OSS_Captcha_Image's ctor
fatals (getTempDir -> getIniOption -> getApplication() on null).
- public/index.php (native zone): bridge Zend_Session to the already-open native
PHP session — set _sessionStarted/_readable/_writable so a ZF1
Zend_Session_Namespace (the captcha word store) attaches to the live session
instead of fataling in Zend_Session::start()/Namespace ("already started" /
"not marked as readable").
Image-validated (vimbadmin:dev + a mailpit SMTP sink): captcha-on GET renders the
image (auth/captcha-image 200 image/png), the RIGHT word sends the reset mail,
the WRONG word shows the inline "does not match that of the image" error and
sends nothing; captcha-off lost-password + the full reset round-trip also send +
verify (new password logs in, the spent token is rejected).
Ports the ZF1 emailSettingsAction + _sendSettingsEmail onto the native kernel — the last mailer-dependent browser action. Sends through the slice-6b-1 Mailer. - MailboxController::emailSettingsAction (GET|POST): the ajax "send settings" modal. GET returns the chrome-less modal (type select username/alt_email/other + an "other" free-text box, CSRF-guarded); POST send=1 resolves the recipient(s) and mails the per-user settings, returning the literal ok/error the modal JS expects, or re-rendering the modal with an inline error (the JS detects the <div class="modal-header"> prefix and swaps it in). "other" splits on comma and validates each address (ZF1 parity). - sendSettingsEmail(): From = server.email.*; body = mailbox/email/settings.phtml rendered with the per-user-substituted server.* display settings (Entities\Mailbox::substitute). The mailbox/sendSettingsEmail/preSetBody notify hook has no listeners, so it is not replicated; the welcome-email variant + cc are dropped (consistent with the other native mailbox actions, no mailer there). - AbstractController: renderEmail() generalised to renderPartial() (chrome-less template render for both email bodies AND ajax partials like this modal); AuthController updated to match. - New native view mailbox/native-email-settings.phtml (modal + type-toggle/ajax JS). No NATIVE_CONTROLLERS / Kernel change (mailbox already native; the dispatcher invokes the new action). Image-validated (vimbadmin:dev + mailpit): username -> mail to the mailbox; other with a bad address -> modal re-render, no send; other with two valid addresses -> mail to both; CSRF enforced. src/ stays free of the legacy prefix.
Native port of the ZF1 QueueController::triggerAction — the last WEB route still
served by the ZF1 fallback. Unauthenticated machine endpoint: Bearer-key
(SHA-256, constant-time) + source-IP-allowlist gated, then spawns a background
runner via the framework-free ViMbAdmin_QueueRunner::triggerCheck and returns
JSON. Empty queue.runner.key => 404 (disabled). No NATIVE_CONTROLLERS change
(queue already native; the dispatcher invokes the new action) — but this makes
canHandle('/queue/trigger') true, so the native stack now serves it instead of
falling through to ZF1.
Image-validated (vimbadmin:dev): empty key -> 404; no bearer -> 401; bad key ->
403; correct Bearer + allowed IP -> 200 {"triggered":false}. src/ stays free of
the legacy prefix (calls \ViMbAdmin_Net + \ViMbAdmin_QueueRunner, both
framework-free).
473018d to
35824c3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #82. Native port of the ZF1
QueueController::triggerAction— thelast web route still served by the ZF1 fallback.
Unauthenticated machine endpoint: Bearer-key (SHA-256, constant-time) + source-IP
allowlist gated, then spawns a background runner via the framework-free
ViMbAdmin_QueueRunner::triggerCheckand returns JSON. Emptyqueue.runner.key⇒ 404 (disabled). No
NATIVE_CONTROLLERSchange (queue already native), but thismakes
canHandle('/queue/trigger')true so the native stack serves it.Image validation (vimbadmin:dev)
404 {"error":"queue trigger disabled"}401 {"error":"missing bearer"}403 {"error":"bad key"}200 {"triggered":false}After this, the only remaining ZF1-served routes are the
cli-*entrypoints(
cli-run,cli-reset-totp,cli-delete-pending,cli-schema-update) — invokedas CLI (
vimbtool/php public/index.phpargs), NOT web-dispatched. Those need adesign call (native CLI bootstrap vs standalone shim) and do not block the web
tier being fully native. Then 6c drops the ZF1 fallback + de-Zends
library/OSS.