Skip to content

Commit

Permalink
My Jetpack: Add a Protect 'needs-attention' status when Threats are d…
Browse files Browse the repository at this point in the history
…etected. (#40628)

* Add a error/warning status and a "Fix threats" CTA when Protect has threats.

Committed via a GitHub action: https://github.com/Automattic/jetpack/actions/runs/12600308956

Upstream-Ref: Automattic/jetpack@681e85c
  • Loading branch information
elliottprogrammer authored and matticbot committed Jan 3, 2025
1 parent 36a471e commit f279817
Show file tree
Hide file tree
Showing 13 changed files with 192 additions and 130 deletions.
1 change: 1 addition & 0 deletions jetpack_vendor/automattic/jetpack-my-jetpack/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
This is an alpha version! The changes listed here are not final.

### Added
- My Jetpack: Added a new status for when Protect detects threats on the site.
- My Jetpack: introduce feature cards for recommendations in My Jetpack.

### Changed
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?php return array('dependencies' => array('jetpack-connection', 'jetpack-script-data', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives', 'wp-url'), 'version' => '3ad67385649d69b798fc');
<?php return array('dependencies' => array('jetpack-connection', 'jetpack-script-data', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives', 'wp-url'), 'version' => 'b1c6623ded15ad148fec');
26 changes: 13 additions & 13 deletions jetpack_vendor/automattic/jetpack-my-jetpack/build/index.js

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions jetpack_vendor/automattic/jetpack-my-jetpack/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,12 @@ interface Window {
};
};
backup_failure?: {
source: 'rewind' | 'last_backup';
status: RewindStatus | BackupStatus;
last_updated: string;
type: 'warning' | 'error';
data: {
source: 'rewind' | 'last_backup';
status: RewindStatus | BackupStatus;
last_updated: string;
};
};
[ key: `${ string }--plan_expired` ]: {
product_slug: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
use Automattic\Jetpack\Licensing;
use Automattic\Jetpack\Modules;
use Automattic\Jetpack\Plugins_Installer;
use Automattic\Jetpack\Protect_Status\Status as Protect_Status;
use Automattic\Jetpack\Status;
use Automattic\Jetpack\Status\Host as Status_Host;
use Automattic\Jetpack\Sync\Functions as Sync_Functions;
Expand Down Expand Up @@ -234,7 +233,7 @@ public static function enqueue_scripts() {
$previous_score = $speed_score_history->latest( 1 );
}
$latest_score['previousScores'] = $previous_score['scores'] ?? array();
$scan_data = Protect_Status::get_status();
$scan_data = Products\Protect::get_protect_data();
self::update_historically_active_jetpack_modules();

$waf_config = array();
Expand Down Expand Up @@ -1045,7 +1044,7 @@ public static function alert_if_paid_plan_expiring( array $red_bubble_slugs ) {
* @return array
*/
public static function alert_if_last_backup_failed( array $red_bubble_slugs ) {
// Make sure we're dealing with the backup product only
// Make sure we're dealing with the Backup product only
if ( ! Products\Backup::has_paid_plan_for_product() ) {
return $red_bubble_slugs;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class Products {
const STATUS_NEEDS_PLAN = 'needs_plan';
const STATUS_NEEDS_ACTIVATION = 'needs_activation';
const STATUS_NEEDS_FIRST_SITE_CONNECTION = 'needs_first_site_connection';
const STATUS_NEEDS_ATTENTION = 'needs_attention';
const STATUS_NEEDS_ATTENTION__WARNING = 'needs_attention_warning';
const STATUS_NEEDS_ATTENTION__ERROR = 'needs_attention_error';

/**
* List of statuses that display the module as disabled
Expand Down Expand Up @@ -67,7 +68,8 @@ class Products {
self::STATUS_USER_CONNECTION_ERROR,
self::STATUS_PLUGIN_ABSENT_WITH_PLAN,
self::STATUS_NEEDS_PLAN,
self::STATUS_NEEDS_ATTENTION,
self::STATUS_NEEDS_ATTENTION__ERROR,
self::STATUS_NEEDS_ATTENTION__WARNING,
);

/**
Expand Down Expand Up @@ -109,7 +111,8 @@ class Products {
self::STATUS_NEEDS_PLAN,
self::STATUS_NEEDS_ACTIVATION,
self::STATUS_NEEDS_FIRST_SITE_CONNECTION,
self::STATUS_NEEDS_ATTENTION,
self::STATUS_NEEDS_ATTENTION__WARNING,
self::STATUS_NEEDS_ATTENTION__ERROR,
);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,12 @@ public static function does_module_need_attention() {
if ( ! is_wp_error( $rewind_state ) ) {
if ( $rewind_state->state !== 'active' && $rewind_state->state !== 'provisioning' && $rewind_state->state !== 'awaiting_credentials' ) {
$backup_failed_status = array(
'source' => 'rewind',
'status' => isset( $rewind_state->reason ) && ! empty( $rewind_state->reason ) ? $rewind_state->reason : $rewind_state->state,
'last_updated' => $rewind_state->last_updated,
'type' => 'error',
'data' => array(
'source' => 'rewind',
'status' => isset( $rewind_state->reason ) && ! empty( $rewind_state->reason ) ? $rewind_state->reason : $rewind_state->state,
'last_updated' => $rewind_state->last_updated,
),
);
}
}
Expand All @@ -270,9 +273,12 @@ public static function does_module_need_attention() {
if ( $last_backup && isset( $last_backup->status ) ) {
if ( $last_backup->status !== 'started' && ! preg_match( '/-will-retry$/', $last_backup->status ) && $last_backup->status !== 'finished' ) {
$backup_failed_status = array(
'source' => 'last_backup',
'status' => $last_backup->status,
'last_updated' => $last_backup->last_updated,
'type' => 'error',
'data' => array(
'source' => 'last_backup',
'status' => $last_backup->status,
'last_updated' => $last_backup->last_updated,
),
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Automattic\Jetpack\Connection\Client;
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
use Automattic\Jetpack\Modules;
use Automattic\Jetpack\My_Jetpack\Products\Backup;
use Automattic\Jetpack\Plugins_Installer;
use Automattic\Jetpack\Status;
use Jetpack_Options;
Expand Down Expand Up @@ -725,8 +724,12 @@ public static function get_status() {
} elseif ( static::$requires_user_connection && ! ( new Connection_Manager() )->has_connected_owner() ) {
$status = Products::STATUS_USER_CONNECTION_ERROR;
} elseif ( static::has_paid_plan_for_product() ) {
if ( static::$slug === 'backup' && Backup::does_module_need_attention() ) {
$status = Products::STATUS_NEEDS_ATTENTION;
$needs_attention = static::does_module_need_attention();
if ( ! empty( $needs_attention ) && is_array( $needs_attention ) ) {
$status = Products::STATUS_NEEDS_ATTENTION__WARNING;
if ( isset( $needs_attention['type'] ) && 'error' === $needs_attention['type'] ) {
$status = Products::STATUS_NEEDS_ATTENTION__ERROR;
}
}
if ( static::is_paid_plan_expired() ) {
$status = Products::STATUS_EXPIRED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Automattic\Jetpack\Connection\Client;
use Automattic\Jetpack\My_Jetpack\Hybrid_Product;
use Automattic\Jetpack\My_Jetpack\Wpcom_Products;
use Automattic\Jetpack\Protect_Status\Status as Protect_Status;
use Automattic\Jetpack\Redirect;
use Jetpack_Options;
use WP_Error;
Expand Down Expand Up @@ -156,6 +157,15 @@ private static function get_state_from_wpcom() {
return $status;
}

/**
* Get the normalized protect/scan data
*
* @return Object|WP_Error
*/
public static function get_protect_data() {
return Protect_Status::get_status();
}

/**
* Get the product's available tiers
*
Expand Down Expand Up @@ -272,6 +282,43 @@ public static function get_pricing_for_ui() {
);
}

/**
* Determines whether the module/plugin/product needs the users attention.
* Typically due to some sort of error where user troubleshooting is needed.
*
* @return boolean|array
*/
public static function does_module_need_attention() {
$protect_threat_status = false;

// Check if there are scan threats.
$protect_data = self::get_protect_data();
if ( is_wp_error( $protect_data ) ) {
return $protect_threat_status; // false
}
$critical_threat_count = false;
if ( ! empty( $protect_data->threats ) ) {
$critical_threat_count = array_reduce(
$protect_data->threats,
function ( $accum, $threat ) {
return $threat->severity >= 5 ? ++$accum : $accum;
},
0
);

$protect_threat_status = array(
'type' => $critical_threat_count ? 'error' : 'warning',
'data' => array(
'threat_count' => count( $protect_data->threats ),
'critical_threat_count' => $critical_threat_count,
'fixable_threat_ids' => $protect_data->fixable_threat_ids,
),
);
}

return $protect_threat_status;
}

/**
* Get the product-slugs of the paid plans for this product.
* (Do not include bundle plans, unless it's a bundle plan itself).
Expand Down
2 changes: 1 addition & 1 deletion jetpack_vendor/i18n-map.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
),
'jetpack-my-jetpack' => array(
'path' => 'jetpack_vendor/automattic/jetpack-my-jetpack',
'ver' => '5.3.0-alpha1735834987',
'ver' => '5.3.0-alpha1735919739',
),
'jetpack-password-checker' => array(
'path' => 'jetpack_vendor/automattic/jetpack-password-checker',
Expand Down
Loading

0 comments on commit f279817

Please sign in to comment.