Skip to content

fix: use _ajax_nonce for network-activate AJAX handler (#836)#875

Merged
superdav42 merged 2 commits intomainfrom
bugfix/836-network-activate-button
Apr 15, 2026
Merged

fix: use _ajax_nonce for network-activate AJAX handler (#836)#875
superdav42 merged 2 commits intomainfrom
bugfix/836-network-activate-button

Conversation

@superdav42
Copy link
Copy Markdown
Collaborator

@superdav42 superdav42 commented Apr 15, 2026

Summary

Follow-up to #871. The Network Activate button now fires correctly (inline <script> moved to external file), but the AJAX request returned 403 because the nonce parameter name nonce was not matching WordPress's standard _ajax_nonce convention.

Changes

  • JS (assets/js/network-activate.js): send nonce as _ajax_nonce (WordPress standard), read from data-ajax-nonce attribute
  • PHP (inc/admin-pages/class-setup-wizard-admin-page.php):
    • Move current_user_can() check before nonce check — gives a meaningful "Permission denied" error instead of opaque 403
    • Use check_ajax_referer('...', false, false) — the false second arg makes WordPress check both _ajax_nonce and _wpnonce fallbacks; the false third arg prevents wp_die(-1) so we return a JSON error instead
  • View (views/wizards/setup/requirements_table.php): data-noncedata-ajax-nonce
  • Test: updated to reflect reordered guards (capability before nonce)

Testing

  • Setup_Wizard_Admin_Page_Test passes (37 tests, exit 0)
  • Manual: visit Setup Wizard → Pre-install Checks when plugin is not network-activated → click Network Activate

Resolves #836

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Enhanced security and error handling for network plugin activation. When nonce verification fails, users now receive clear instructions to reload the page and retry the activation.

The inline <script> in requirements_table.php was rendered as visible
text because wu_get_template_contents() captures output via ob_start
and injects it as innerHTML — browsers do not execute script tags
inserted this way.

Extract the click handler to assets/js/network-activate.js, enqueue it
via wp_enqueue_script in register_scripts(), and pass the translated
error string through wp_localize_script.

Also fix the AJAX nonce handling:
- Use _ajax_nonce parameter (WordPress standard convention) instead of
  the generic 'nonce' key which can conflict with server-side filtering
- Move capability check before nonce check so unauthorized users get a
  meaningful 'Permission denied' error instead of an opaque 403
- Use check_ajax_referer with stop=false to return a JSON error on
  nonce failure instead of wp_die(-1)

Resolves #836
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 15, 2026

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: af2385d1-d299-461e-8aee-9df1df70a667

📥 Commits

Reviewing files that changed from the base of the PR and between a7e802e and 3ee7cc6.

📒 Files selected for processing (4)
  • assets/js/network-activate.js
  • inc/admin-pages/class-setup-wizard-admin-page.php
  • tests/WP_Ultimo/Admin_Pages/Setup_Wizard_Admin_Page_Test.php
  • views/wizards/setup/requirements_table.php

📝 Walkthrough

Walkthrough

This PR updates the AJAX network activation flow to use WordPress AJAX naming conventions. The nonce is now read from data-ajax-nonce instead of data-nonce, the POST payload key changes from nonce to _ajax_nonce, and server-side nonce verification is made explicit with proper error handling for failed verification.

Changes

Cohort / File(s) Summary
Client-side nonce handling
assets/js/network-activate.js, views/wizards/setup/requirements_table.php
Updated to read nonce from data-ajax-nonce attribute and send it as _ajax_nonce in AJAX POST payload, aligning with WordPress AJAX conventions.
Server-side verification
inc/admin-pages/class-setup-wizard-admin-page.php
Modified ajax_network_activate() to use explicit conditional nonce verification with check_ajax_referer(), returning early with bad-nonce error and instruction message if verification fails.
Test updates
tests/WP_Ultimo/Admin_Pages/Setup_Wizard_Admin_Page_Test.php
Removed nonce setup from test and relied on permission check instead, reflecting the updated guard order where capability check occurs before nonce check.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested labels

bug

Poem

🐰 A nonce by any other name would read as sweet,
From data-nonce to data-ajax-nonce, the journey's neat,
WordPress conventions guide our humble hare,
Network activation flows with proper care! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adopting _ajax_nonce convention for the network-activate AJAX handler, which is the core technical fix across all modified files.
Linked Issues check ✅ Passed The pull request implements all coding requirements from issue #836: Network Activate button functionality with proper AJAX nonce handling, capability checks, and JSON error responses instead of opaque failures.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the network-activation feature: AJAX handler updates, nonce handling standardization, button DOM attributes, and supporting test updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bugfix/836-network-activate-button

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 15, 2026

Performance Test Results

Performance test results for 5e5395f are in 🛎️!

Note: the numbers in parentheses show the difference to the previous (baseline) test run. Differences below 2% or 0.5 in absolute values are not shown.

URL: /

Run DB Queries Memory Before Template Template WP Total LCP TTFB LCP - TTFB
0 41 37.80 MB 853.50 ms 159.00 ms 1045.50 ms 2000.00 ms 1915.60 ms 88.50 ms (-5.05 ms / -6% )
1 56 49.03 MB 858.00 ms (-95.50 ms / -11% ) 139.50 ms (-8.50 ms / -6% ) 1000.50 ms (-99.00 ms / -10% ) 1958.00 ms (-116.00 ms / -6% ) 1874.20 ms (-122.20 ms / -7% ) 81.15 ms

@github-actions
Copy link
Copy Markdown

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

@superdav42 superdav42 merged commit adcf871 into main Apr 15, 2026
10 of 11 checks passed
superdav42 added a commit that referenced this pull request Apr 15, 2026
The setup wizard requirements table HTML passes through wp_kses()
twice (field-note.php and default.php templates). The button element's
kses allowlist only permitted disabled, name, and value — stripping
type="button" and data-ajax-nonce from the Network Activate button.

Without type="button", the click submits the parent form instead of
triggering the AJAX handler. Without data-ajax-nonce, the JS reads
undefined and the server rejects the request with bad-nonce.

PR #875 correctly moved the JS to an external file and changed the
nonce field to _ajax_nonce, but the button attributes were still
stripped before reaching the browser.
superdav42 added a commit that referenced this pull request Apr 15, 2026
The setup wizard requirements table HTML passes through wp_kses()
twice (field-note.php and default.php templates). The button element's
kses allowlist only permitted disabled, name, and value — stripping
type="button" and data-ajax-nonce from the Network Activate button.

Without type="button", the click submits the parent form instead of
triggering the AJAX handler. Without data-ajax-nonce, the JS reads
undefined and the server rejects the request with bad-nonce.

PR #875 correctly moved the JS to an external file and changed the
nonce field to _ajax_nonce, but the button attributes were still
stripped before reaching the browser.
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.

If ultimate multisite is not network active in setup wizard it should try to activate it

1 participant