Skip to content

Commit

Permalink
Refactor threat history
Browse files Browse the repository at this point in the history
  • Loading branch information
nateweller committed Jul 7, 2024
1 parent 8106df9 commit 826e33f
Show file tree
Hide file tree
Showing 36 changed files with 810 additions and 860 deletions.
48 changes: 28 additions & 20 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion projects/plugins/protect/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"prop-types": "15.8.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router-dom": "6.2.2"
"react-router-dom": "6.24.0"
},
"devDependencies": {
"@automattic/jetpack-webpack-config": "workspace:*",
Expand Down
1 change: 0 additions & 1 deletion projects/plugins/protect/src/class-jetpack-protect.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ public function initial_state() {
'apiNonce' => wp_create_nonce( 'wp_rest' ),
'registrationNonce' => wp_create_nonce( 'jetpack-registration-nonce' ),
'status' => Status::get_status( $refresh_status_from_wpcom ),
'viewingScanHistory' => false,
'scanHistory' => Scan_History::get_scan_history( $refresh_status_from_wpcom ),
'installedPlugins' => Plugins_Installer::get_plugins(),
'installedThemes' => Sync_Functions::get_themes(),
Expand Down
51 changes: 0 additions & 51 deletions projects/plugins/protect/src/class-rest-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,30 +198,6 @@ public static function register_rest_endpoints() {
},
)
);

register_rest_route(
'jetpack-protect/v1',
'scan-history',
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => __CLASS__ . '::api_get_scan_history',
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
)
);

register_rest_route(
'jetpack-protect/v1',
'clear-scan-history-cache',
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => __CLASS__ . '::api_clear_scan_history_cache',
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
)
);
}

/**
Expand Down Expand Up @@ -433,31 +409,4 @@ public static function api_complete_onboarding_steps( $request ) {

return new WP_REST_Response( 'Onboarding step(s) completed.' );
}

/**
* Return Scan History for the API endpoint
*
* @param WP_REST_Request $request The request object.
*
* @return WP_REST_Response
*/
public static function api_get_scan_history( $request ) {
$scan_history = Scan_History::get_scan_history( false, $request['filter'] );
return rest_ensure_response( $scan_history, 200 );
}

/**
* Clear the Scan_History cache for the API endpoint
*
* @return WP_REST_Response
*/
public static function api_clear_scan_history_cache() {
$cache_cleared = Scan_History::delete_option();

if ( ! $cache_cleared ) {
return new WP_REST_Response( 'An error occured while attempting to clear the Jetpack Scan history cache.', 500 );
}

return new WP_REST_Response( 'Jetpack Scan history cache cleared.' );
}
}
155 changes: 14 additions & 141 deletions projects/plugins/protect/src/class-scan-history.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,9 @@ public static function delete_option() {
* Gets the current history of the Jetpack Protect checks
*
* @param bool $refresh_from_wpcom Refresh the local plan and history cache from wpcom.

Check failure on line 116 in projects/plugins/protect/src/class-scan-history.php

View workflow job for this annotation

GitHub Actions / PHP Code Sniffer (non-excluded files only)

Expected 1 spaces after parameter type; 2 found (Squiz.Commenting.FunctionComment.SpacingAfterParamType)
* @param array $filter The filter to apply to the data.
* @return History_Model|bool
*/
public static function get_scan_history( $refresh_from_wpcom = false, $filter = null ) {
public static function get_scan_history( $refresh_from_wpcom = false ) {
$has_required_plan = Plan::has_required_plan();
if ( ! $has_required_plan ) {
return false;
Expand All @@ -142,7 +141,7 @@ public static function get_scan_history( $refresh_from_wpcom = false, $filter =
)
);
} else {
$history = self::normalize_api_data( $history, $filter );
$history = self::normalize_api_data( $history );
}

self::$history = $history;
Expand Down Expand Up @@ -204,156 +203,30 @@ public static function fetch_from_api() {
* Formats the payload from the Scan API into an instance of History_Model.
*
* @param object $scan_data The data returned by the scan API.
* @param array $filter The filter to apply to the data.
* @return History_Model
*/
private static function normalize_api_data( $scan_data, $filter ) {
$history = new History_Model();
$history->num_threats = 0;
$history->num_core_threats = 0;
$history->num_plugins_threats = 0;
$history->num_themes_threats = 0;

if ( $filter ) {
$history->filter = $filter;
}

$history->last_checked = $scan_data->last_checked;
private static function normalize_api_data( $scan_data ) {
$history = new History_Model();

if ( empty( $scan_data->threats ) || ! is_array( $scan_data->threats ) ) {
return $history;
}

foreach ( $scan_data->threats as $threat ) {
if ( ! in_array( $threat->status, $history->filter, true ) ) {
continue;
}

if ( isset( $threat->extension->type ) ) {
if ( 'plugin' === $threat->extension->type ) {
self::handle_extension_threats( $threat, $history, 'plugin' );
continue;
}

if ( 'theme' === $threat->extension->type ) {
self::handle_extension_threats( $threat, $history, 'theme' );
continue;
}
}
$threat_model = new Threat_Model( $threat );
$history->threats[] = $threat_model;

Check failure on line 217 in projects/plugins/protect/src/class-scan-history.php

View workflow job for this annotation

GitHub Actions / Static analysis

TypeError PhanTypeMismatchProperty Assigning ($threat_model as a field) of type non-empty-array<int,\Automattic\Jetpack\Protect\Threat_Model> to property but \Automattic\Jetpack\Protect\History_Model->threats is \Automattic\Jetpack\Protect\Extension_Model[]

if ( 'Vulnerable.WP.Core' === $threat->signature ) {
self::handle_core_threats( $threat, $history );
continue;
++$history->num_threats;
switch ( $threat_model->status ) {
case 'fixed':
++$history->num_fixed_threats;
break;
case 'ignored':
++$history->num_ignored_threats;
break;
}

self::handle_additional_threats( $threat, $history );
}

return $history;
}

/**
* Handles threats for extensions such as plugins or themes.
*
* @param object $threat The threat object.
* @param object $history The history object.
* @param string $type The type of extension ('plugin' or 'theme').
* @return void
*/
private static function handle_extension_threats( $threat, $history, $type ) {
$extension_list = $type === 'plugin' ? 'plugins' : 'themes';
$extensions = &$history->{ $extension_list};
$found_index = null;

// Check if the extension does not exist in the array
foreach ( $extensions as $index => $extension ) {
if ( $extension->slug === $threat->extension->slug ) {
$found_index = $index;
break;
}
}

// Add the extension if it does not yet exist in the history
if ( $found_index === null ) {
$new_extension = new Extension_Model(
array(
'name' => $threat->extension->name ?? null,
'slug' => $threat->extension->slug ?? null,
'version' => $threat->extension->version ?? null,
'type' => $type,
'checked' => true,
'threats' => array(),
)
);
$extensions[] = $new_extension;
$found_index = array_key_last( $extensions );
}

// Add the threat to the found extension
$extensions[ $found_index ]->threats[] = new Threat_Model( $threat );

// Increment the threat counts
++$history->num_threats;
if ( $type === 'plugin' ) {
++$history->num_plugins_threats;
} elseif ( $type === 'theme' ) {
++$history->num_themes_threats;
}
}

/**
* Handles core threats
*
* @param object $threat The threat object.
* @param object $history The history object.
* @return void
*/
private static function handle_core_threats( $threat, $history ) {
// Check if the core version does not exist in the array
$found_index = null;
foreach ( $history->core as $index => $core ) {
if ( $core->version === $threat->version ) {
$found_index = $index;
break;
}
}

// Add the extension if it does not yet exist in the history
if ( null === $found_index ) {
$new_core = new Extension_Model(
array(
'name' => 'WordPress',
'version' => $threat->version,
'type' => 'core',
'checked' => true,
'threats' => array(),
)
);
$history->core[] = $new_core;
$found_index = array_key_last( $history->core );
}

// Add the threat to the found core
$history->core[ $found_index ]->threats[] = new Threat_Model( $threat );

++$history->num_threats;
++$history->num_core_threats;
}

/**
* Handles additional threats that are not core, plugin or theme
*
* @param object $threat The threat object.
* @param object $history The history object.
* @return void
*/
private static function handle_additional_threats( $threat, $history ) {
if ( ! empty( $threat->filename ) ) {
$history->files[] = new Threat_Model( $threat );
++$history->num_threats;
} elseif ( ! empty( $threat->table ) ) {
$history->database[] = new Threat_Model( $threat );
++$history->num_threats;
}
}
}
7 changes: 0 additions & 7 deletions projects/plugins/protect/src/js/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,6 @@ const API = {
method: 'POST',
data: { step_ids: stepIds },
} ),

fetchScanHistory: $filter =>
apiFetch( {
path: 'jetpack-protect/v1/scan-history',
method: 'POST',
data: { filter: $filter },
} ),
};

export default API;
Loading

0 comments on commit 826e33f

Please sign in to comment.