Skip to content

Protect Dashboard: Add the Login protection section - #53192

Merged
kraftbj merged 35 commits into
trunkfrom
add/protect-dashboard-login-protection
Oct 14, 2026
Merged

kraftbj merged 35 commits into
trunkfrom
add/protect-dashboard-login-protection

Conversation

@enejb

@enejb enejb commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Fixes JETPACK-2958

Part of JETPACK-2883, JETPACK-2887

Proposed changes

  • Builds on the section framework from Protect Dashboard: Add tabbed layout and section framework #53190.
  • Adds the Login protection section to the flag-gated Protect dashboard (routes/dashboard/sections/login-protection/ and src/sections/class-login-protection.php in packages/protect).
  • Overview card: an "N of M on" badge (neutral when no method is available), the locale-formatted all-time blocked login attempt count while brute force protection is on, and one row per method (brute force protection, account protection, WordPress.com login) marked On, Off or Unavailable. WordPress.com login shows as Unavailable, and is left out of the count, when it can't run (no connected owner, or offline mode), even if its module is still active. The badges follow live module state once settings load, and "Configure login protection" switches to the Settings tab.
  • Settings card, in three parts:
    • Brute force protection: the protect toggle (disabled when the module is unavailable), plus the "Always allow specific IP addresses" toggle and list, with a button that adds the visitor's own IP. The list is hidden rather than unmounted while its toggle is off, so unsaved addresses survive the toggle going off or a failed save.
    • Account protection: the account-protection toggle (disabled when the module is unavailable).
    • WordPress.com login: the sso toggle, plus "Match accounts using email addresses" and "Require Two-Step Authentication". As in Jetpack Settings, the sso toggle is disabled without a connected owner or in offline mode, with help text that says which, and turning it off asks for confirmation first. Both options are disabled while SSO is off. When a filter or constant forces an option, the toggle is locked, shows the value SSO actually applies, and help text says so.
  • PHP state: module state for protect, account-protection and sso, the jetpack_protect_blocked_attempts count (always sent, formatted with number_format_i18n()), whether SSO can be turned on (connected owner, not offline), whether the site is in offline mode, the SSO locks (each Helpers call guarded with method_exists) and the effective SSO values (Helpers::match_by_email(), Helpers::is_two_step_required()), and the current IP. The section adds no REST routes of its own and uses jetpack/v4/settings. packages/protect now requires automattic/jetpack-ip directly for the IP lookup.
  • Tests: Jest for both cards (the "N of M on" count against live module state, the SSO confirmation, locked options, which toggles are enabled) and PHPUnit for the section state (blocked count formatting, SSO usability, SSO locks and effective values).

Related product discussion/links

Does this pull request change what data or activity we track or use?

No.

Testing instructions

  • Build and sync Jetpack to a connected test site, then run:

    • wp companion feature-flag enable jetpack-protect-dashboard (or force the jetpack-protect-dashboard flag on with the jetpack_feature_flag_enabled_jetpack-protect-dashboard filter)
    • wp eval 'Jetpack_Options::delete_option("available_modules");'
    • wp jetpack module activate protect-dashboard
    • wp jetpack module activate protect, then the same for account-protection and sso
  • Go to Jetpack › Protect (admin.php?page=jetpack-protect). Check that the Login protection card shows "3 of 3 on", "All-time blocked login attempts", and the three methods marked On.

  • Click "Configure login protection". The Settings tab should open, with three subsections under Login protection.

  • Turn "Match accounts using email addresses" off, then back on. Each change should save with a 200 POST to jetpack/v4/settings.

  • Turn on "Always allow specific IP addresses", click "Add my IP address", then click Save. Check that jetpack_waf_ip_allow_list now holds your IP.

  • Turn off "Allow users to log in with their WordPress.com account". A confirmation dialog should appear; Cancel leaves SSO on, "Turn off" saves it. The two options under it should then become disabled. Go back to Overview: the badge should now read "2 of 3 on" and the WordPress.com login row should say Off.

  • Locked option: add an mu-plugin with add_filter( 'jetpack_sso_require_two_step', '__return_true' ); and reload. "Require accounts to use WordPress.com Two-Step Authentication" should be on and disabled, with help text saying it is enforced. Remove the mu-plugin afterwards.

Review follow-ups

Fixed:

  • An enforced Two-Step (or match-by-email) setting no longer shows as off: PHP sends the effective values and locked toggles render them.
  • The blocked count is always sent, so turning brute force on from Settings no longer shows 0 for a non-zero count; it is locale-formatted.
  • Module toggles respect available, and the SSO toggle needs a connected owner and no offline mode, as in Jetpack Settings.
  • Turning SSO off asks for confirmation (AlertDialog from @wordpress/ui).
  • The badge is neutral for "0 of 0 on"; the settings link text is sentence case.

Deferred:

  • Heading structure: the subsection h3s sit under the card title, which ProtectCard (foundation) renders as a span; the fix belongs in ProtectCard (render the title as h2).
  • Jetpack Settings shows an SSO feedback survey after disabling; not ported, since it needs the connection user data and a survey URL that are out of scope here.
  • Allow-listing a proxy IP via "Add my IP address" is pre-existing behavior shared with Jetpack Settings and the Protect plugin.

Screenshots

Captured on a live Jurassic Ninja site at Jetpack › Protect, 1440px wide, with all three methods on.

