diff --git a/projects/js-packages/components/components/scan-report/constants.ts b/projects/js-packages/components/components/scan-report/constants.ts index 436eed91c5701..6a10d008b876f 100644 --- a/projects/js-packages/components/components/scan-report/constants.ts +++ b/projects/js-packages/components/components/scan-report/constants.ts @@ -7,6 +7,12 @@ import { wordpress as coreIcon, } from '@wordpress/icons'; +export const STATUS_TYPES = [ + { value: 'checked', label: __( 'Checked', 'jetpack-components' ) }, + { value: 'unchecked', label: __( 'Unchecked', 'jetpack-components' ) }, + { value: 'threat', label: __( 'Threat', 'jetpack-components' ) }, +]; + export const TYPES = [ { value: 'core', label: __( 'WordPress', 'jetpack-components' ) }, { value: 'plugins', label: __( 'Plugin', 'jetpack-components' ) }, diff --git a/projects/js-packages/components/components/scan-report/index.tsx b/projects/js-packages/components/components/scan-report/index.tsx index 14795376f7d95..4600ecf98d9db 100644 --- a/projects/js-packages/components/components/scan-report/index.tsx +++ b/projects/js-packages/components/components/scan-report/index.tsx @@ -7,7 +7,7 @@ import { DataViews, filterSortAndPaginate, } from '@wordpress/dataviews'; -import { __ } from '@wordpress/i18n'; +import { __, _n } from '@wordpress/i18n'; import { Icon } from '@wordpress/icons'; import { useCallback, useMemo, useState } from 'react'; import ShieldIcon from '../shield-icon'; @@ -17,6 +17,7 @@ import { FIELD_ICON, FIELD_STATUS, FIELD_TYPE, + STATUS_TYPES, TYPES, ICONS, } from './constants'; @@ -26,12 +27,13 @@ import styles from './styles.module.scss'; * DataViews component for displaying a scan report. * * @param {object} props - Component props. + * @param {string} props.dataSource - Data source. * @param {Array} props.data - Scan report data. * @param {Function} props.onChangeSelection - Callback function run when an item is selected. * * @return {JSX.Element} The ScanReport component. */ -export default function ScanReport( { data, onChangeSelection } ): JSX.Element { +export default function ScanReport( { dataSource, data, onChangeSelection } ): JSX.Element { const baseView = { search: '', filters: [], @@ -84,8 +86,19 @@ export default function ScanReport( { data, onChangeSelection } ): JSX.Element { const result: Field< ScanReportExtension >[] = [ { id: FIELD_STATUS, + elements: STATUS_TYPES, label: __( 'Status', 'jetpack-components' ), + getValue( { item } ) { + if ( item.checked ) { + if ( item.threats.length > 0 ) { + return 'threat'; + } + return 'checked'; + } + return 'unchecked'; + }, render( { item }: { item: ScanReportExtension } ) { + const scanApi = 'scan_api' === dataSource; let variant: 'info' | 'warning' | 'success' = 'info'; let text = __( 'This item was added to your site after the most recent scan. We will check for threats during the next scheduled one.', @@ -95,10 +108,34 @@ export default function ScanReport( { data, onChangeSelection } ): JSX.Element { if ( item.checked ) { if ( item.threats.length > 0 ) { variant = 'warning'; - text = __( 'Threat detected.', 'jetpack-components' ); + text = _n( + 'Vulnerability detected.', + 'Vulnerabilities detected.', + item.threats.length, + 'jetpack-components' + ); + + if ( scanApi ) { + text = _n( + 'Threat detected.', + 'Threats detected.', + item.threats.length, + 'jetpack-components' + ); + } } else { variant = 'success'; - text = __( 'No known threats found that affect this version.', 'jetpack-components' ); + text = __( + 'No known vulnerabilities found that affect this version.', + 'jetpack-components' + ); + + if ( scanApi ) { + text = __( + 'No known threats found that affect this version.', + 'jetpack-components' + ); + } } } @@ -127,6 +164,7 @@ export default function ScanReport( { data, onChangeSelection } ): JSX.Element { { id: FIELD_VERSION, label: __( 'Version', 'jetpack-components' ), + enableSorting: false, enableGlobalSearch: true, getValue( { item }: { item: ScanReportExtension } ) { return item.version ? item.version : ''; @@ -155,7 +193,7 @@ export default function ScanReport( { data, onChangeSelection } ): JSX.Element { ]; return result; - }, [ view ] ); + }, [ view, dataSource ] ); /** * Apply the view settings (i.e. filters, sorting, pagination) to the dataset. diff --git a/projects/js-packages/components/components/scan-report/stories/index.stories.tsx b/projects/js-packages/components/components/scan-report/stories/index.stories.tsx index 63926908850de..eebcbc428fb39 100644 --- a/projects/js-packages/components/components/scan-report/stories/index.stories.tsx +++ b/projects/js-packages/components/components/scan-report/stories/index.stories.tsx @@ -20,6 +20,7 @@ export default { export const Default = args => ; Default.args = { + dataSource: 'scan_api', data: [ { id: 1, @@ -64,6 +65,12 @@ Default.args = { title: 'Malicious code found in file: jptt_eicar.php', severity: 1, }, + { + id: 198352407, + signature: 'EICAR_AV_Test_Suspicious', + title: 'Malicious code found in file: jptt_eicar.php', + severity: 1, + }, ], checked: true, type: 'files', diff --git a/projects/js-packages/components/components/threats-data-views/constants.ts b/projects/js-packages/components/components/threats-data-views/constants.ts index 59b79a7618453..84c7c5cf7b0cd 100644 --- a/projects/js-packages/components/components/threats-data-views/constants.ts +++ b/projects/js-packages/components/components/threats-data-views/constants.ts @@ -19,6 +19,7 @@ export const THREAT_TYPES = [ { value: 'themes', label: __( 'Theme', 'jetpack-components' ) }, { value: 'core', label: __( 'WordPress', 'jetpack-components' ) }, { value: 'file', label: __( 'File', 'jetpack-components' ) }, + { value: '', label: __( 'Unknown', 'jetpack-components' ) }, ]; export const THREAT_ICONS = { diff --git a/projects/js-packages/components/components/threats-data-views/index.tsx b/projects/js-packages/components/components/threats-data-views/index.tsx index 6af7c028f4c3a..0d81b8995060e 100644 --- a/projects/js-packages/components/components/threats-data-views/index.tsx +++ b/projects/js-packages/components/components/threats-data-views/index.tsx @@ -280,18 +280,7 @@ export default function ThreatsDataViews( { label: __( 'Type', 'jetpack-components' ), elements: THREAT_TYPES, getValue( { item }: { item: Threat } ) { - switch ( getThreatType( item ) ) { - case 'core': - return __( 'WordPress', 'jetpack-components' ); - case 'plugins': - return __( 'Plugin', 'jetpack-components' ); - case 'themes': - return __( 'Theme', 'jetpack-components' ); - case 'file': - return __( 'File', 'jetpack-components' ); - default: - return __( 'Unknown', 'jetpack-components' ); - } + return getThreatType( item ) ?? ''; }, }, { diff --git a/projects/plugins/protect/changelog/update-protect-add-scan-report-to-home b/projects/plugins/protect/changelog/update-protect-add-scan-report-to-home new file mode 100644 index 0000000000000..0478ae51501b8 --- /dev/null +++ b/projects/plugins/protect/changelog/update-protect-add-scan-report-to-home @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Adds ScanReport to HomeRoute diff --git a/projects/plugins/protect/src/js/routes/firewall/firewall-admin-section-hero.tsx b/projects/plugins/protect/src/js/routes/firewall/firewall-admin-section-hero.tsx index 837f649c67f16..c302f93dd8863 100644 --- a/projects/plugins/protect/src/js/routes/firewall/firewall-admin-section-hero.tsx +++ b/projects/plugins/protect/src/js/routes/firewall/firewall-admin-section-hero.tsx @@ -88,12 +88,12 @@ const FirewallAdminSectionHero = () => { { heading } - { subheading } + { subheading } { wafSupported && ( diff --git a/projects/plugins/protect/src/js/routes/firewall/firewall-statcards.jsx b/projects/plugins/protect/src/js/routes/firewall/firewall-statcards.jsx index 1eebd67cb60d7..7b1fd7cbbbede 100644 --- a/projects/plugins/protect/src/js/routes/firewall/firewall-statcards.jsx +++ b/projects/plugins/protect/src/js/routes/firewall/firewall-statcards.jsx @@ -1,13 +1,11 @@ -import { Text, useBreakpointMatch, StatCard } from '@automattic/jetpack-components'; +import { useBreakpointMatch, StatCard } from '@automattic/jetpack-components'; import { __, sprintf } from '@wordpress/i18n'; import { Icon, shield, chartBar } from '@wordpress/icons'; import { useCallback, useMemo } from 'react'; -import usePlan from '../../hooks/use-plan'; import useWafData from '../../hooks/use-waf-data'; import styles from './styles.module.scss'; const FirewallStatCards = () => { - const { hasPlan } = usePlan(); const { config: { bruteForceProtection: isBruteForceModuleEnabled }, isEnabled: isWafModuleEnabled, @@ -22,26 +20,22 @@ const FirewallStatCards = () => { const { currentDay: currentDayBlockCount, thirtyDays: thirtyDayBlockCounts } = stats ? stats.blockedRequests : { currentDay: 0, thirtyDays: 0 }; - const isFeatureDisabled = ! isSupportedWafFeatureEnabled || ! hasPlan; const defaultArgs = useMemo( () => ( { - className: isFeatureDisabled ? styles.disabled : styles.active, + className: ! isSupportedWafFeatureEnabled ? styles.disabled : styles.active, variant: isSmall ? 'horizontal' : 'square', } ), - [ isFeatureDisabled, isSmall ] + [ isSupportedWafFeatureEnabled, isSmall ] ); const StatCardIcon = useCallback( ( { icon } ) => ( - { ! isSmall && ! hasPlan && ( - { __( 'Paid feature', 'jetpack-protect' ) } - ) } ), - [ isSmall, hasPlan ] + [] ); const StatCardLabel = useCallback( @@ -77,9 +71,9 @@ const FirewallStatCards = () => { ...defaultArgs, icon: , label: , - value: isFeatureDisabled ? 0 : currentDayBlockCount, + value: ! isSupportedWafFeatureEnabled ? 0 : currentDayBlockCount, } ), - [ defaultArgs, StatCardIcon, StatCardLabel, isFeatureDisabled, currentDayBlockCount ] + [ defaultArgs, StatCardIcon, StatCardLabel, isSupportedWafFeatureEnabled, currentDayBlockCount ] ); const thirtyDaysArgs = useMemo( @@ -87,9 +81,9 @@ const FirewallStatCards = () => { ...defaultArgs, icon: , label: , - value: isFeatureDisabled ? 0 : thirtyDayBlockCounts, + value: ! isSupportedWafFeatureEnabled ? 0 : thirtyDayBlockCounts, } ), - [ defaultArgs, StatCardIcon, StatCardLabel, isFeatureDisabled, thirtyDayBlockCounts ] + [ defaultArgs, StatCardIcon, StatCardLabel, isSupportedWafFeatureEnabled, thirtyDayBlockCounts ] ); return ( diff --git a/projects/plugins/protect/src/js/routes/home/home-admin-section-hero.tsx b/projects/plugins/protect/src/js/routes/home/home-admin-section-hero.tsx index 12d887e933f43..d695f05eea9cc 100644 --- a/projects/plugins/protect/src/js/routes/home/home-admin-section-hero.tsx +++ b/projects/plugins/protect/src/js/routes/home/home-admin-section-hero.tsx @@ -29,7 +29,8 @@ const HomeAdminSectionHero: React.FC = () => { ) : __( 'We stay ahead of security vulnerabilities to keep your site protected.', - 'jetpack-protect' + 'jetpack-protect', + /* dummy arg to avoid bad minification */ 0 ) }