-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f13628c
commit 6114be1
Showing
21 changed files
with
738 additions
and
558 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import { Button } from '@automattic/components'; | ||
import { ToggleControl } from '@wordpress/components'; | ||
import { translate } from 'i18n-calypso'; | ||
import { includes, some } from 'lodash'; | ||
import React, { useCallback, useEffect, useMemo, useState } from 'react'; | ||
import FormFieldset from 'calypso/components/forms/form-fieldset'; | ||
import FormSettingExplanation from 'calypso/components/forms/form-setting-explanation'; | ||
import FormTextarea from 'calypso/components/forms/form-textarea'; | ||
import { useWafMutation, useWafQuery } from './data'; | ||
|
||
export default function AllowList() { | ||
const { data: waf, isLoading } = useWafQuery(); | ||
const { mutate: updateWaf, isPending: isUpdating } = useWafMutation(); | ||
|
||
const [ inputState, setInputState ] = useState( '' ); | ||
|
||
const toggleIpAllowList = useCallback( () => { | ||
updateWaf( { | ||
jetpack_waf_ip_allow_list_enabled: ! waf?.jetpack_waf_ip_allow_list_enabled, | ||
} ); | ||
}, [ updateWaf, waf?.jetpack_waf_ip_allow_list_enabled ] ); | ||
|
||
const saveIpAllowList = useCallback( () => { | ||
updateWaf( { jetpack_waf_ip_allow_list: inputState } ); | ||
}, [ inputState, updateWaf ] ); | ||
|
||
const togglingAllowListSupported = useMemo( | ||
() => waf?.jetpack_waf_ip_allow_list_enabled !== undefined, | ||
[ waf?.jetpack_waf_ip_allow_list_enabled ] | ||
); | ||
|
||
const showAllowList = useMemo( | ||
() => ! togglingAllowListSupported || waf?.jetpack_waf_ip_allow_list_enabled, | ||
[ waf?.jetpack_waf_ip_allow_list_enabled, togglingAllowListSupported ] | ||
); | ||
|
||
const ipAddress = useMemo( () => { | ||
if ( window.app && window.app.clientIp ) { | ||
return window.app.clientIp; | ||
} | ||
|
||
return null; | ||
}, [] ); | ||
|
||
const isIpAllowed = useMemo( () => { | ||
if ( ! ipAddress ) { | ||
return false; | ||
} | ||
|
||
const allowedIps = inputState.split( '\n' ); | ||
|
||
return ( | ||
includes( allowedIps, ipAddress ) || | ||
some( allowedIps, ( entry ) => { | ||
if ( entry.indexOf( '-' ) < 0 ) { | ||
return false; | ||
} | ||
|
||
const range = entry.split( '-' ).map( ( ip ) => ip.trim() ); | ||
return includes( range, ipAddress ); | ||
} ) | ||
); | ||
}, [ ipAddress, inputState ] ); | ||
|
||
const addCurrentIpToAllowList = useCallback( () => { | ||
let allowedIps = inputState.trimEnd(); | ||
|
||
if ( allowedIps.length ) { | ||
allowedIps += '\n'; | ||
} | ||
|
||
setInputState( allowedIps + ipAddress ); | ||
}, [ ipAddress, inputState ] ); | ||
|
||
useEffect( () => { | ||
if ( waf?.jetpack_waf_ip_allow_list ) { | ||
setInputState( waf.jetpack_waf_ip_allow_list ); | ||
} | ||
}, [ waf?.jetpack_waf_ip_allow_list ] ); | ||
|
||
if ( ! waf ) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<FormFieldset> | ||
<ToggleControl | ||
disabled={ isLoading || isUpdating || ! togglingAllowListSupported } | ||
onChange={ toggleIpAllowList } | ||
checked={ ! togglingAllowListSupported || !! waf?.jetpack_waf_ip_allow_list_enabled } | ||
label={ | ||
<> | ||
<div>{ translate( 'Trusted IP addresses' ) }</div> | ||
<FormSettingExplanation> | ||
{ translate( | ||
'IP addresses added to this list are always allowed to access your site, regardless of any other Jetpack security settings.' | ||
) } | ||
</FormSettingExplanation> | ||
{ showAllowList && ( | ||
<> | ||
<FormTextarea | ||
id="jetpack_waf_ip_allow_list" | ||
value={ inputState } | ||
onChange={ ( e ) => setInputState( e.target.value ) } | ||
disabled={ isLoading || isUpdating } | ||
placeholder={ translate( 'Example: 12.12.12.1-12.12.12.100' ) } | ||
/> | ||
<FormSettingExplanation> | ||
{ translate( | ||
'IPv4 and IPv6 supported. Separate IPs with commas, spaces, or new lines. To specify a range, use CIDR notation (i.e. 12.12.12.0/24) or enter the low value and high value separated by a dash (i.e. 12.12.12.0–12.12.12.255).' | ||
) } | ||
</FormSettingExplanation> | ||
<div className="allow-list-controls"> | ||
<div className="current-ip"> | ||
<div> | ||
{ translate( 'Your current IP: {{strong}}%(IP)s{{/strong}}', { | ||
args: { | ||
IP: ipAddress || translate( 'Unknown IP address' ), | ||
}, | ||
components: { | ||
strong: <strong />, | ||
}, | ||
} ) } | ||
</div> | ||
|
||
{ ipAddress && ( | ||
<div> | ||
<Button | ||
className="site-settings__add-to-explicitly-allowed-list" | ||
onClick={ addCurrentIpToAllowList } | ||
disabled={ isLoading || isUpdating || isIpAllowed } | ||
compact | ||
> | ||
{ isIpAllowed | ||
? translate( 'Already in list of trusted IPs' ) | ||
: translate( 'Add to Trusted IPs' ) } | ||
</Button> | ||
</div> | ||
) } | ||
</div> | ||
<div> | ||
<Button | ||
onClick={ saveIpAllowList } | ||
disabled={ isLoading || isUpdating } | ||
primary | ||
> | ||
{ translate( 'Save allow list' ) } | ||
</Button> | ||
</div> | ||
</div> | ||
</> | ||
) } | ||
</> | ||
} | ||
/> | ||
</FormFieldset> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { PRODUCT_JETPACK_SCAN, WPCOM_FEATURES_SCAN } from '@automattic/calypso-products'; | ||
import { ToggleControl } from '@wordpress/components'; | ||
import { translate } from 'i18n-calypso'; | ||
import moment from 'moment'; | ||
import React, { useCallback, useMemo } from 'react'; | ||
import UpsellNudge from 'calypso/blocks/upsell-nudge'; | ||
import FormFieldset from 'calypso/components/forms/form-fieldset'; | ||
import FormSettingExplanation from 'calypso/components/forms/form-setting-explanation'; | ||
import { useSelector } from 'calypso/state'; | ||
import { getSelectedSiteSlug } from 'calypso/state/ui/selectors'; | ||
import { useWafMutation, useWafQuery } from './data'; | ||
|
||
/** | ||
* Automatic Firewall Rules Setting | ||
*/ | ||
export default function AutomaticRules() { | ||
const { data: waf, isLoading } = useWafQuery(); | ||
const { mutate: updateWaf, isPending: isUpdating } = useWafMutation(); | ||
|
||
const selectedSiteSlug = useSelector( getSelectedSiteSlug ); | ||
|
||
const toggleAutomaticRules = useCallback( () => { | ||
updateWaf( { | ||
jetpack_waf_automatic_rules: ! waf?.jetpack_waf_automatic_rules, | ||
} ); | ||
}, [ updateWaf, waf?.jetpack_waf_automatic_rules ] ); | ||
|
||
const automaticRulesLastUpdated = useMemo( () => { | ||
const timestamp = parseInt( waf?.automatic_rules_last_updated ); | ||
if ( timestamp ) { | ||
return moment( timestamp * 1000 ).format( 'MMMM D, YYYY h:mm A' ); | ||
} | ||
return ''; | ||
}, [ waf?.automatic_rules_last_updated ] ); | ||
|
||
// Do not render if the WAF is not supported. | ||
if ( ! waf || ! waf?.waf_supported ) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<> | ||
<FormFieldset> | ||
<ToggleControl | ||
disabled={ isLoading || isUpdating || ! waf?.automatic_rules_available } | ||
onChange={ toggleAutomaticRules } | ||
checked={ !! waf?.jetpack_waf_automatic_rules } | ||
label={ | ||
<> | ||
<div>{ translate( 'Automatic firewall protection' ) }</div> | ||
{ automaticRulesLastUpdated && ( | ||
<FormSettingExplanation> | ||
{ translate( 'Automatic security rules installed. Last updated on %(date)s.', { | ||
args: { | ||
date: automaticRulesLastUpdated, | ||
}, | ||
} ) } | ||
</FormSettingExplanation> | ||
) } | ||
<FormSettingExplanation> | ||
{ translate( | ||
'Block untrusted traffic by scanning every request made to your site. Jetpack’s security rules are always up-to-date to protect against the latest threats.' | ||
) } | ||
</FormSettingExplanation> | ||
<UpsellNudge | ||
className="site-settings__security-settings-firewall-nudge" | ||
title={ | ||
waf?.automatic_rules_available | ||
? translate( | ||
'Your site is not receiving the latest updates to automatic rules' | ||
) | ||
: translate( 'Set up automatic rules with one click' ) | ||
} | ||
description={ | ||
waf?.automatic_rules_available | ||
? translate( 'Upgrade to keep your site secure with up-to-date firewall rules' ) | ||
: translate( 'Upgrade to enable automatic firewall protection.' ) | ||
} | ||
callToAction={ translate( 'Upgrade now' ) } | ||
primaryButton | ||
event="calypso_scan_settings_upgrade_nudge" | ||
feature={ WPCOM_FEATURES_SCAN } | ||
href={ `/checkout/${ selectedSiteSlug }/${ PRODUCT_JETPACK_SCAN }?redirect_to=/scan/firewall/${ selectedSiteSlug }` } | ||
/> | ||
</> | ||
} | ||
/> | ||
</FormFieldset> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { Button } from '@automattic/components'; | ||
import { ToggleControl } from '@wordpress/components'; | ||
import { translate } from 'i18n-calypso'; | ||
import React, { useCallback, useEffect, useState } from 'react'; | ||
import FormFieldset from 'calypso/components/forms/form-fieldset'; | ||
import FormSettingExplanation from 'calypso/components/forms/form-setting-explanation'; | ||
import FormTextarea from 'calypso/components/forms/form-textarea'; | ||
import { useWafMutation, useWafQuery } from './data'; | ||
|
||
/** | ||
* Blocked IP List Setting | ||
*/ | ||
export default function BlockList() { | ||
const { data: waf, isLoading } = useWafQuery(); | ||
const { mutate: updateWaf, isPending: isUpdating } = useWafMutation(); | ||
|
||
const [ inputState, setInputState ] = useState( '' ); | ||
|
||
const toggleIpBlockList = useCallback( () => { | ||
updateWaf( { | ||
jetpack_waf_ip_block_list_enabled: ! waf?.jetpack_waf_ip_block_list_enabled, | ||
} ); | ||
}, [ updateWaf, waf?.jetpack_waf_ip_block_list_enabled ] ); | ||
|
||
const saveIpBlockList = useCallback( () => { | ||
updateWaf( { jetpack_waf_ip_block_list: inputState } ); | ||
}, [ inputState, updateWaf ] ); | ||
|
||
useEffect( () => { | ||
if ( waf?.jetpack_waf_ip_block_list ) { | ||
setInputState( waf.jetpack_waf_ip_block_list ); | ||
} | ||
}, [ waf?.jetpack_waf_ip_block_list ] ); | ||
|
||
// Do not render if the WAF is not supported. | ||
if ( ! waf || ! waf?.waf_supported ) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<FormFieldset> | ||
<ToggleControl | ||
disabled={ isLoading || isUpdating } | ||
onChange={ toggleIpBlockList } | ||
checked={ !! waf.jetpack_waf_ip_block_list_enabled } | ||
label={ | ||
<> | ||
<div>{ translate( 'Block IP addresses' ) }</div> | ||
<FormSettingExplanation> | ||
{ translate( | ||
'Stop specific visitors from accessing your site by their IP address.' | ||
) } | ||
</FormSettingExplanation> | ||
{ waf?.jetpack_waf_ip_block_list_enabled && ( | ||
<> | ||
<FormTextarea | ||
id="jetpack_waf_ip_block_list" | ||
value={ inputState } | ||
onChange={ ( e: React.ChangeEvent< HTMLInputElement > ) => | ||
setInputState( e.target.value ) | ||
} | ||
disabled={ isLoading || isUpdating || ! waf?.jetpack_waf_ip_block_list_enabled } | ||
placeholder={ translate( 'Example: 12.12.12.1-12.12.12.100' ) } | ||
/> | ||
<FormSettingExplanation> | ||
{ translate( | ||
'IPv4 and IPv6 supported. Separate IPs with commas, spaces, or new lines. To specify a range, use CIDR notation (i.e. 12.12.12.0/24) or enter the low value and high value separated by a dash (i.e. 12.12.12.0–12.12.12.255).' | ||
) } | ||
</FormSettingExplanation> | ||
<div className="block-list-controls"> | ||
<div> | ||
<Button | ||
onClick={ saveIpBlockList } | ||
disabled={ isLoading || isUpdating } | ||
primary | ||
> | ||
{ translate( 'Save block list' ) } | ||
</Button> | ||
</div> | ||
</div> | ||
</> | ||
) } | ||
</> | ||
} | ||
/> | ||
</FormFieldset> | ||
); | ||
} |
Oops, something went wrong.