Overview → Login protection card:
Login protection overview card
Settings → Login protection card:
Login protection settings card

With the site connected but no owner account linked (WordPress.com login's module still active):

Overview → WordPress.com login shows as Unavailable and is left out of the count:
Login protection overview card with WordPress.com login unavailable
Settings → the locked toggle says why:
Login protection settings card with WordPress.com login locked

@enejb enejb self-assigned this Oct 6, 2026
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack), and enable the add/protect-dashboard-login-protection branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack add/protect-dashboard-login-protection

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions github-actions Bot added [Feature] Protect Dashboard [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ labels Oct 6, 2026
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!


Jetpack plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.

@jp-launch-control

jp-launch-control Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 2 files.

File Coverage Δ% Δ Uncovered
projects/packages/protect/routes/dashboard/components/card.tsx 3/3 (100.00%) 33.33% -1 💚
projects/packages/protect/routes/dashboard/components/tab-link.tsx 6/7 (85.71%) 42.86% -3 💚

4 files are newly checked for coverage.

File Coverage
projects/packages/protect/src/sections/class-login-protection.php 18/22 (81.82%) 💚
projects/packages/protect/routes/dashboard/sections/login-protection/login-protection-card.tsx 18/19 (94.74%) 💚
projects/packages/protect/routes/dashboard/sections/login-protection/login-protection-settings-card.tsx 23/23 (100.00%) 💚
projects/packages/protect/routes/dashboard/sections/login-protection/types.ts 0/0 (—%) 🤷

Full summary · PHP report · JS report

@enejb
enejb force-pushed the add/protect-dashboard-login-protection branch from 6d2c079 to ba796ae Compare October 6, 2026 00:55
@enejb
enejb force-pushed the add/protect-dashboard-login-protection branch from ba796ae to 5c74b1e Compare October 6, 2026 01:11
With the protect-dashboard module active and no standalone plugin, the link went to protect-details or Jetpack Cloud instead of the Protect page.
… retry

A failed save no longer resets the IP list field to the saved value, and a
failed settings load now clears its error on retry and offers a Try again
button. Section types take an optional state type, the tab search param is
narrowed at runtime, and the settings hook returns a stable object.
ProtectCard and CardRow keep their props and now render through Card from
the WordPress UI package, so border, radius, background and header spacing
come from the design system.
… section registry

Adds routes/ to the client Jest roots so route tests run.
The base branch added a Jetpack_Protect_Dashboard_Test class of its own, so
the section registry tests now live in that class and the threats test moves
into the same suite directory.
…' into add/protect-dashboard-login-protection
My Jetpack no longer depends on the feature flags package, so the Jetpack plugin now reports the flag through jetpack_my_jetpack_protect_in_jetpack.
…' into add/protect-dashboard-login-protection
Pass LoginProtectionState to ProtectSection and DashboardContext now
that they take a state type, and drop the casts.
@enejb
enejb force-pushed the add/protect-dashboard-foundation branch 3 times, most recently from b531356 to 6567e4b Compare October 8, 2026 14:23
Base automatically changed from add/protect-dashboard-foundation to trunk October 8, 2026 15:34
…d-login-protection

# Conflicts:
#	projects/packages/my-jetpack/src/class-main-features.php
#	projects/packages/my-jetpack/src/products/class-protect.php
#	projects/packages/my-jetpack/tests/php/Protect_Product_Test.php
#	projects/plugins/jetpack/_inc/lib/class-jetpack-protect-dashboard-feature-flags.php
#	projects/plugins/jetpack/composer.json
#	projects/plugins/jetpack/composer.lock
#	projects/plugins/jetpack/modules/protect-dashboard.php
#	projects/plugins/jetpack/tests/php/_inc/lib/Jetpack_Protect_Dashboard_Feature_Flags_Test.php
@kraftbj
kraftbj marked this pull request as ready for review October 9, 2026 17:59
…t run

* The Overview card counted WordPress.com login as on whenever its
  module was active. With no connected owner, or in offline mode, the
  module doesn't run, so the card now shows it as unavailable and
  leaves it out of the count, matching the Settings card.
* The disabled toggle blamed a missing owner connection in offline
  mode too. PHP now reports offline mode separately and each cause
  gets its own text, including a module that isn't available.
* The allow list field was unmounted while its toggle was off, so
  unsaved addresses were lost when the toggle went off or its save
  failed. It stays mounted and is hidden instead.
* Require automattic/jetpack-ip directly, since the section uses its
  IP utilities, as every other package that uses them does.
* Tests: WordPress.com login usability with a connected owner and in
  offline mode, module toggles locked when unavailable, and the
  per-method badges on the Overview card.
@kraftbj kraftbj added [Status] Needs Review This PR is ready for review. and removed [Status] In Progress labels Oct 13, 2026
@kraftbj
kraftbj merged commit b0e0af8 into trunk Oct 14, 2026
90 checks passed
@kraftbj
kraftbj deleted the add/protect-dashboard-login-protection branch October 14, 2026 15:02
@github-actions github-actions Bot added [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. and removed [Status] Needs Review This PR is ready for review. labels Oct 14, 2026
@github-actions github-actions Bot added this to the jetpack/16.4 milestone Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Protect Dashboard [Package] My Jetpack [Package] Protect [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants