@automattic/jetpack-scan 0.5.8 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/build/components/index.d.ts +4 -0
  3. package/build/components/index.js +4 -0
  4. package/build/components/threat-fixer-button/index.d.ts +16 -0
  5. package/build/components/threat-fixer-button/index.js +56 -0
  6. package/build/components/threat-modal/fixer-state-notice.d.ts +19 -0
  7. package/build/components/threat-modal/fixer-state-notice.js +44 -0
  8. package/build/components/threat-modal/index.d.ts +51 -0
  9. package/build/components/threat-modal/index.js +45 -0
  10. package/build/components/threat-modal/threat-actions.d.ts +7 -0
  11. package/build/components/threat-modal/threat-actions.js +40 -0
  12. package/build/components/threat-modal/threat-fix-confirmation.d.ts +7 -0
  13. package/build/components/threat-modal/threat-fix-confirmation.js +19 -0
  14. package/build/components/threat-modal/threat-fix-details.d.ts +7 -0
  15. package/build/components/threat-modal/threat-fix-details.js +40 -0
  16. package/build/components/threat-modal/threat-notice.d.ts +16 -0
  17. package/build/components/threat-modal/threat-notice.js +23 -0
  18. package/build/components/threat-modal/threat-summary.d.ts +7 -0
  19. package/build/components/threat-modal/threat-summary.js +16 -0
  20. package/build/components/threat-modal/threat-technical-details.d.ts +7 -0
  21. package/build/components/threat-modal/threat-technical-details.js +26 -0
  22. package/build/components/threat-severity-badge/index.d.ts +4 -0
  23. package/build/components/threat-severity-badge/index.js +13 -0
  24. package/build/components/threat-severity-badge/test/index.test.d.ts +1 -0
  25. package/build/components/threat-severity-badge/test/index.test.js +9 -0
  26. package/build/components/threats-data-views/constants.d.ts +33 -0
  27. package/build/components/threats-data-views/constants.js +37 -0
  28. package/build/components/threats-data-views/index.d.ts +29 -0
  29. package/build/components/threats-data-views/index.js +412 -0
  30. package/build/components/threats-data-views/test/index.test.d.ts +1 -0
  31. package/build/components/threats-data-views/test/index.test.js +51 -0
  32. package/build/components/threats-data-views/threats-status-toggle-group-control.d.ts +15 -0
  33. package/build/components/threats-data-views/threats-status-toggle-group-control.js +95 -0
  34. package/build/index.d.ts +4 -3
  35. package/build/index.js +4 -3
  36. package/build/types/index.d.ts +3 -3
  37. package/build/types/index.js +3 -3
  38. package/build/types/status.d.ts +1 -1
  39. package/build/types/threats.d.ts +1 -1
  40. package/build/utils/index.d.ts +2 -2
  41. package/build/utils/index.js +7 -9
  42. package/package.json +23 -18
  43. package/src/components/index.js +4 -0
  44. package/src/components/threat-fixer-button/index.tsx +101 -0
  45. package/src/components/threat-fixer-button/styles.module.scss +16 -0
  46. package/src/components/threat-modal/fixer-state-notice.tsx +63 -0
  47. package/src/components/threat-modal/index.tsx +109 -0
  48. package/src/components/threat-modal/styles.module.scss +82 -0
  49. package/src/components/threat-modal/threat-actions.tsx +93 -0
  50. package/src/components/threat-modal/threat-fix-confirmation.tsx +54 -0
  51. package/src/components/threat-modal/threat-fix-details.tsx +64 -0
  52. package/src/components/threat-modal/threat-notice.tsx +84 -0
  53. package/src/components/threat-modal/threat-summary.tsx +29 -0
  54. package/src/components/threat-modal/threat-technical-details.tsx +65 -0
  55. package/src/components/threat-severity-badge/index.tsx +24 -0
  56. package/src/components/threat-severity-badge/styles.module.scss +27 -0
  57. package/src/components/threat-severity-badge/test/index.test.jsx +9 -0
  58. package/src/components/threats-data-views/constants.ts +49 -0
  59. package/src/components/threats-data-views/index.tsx +533 -0
  60. package/src/components/threats-data-views/styles.module.scss +40 -0
  61. package/src/components/threats-data-views/test/index.test.jsx +56 -0
  62. package/src/components/threats-data-views/threats-status-toggle-group-control.tsx +158 -0
  63. package/src/index.ts +4 -3
  64. package/src/types/index.ts +3 -3
  65. package/src/types/status.ts +1 -1
  66. package/src/types/threats.ts +1 -1
  67. package/src/utils/index.ts +3 -3
  68. /package/src/{index.test.ts → index.test.js} +0 -0
@@ -0,0 +1,64 @@
1
+ import { ContextualUpgradeTrigger, Text } from '@automattic/jetpack-components';
2
+ import { __, sprintf } from '@wordpress/i18n';
3
+ import React, { useMemo, useContext } from 'react';
4
+ import { getFixerDescription } from '@automattic/jetpack-scan';
5
+ import { ThreatModalContext } from './index.tsx';
6
+ import styles from './styles.module.scss';
7
+
8
+ /**
9
+ * ThreatFixDetails component
10
+ *
11
+ * @return {JSX.Element | null} The rendered fix details or null if no fixable details are available.
12
+ */
13
+ const ThreatFixDetails = (): JSX.Element => {
14
+ const { threat, handleUpgradeClick } = useContext( ThreatModalContext );
15
+
16
+ const title = useMemo( () => {
17
+ if ( threat.status === 'fixed' ) {
18
+ return __( 'How did Jetpack fix it?', 'jetpack-scan' );
19
+ }
20
+ if ( threat.status === 'current' && threat.fixable ) {
21
+ return __( 'How can Jetpack auto-fix this threat?', 'jetpack-scan' );
22
+ }
23
+ return __( 'How to fix it?', 'jetpack-scan' );
24
+ }, [ threat ] );
25
+
26
+ const fix = useMemo( () => {
27
+ // The threat has a fixed version available, but no auto-fix is available.
28
+ // The user needs to update the extension to the fixed version.
29
+ if ( ! threat.fixable && threat.fixedIn ) {
30
+ return sprintf(
31
+ /* translators: Translates to Updates to version. %1$s: Name. %2$s: Fixed version */
32
+ __( 'Update %1$s to version %2$s.', 'jetpack-scan' ),
33
+ threat.extension.name,
34
+ threat.fixedIn
35
+ );
36
+ }
37
+
38
+ // The threat has an auto-fix available.
39
+ return getFixerDescription( threat );
40
+ }, [ threat ] );
41
+
42
+ if ( ! threat.fixable && ! threat.fixedIn ) {
43
+ return null;
44
+ }
45
+
46
+ return (
47
+ <div className={ styles.section }>
48
+ <Text variant="title-small">{ title }</Text>
49
+ <Text>{ fix }</Text>
50
+ { handleUpgradeClick && (
51
+ <ContextualUpgradeTrigger
52
+ description={ __(
53
+ 'Looking for advanced scan results and one-click fixes?',
54
+ 'jetpack-scan'
55
+ ) }
56
+ cta={ __( 'Upgrade Jetpack now', 'jetpack-scan' ) }
57
+ onClick={ handleUpgradeClick }
58
+ />
59
+ ) }
60
+ </div>
61
+ );
62
+ };
63
+
64
+ export default ThreatFixDetails;
@@ -0,0 +1,84 @@
1
+ import { Text, Button } from '@automattic/jetpack-components';
2
+ import { Notice, Spinner } from '@wordpress/components';
3
+ import { __ } from '@wordpress/i18n';
4
+ import { Icon, warning } from '@wordpress/icons';
5
+ import { useContext } from 'react';
6
+ import { ThreatModalContext } from './index.tsx';
7
+ import styles from './styles.module.scss';
8
+
9
+ /**
10
+ * ThreatNotice component
11
+ *
12
+ * @param {object} props - The component props.
13
+ * @param {string} props.status - The status of the notice.
14
+ * @param {string} props.title - The title of the notice.
15
+ * @param {string} props.content - The content of the notice.
16
+ *
17
+ * @return {JSX.Element} The rendered ThreatNotice component.
18
+ */
19
+ const ThreatNotice = ( {
20
+ status = 'warning',
21
+ title,
22
+ content,
23
+ }: {
24
+ status?: 'warning' | 'error' | 'success' | undefined;
25
+ title: string;
26
+ content: string;
27
+ } ): JSX.Element => {
28
+ const {
29
+ userConnectionNeeded,
30
+ userIsConnecting,
31
+ handleConnectUser,
32
+ siteCredentialsNeeded,
33
+ credentialsRedirectUrl,
34
+ credentialsIsFetching,
35
+ } = useContext( ThreatModalContext );
36
+
37
+ return (
38
+ <Notice
39
+ status={ status }
40
+ isDismissible={ false }
41
+ children={
42
+ <div className={ styles.notice }>
43
+ <div className={ styles.notice__title }>
44
+ { status === 'success' ? (
45
+ <Spinner className={ styles.spinner } />
46
+ ) : (
47
+ <Icon icon={ warning } size={ 30 } />
48
+ ) }
49
+ <Text variant="title-small" mb={ 2 }>
50
+ { title }
51
+ </Text>
52
+ </div>
53
+ <Text>{ content }</Text>
54
+ <div className={ styles.notice__actions }>
55
+ { userConnectionNeeded && (
56
+ <Button
57
+ className={ styles.notice__action }
58
+ isExternalLink={ true }
59
+ weight="regular"
60
+ isLoading={ userIsConnecting }
61
+ onClick={ handleConnectUser }
62
+ >
63
+ { __( 'Connect your user account', 'jetpack-scan' ) }
64
+ </Button>
65
+ ) }
66
+ { siteCredentialsNeeded && (
67
+ <Button
68
+ className={ styles.notice__action }
69
+ isExternalLink={ true }
70
+ weight="regular"
71
+ href={ credentialsRedirectUrl }
72
+ isLoading={ credentialsIsFetching }
73
+ >
74
+ { __( 'Enter server credentials', 'jetpack-scan' ) }
75
+ </Button>
76
+ ) }
77
+ </div>
78
+ </div>
79
+ }
80
+ />
81
+ );
82
+ };
83
+
84
+ export default ThreatNotice;
@@ -0,0 +1,29 @@
1
+ import { Button, Text } from '@automattic/jetpack-components';
2
+ import { __ } from '@wordpress/i18n';
3
+ import { useContext } from 'react';
4
+ import { ThreatModalContext } from './index.tsx';
5
+ import styles from './styles.module.scss';
6
+
7
+ /**
8
+ * ThreatSummary component
9
+ *
10
+ * @return {JSX.Element} The rendered threat summary.
11
+ */
12
+ const ThreatSummary = (): JSX.Element => {
13
+ const { threat } = useContext( ThreatModalContext );
14
+
15
+ return (
16
+ <div className={ styles.section }>
17
+ { !! threat.description && <Text>{ threat.description }</Text> }
18
+ { !! threat.source && (
19
+ <div>
20
+ <Button variant="link" isExternalLink={ true } weight="regular" href={ threat.source }>
21
+ { __( 'See more technical details of this threat', 'jetpack-scan' ) }
22
+ </Button>
23
+ </div>
24
+ ) }
25
+ </div>
26
+ );
27
+ };
28
+
29
+ export default ThreatSummary;
@@ -0,0 +1,65 @@
1
+ import { Text, Button, DiffViewer, MarkedLines } from '@automattic/jetpack-components';
2
+ import { __ } from '@wordpress/i18n';
3
+ import { chevronDown, chevronUp, Icon } from '@wordpress/icons';
4
+ import { useState, useCallback, useContext } from 'react';
5
+ import { ThreatModalContext } from './index.tsx';
6
+ import styles from './styles.module.scss';
7
+
8
+ /**
9
+ * ThreatTechnicalDetails component
10
+ *
11
+ * @return {JSX.Element | null} The rendered technical details or null if no details are available.
12
+ */
13
+ const ThreatTechnicalDetails = (): JSX.Element => {
14
+ const { threat } = useContext( ThreatModalContext );
15
+
16
+ const [ open, setOpen ] = useState( false );
17
+
18
+ const toggleOpen = useCallback( () => {
19
+ setOpen( ! open );
20
+ }, [ open ] );
21
+
22
+ if ( ! threat.filename && ! threat.context && ! threat.diff ) {
23
+ return null;
24
+ }
25
+
26
+ return (
27
+ <div className={ styles.section }>
28
+ <div className={ styles.section__title }>
29
+ <Button
30
+ variant="link"
31
+ className={ styles.section__toggle }
32
+ aria-expanded={ open }
33
+ aria-controls={ `threat-details-${ threat.id }` }
34
+ onClick={ toggleOpen }
35
+ >
36
+ <div className={ styles.section__toggle__content }>
37
+ <Text variant="title-small" mb={ 0 }>
38
+ { open
39
+ ? __( 'Hide the technical details', 'jetpack-scan' )
40
+ : __( 'Show the technical details', 'jetpack-scan' ) }
41
+ </Text>
42
+ <Icon icon={ open ? chevronUp : chevronDown } size={ 24 } />
43
+ </div>
44
+ </Button>
45
+ </div>
46
+ { open && (
47
+ <div
48
+ className={ open ? styles.section__open : styles.section__closed }
49
+ id={ `threat-details-${ threat.id }` }
50
+ >
51
+ { threat.filename && (
52
+ <>
53
+ <Text>{ __( 'Threat found in file:', 'jetpack-scan' ) }</Text>
54
+ <pre className={ styles.filename }>{ threat.filename }</pre>
55
+ </>
56
+ ) }
57
+ { threat.context && <MarkedLines context={ threat.context } /> }
58
+ { threat.diff && <DiffViewer diff={ threat.diff } /> }
59
+ </div>
60
+ ) }
61
+ </div>
62
+ );
63
+ };
64
+
65
+ export default ThreatTechnicalDetails;
@@ -0,0 +1,24 @@
1
+ import { Badge } from '@automattic/jetpack-components';
2
+ import { _x } from '@wordpress/i18n';
3
+
4
+ const ThreatSeverityBadge = ( { severity } ) => {
5
+ if ( severity >= 5 ) {
6
+ return (
7
+ <Badge variant="danger">
8
+ { _x( 'Critical', 'Severity label for issues rated 5 or higher.', 'jetpack-scan' ) }
9
+ </Badge>
10
+ );
11
+ }
12
+
13
+ if ( severity >= 3 && severity < 5 ) {
14
+ return (
15
+ <Badge variant="warning">
16
+ { _x( 'High', 'Severity label for issues rated between 3 and 5.', 'jetpack-scan' ) }
17
+ </Badge>
18
+ );
19
+ }
20
+
21
+ return <Badge>{ _x( 'Low', 'Severity label for issues rated below 3.', 'jetpack-scan' ) }</Badge>;
22
+ };
23
+
24
+ export default ThreatSeverityBadge;
@@ -0,0 +1,27 @@
1
+ .threat-severity-badge {
2
+ border-radius: 32px;
3
+ flex-shrink: 0;
4
+ font-size: 12px;
5
+ font-style: normal;
6
+ font-weight: 600;
7
+ line-height: 16px;
8
+ padding: calc( var( --spacing-base ) / 2 ); // 4px
9
+ position: relative;
10
+ text-align: center;
11
+ width: 60px;
12
+ }
13
+
14
+ .is-critical {
15
+ background: var( --jp-red-5 );
16
+ color: var( --jp-red-60 );
17
+ }
18
+
19
+ .is-high {
20
+ background: var( --jp-yellow-5 );
21
+ color: var( --jp-yellow-60 );
22
+ }
23
+
24
+ .is-low {
25
+ background: var( --jp-gray-0 );
26
+ color: var( --jp-gray-50 );
27
+ }
@@ -0,0 +1,9 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import ThreatSeverityBadge from '../index.tsx';
3
+
4
+ describe( 'ThreatSeverityBadge', () => {
5
+ it( 'renders the correct severity label', () => {
6
+ render( <ThreatSeverityBadge severity={ 4 } /> );
7
+ expect( screen.getByText( 'High' ) ).toBeInTheDocument();
8
+ } );
9
+ } );
@@ -0,0 +1,49 @@
1
+ import { __ } from '@wordpress/i18n';
2
+ import {
3
+ code as fileIcon,
4
+ color as themeIcon,
5
+ plugins as pluginIcon,
6
+ shield as shieldIcon,
7
+ wordpress as coreIcon,
8
+ } from '@wordpress/icons';
9
+
10
+ export const THREAT_STATUSES: { value: string; label: string; variant?: 'success' | 'warning' }[] =
11
+ [
12
+ { value: 'current', label: __( 'Active', 'jetpack-scan' ), variant: 'warning' },
13
+ { value: 'fixed', label: __( 'Fixed', 'jetpack-scan' ), variant: 'success' },
14
+ { value: 'ignored', label: __( 'Ignored', 'jetpack-scan' ) },
15
+ ];
16
+
17
+ export const THREAT_TYPES = [
18
+ { value: 'plugins', label: __( 'Plugin', 'jetpack-scan' ) },
19
+ { value: 'themes', label: __( 'Theme', 'jetpack-scan' ) },
20
+ { value: 'core', label: __( 'WordPress', 'jetpack-scan' ) },
21
+ { value: 'file', label: __( 'File', 'jetpack-scan' ) },
22
+ ];
23
+
24
+ export const THREAT_ICONS = {
25
+ plugins: pluginIcon,
26
+ themes: themeIcon,
27
+ core: coreIcon,
28
+ file: fileIcon,
29
+ default: shieldIcon,
30
+ };
31
+
32
+ export const THREAT_FIELD_THREAT = 'threat';
33
+ export const THREAT_FIELD_TITLE = 'title';
34
+ export const THREAT_FIELD_DESCRIPTION = 'description';
35
+ export const THREAT_FIELD_ICON = 'icon';
36
+ export const THREAT_FIELD_STATUS = 'status';
37
+ export const THREAT_FIELD_TYPE = 'type';
38
+ export const THREAT_FIELD_EXTENSION = 'extension';
39
+ export const THREAT_FIELD_PLUGIN = 'plugin';
40
+ export const THREAT_FIELD_THEME = 'theme';
41
+ export const THREAT_FIELD_SEVERITY = 'severity';
42
+ export const THREAT_FIELD_SIGNATURE = 'signature';
43
+ export const THREAT_FIELD_FIRST_DETECTED = 'first-detected';
44
+ export const THREAT_FIELD_FIXED_ON = 'fixed-on';
45
+ export const THREAT_FIELD_AUTO_FIX = 'auto-fix';
46
+
47
+ export const THREAT_ACTION_FIX = 'fix';
48
+ export const THREAT_ACTION_IGNORE = 'ignore';
49
+ export const THREAT_ACTION_UNIGNORE = 'unignore';