Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Cloudflare warning #11350

Merged
merged 2 commits into from
Nov 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 2 additions & 153 deletions lib/compat.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,19 +134,15 @@ function gutenberg_check_if_classic_needs_warning_about_blocks() {
return;
}

if ( ! has_blocks( $post ) && ! isset( $_REQUEST['cloudflare-error'] ) ) {
if ( ! has_blocks( $post ) ) {
return;
}

// Enqueue the JS we're going to need in the dialog.
wp_enqueue_script( 'wp-a11y' );
wp_enqueue_script( 'wp-sanitize' );

if ( isset( $_REQUEST['cloudflare-error'] ) ) {
add_action( 'admin_footer', 'gutenberg_warn_classic_about_cloudflare' );
} else {
add_action( 'admin_footer', 'gutenberg_warn_classic_about_blocks' );
}
add_action( 'admin_footer', 'gutenberg_warn_classic_about_blocks' );
}
add_action( 'admin_enqueue_scripts', 'gutenberg_check_if_classic_needs_warning_about_blocks' );

Expand Down Expand Up @@ -308,150 +304,3 @@ function gutenberg_warn_classic_about_blocks() {
</script>
<?php
}

/**
* Adds a warning to the Classic Editor when CloudFlare is blocking REST API requests.
*
* @since 3.4.0
*/
function gutenberg_warn_classic_about_cloudflare() {
?>
<style type="text/css">
#cloudflare-block-dialog .notification-dialog {
position: fixed;
top: 50%;
left: 50%;
width: 500px;
box-sizing: border-box;
transform: translate(-50%, -50%);
margin: 0;
padding: 25px;
max-height: 90%;
background: #fff;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
line-height: 1.5;
z-index: 1000005;
overflow-y: auto;
}

#cloudflare-block-dialog ul {
list-style: initial;
padding-left: 20px;
}

@media only screen and (max-height: 480px), screen and (max-width: 450px) {
#cloudflare-block-dialog .notification-dialog {
top: 0;
left: 0;
width: 100%;
height: 100%;
transform: none;
max-height: 100%;
}
}
</style>

<div id="cloudflare-block-dialog" class="notification-dialog-wrap">
<div class="notification-dialog-background"></div>
<div class="notification-dialog">
<div class="cloudflare-block-message">
<h2><?php _e( 'Cloudflare is blocking REST API requests', 'gutenberg' ); ?></h2>
<p><?php _e( 'Your site uses Cloudflare, which provides a Web Application Firewall (WAF) to secure your site against attacks. Unfortunately, some of these WAF rules are incorrectly blocking legitimate access to your site, preventing Gutenberg from functioning correctly.', 'gutenberg' ); ?></p>
<p><?php _e( "We're working closely with Cloudflare to fix this issue, but in the mean time, you can work around it in one of two ways:", 'gutenberg' ); ?></p>
<ul>
<li><?php _e( 'If you have a Cloudflare Pro account, log in to Cloudflare, visit the Firewall settings page, open the "Cloudflare Rule Set" details, open the "Cloudflare WordPress" ruleset, then set the rules "WP0025A" and "WP0025B" to "Disable".', 'gutenberg' ); ?></li>
<li>
<?php
printf(
/* translators: %s: link to a comment in the Gutenberg repository */
__( 'For free Cloudflare accounts, you can <a href="%s">change the REST API URL</a>, to avoid triggering the WAF rules. Please be aware that this may cause issues with other plugins that use the REST API, and removes any other protection Cloudflare may be offering for the REST API.', 'gutenberg' ),
'https://github.com/WordPress/gutenberg/issues/2704#issuecomment-410582252'
);
?>
</li>
</ul>
<p>
<?php
printf(
/* translators: %s link to an issue in the Gutenberg repository */
__( 'If neither of these options are possible for you, please <a href="%s">follow this issue for updates</a>. We hope to have this issue rectified soon!', 'gutenberg' ),
'https://github.com/WordPress/gutenberg/issues/2704'
);
?>
</p>
</div>
<p>
<button type="button" class="button button-primary cloudflare-block-classic-button"><?php _e( 'Continue to Classic Editor', 'gutenberg' ); ?></button>
</p>
</div>
</div>

<script type="text/javascript">
/* <![CDATA[ */
( function( $ ) {
var dialog = {};

dialog.init = function() {
// The modal
dialog.warning = $( '#cloudflare-block-dialog' );
// Get the links and buttons within the modal.
dialog.warningTabbables = dialog.warning.find( 'a, button' );

// Get the text within the modal.
dialog.rawMessage = dialog.warning.find( '.cloudflare-block-message' ).text();

// Hide all the #wpwrap content from assistive technologies.
$( '#wpwrap' ).attr( 'aria-hidden', 'true' );

// Detach the warning modal from its position and append it to the body.
$( document.body )
.addClass( 'modal-open' )
.append( dialog.warning.detach() );

// Reveal the modal and set focus on the Gutenberg button.
dialog.warning
.removeClass( 'hidden' )
.find( '.cloudflare-block-classic-button' ).focus();

// Attach event handlers.
dialog.warningTabbables.on( 'keydown', dialog.constrainTabbing );
dialog.warning.on( 'click', '.cloudflare-block-classic-button', dialog.dismissWarning );

// Make screen readers announce the warning message after a short delay (necessary for some screen readers).
setTimeout( function() {
wp.a11y.speak( wp.sanitize.stripTags( dialog.rawMessage.replace( /\s+/g, ' ' ) ), 'assertive' );
}, 1000 );
};

dialog.constrainTabbing = function( event ) {
var firstTabbable, lastTabbable;

if ( 9 !== event.which ) {
return;
}

firstTabbable = dialog.warningTabbables.first()[0];
lastTabbable = dialog.warningTabbables.last()[0];

if ( lastTabbable === event.target && ! event.shiftKey ) {
firstTabbable.focus();
event.preventDefault();
} else if ( firstTabbable === event.target && event.shiftKey ) {
lastTabbable.focus();
event.preventDefault();
}
};

dialog.dismissWarning = function() {
// Hide modal.
dialog.warning.remove();
$( '#wpwrap' ).removeAttr( 'aria-hidden' );
$( 'body' ).removeClass( 'modal-open' );
};

$( document ).ready( dialog.init );
} )( jQuery );
/* ]]> */
</script>
<?php
}
2 changes: 2 additions & 0 deletions packages/api-fetch/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## 2.2.2 (Unreleased)

## 2.2.1 (2018-10-30)

## 2.2.0 (2018-10-29)
Expand Down
22 changes: 1 addition & 21 deletions packages/api-fetch/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@ function registerMiddleware( middleware ) {
middlewares.push( middleware );
}

function checkCloudflareError( error ) {
if ( typeof error === 'string' && error.indexOf( 'Cloudflare Ray ID' ) >= 0 ) {
throw {
code: 'cloudflare_error',
};
}
}

function apiFetch( options ) {
const raw = ( nextOptions ) => {
const { url, path, body, data, parse = true, ...remainingOptions } = nextOptions;
Expand Down Expand Up @@ -82,18 +74,8 @@ function apiFetch( options ) {
throw invalidJsonError;
}

/*
* Response data is a stream, which will be consumed by the .json() call.
* If we need to re-use this data to send to the Cloudflare error handler,
* we need a clone of the original response, so the stream can be consumed
* in the .text() call, instead.
*/
const responseClone = response.clone();

return response.json()
.catch( async () => {
const text = await responseClone.text();
checkCloudflareError( text );
.catch( () => {
throw invalidJsonError;
} )
.then( ( error ) => {
Expand All @@ -102,8 +84,6 @@ function apiFetch( options ) {
message: __( 'An unknown error occurred.' ),
};

checkCloudflareError( error );

throw error || unknownError;
} );
} );
Expand Down
3 changes: 0 additions & 3 deletions packages/api-fetch/src/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ describe( 'apiFetch', () => {
message: 'Bad Request',
} );
},
clone() {
return null;
},
} ) );

return apiFetch( { path: '/random' } ).catch( ( body ) => {
Expand Down
2 changes: 2 additions & 0 deletions packages/editor/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## 6.1.1 (Unreleased)

## 6.1.0 (2018-10-30)

### Deprecations
Expand Down
20 changes: 0 additions & 20 deletions packages/editor/src/store/effects/posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { pick, includes } from 'lodash';
*/
import apiFetch from '@wordpress/api-fetch';
import { __ } from '@wordpress/i18n';
import { addQueryArgs } from '@wordpress/url';
// TODO: Ideally this would be the only dispatch in scope. This requires either
// refactoring editor actions to yielded controls, or replacing direct dispatch
// on the editor store with action creators (e.g. `REQUEST_POST_UPDATE_START`).
Expand Down Expand Up @@ -266,25 +265,6 @@ export const requestPostUpdateFailure = ( action ) => {
dataDispatch( 'core/notices' ).createErrorNotice( noticeMessage, {
id: SAVE_POST_NOTICE_ID,
} );

if ( error && 'cloudflare_error' === error.code ) {
dataDispatch( 'core/notices' ).createErrorNotice(
__( 'Cloudflare is blocking REST API requests.' ),
{
actions: [
{
label: __( 'Learn More' ),
url: addQueryArgs( 'post.php', {
post: post.id,
action: 'edit',
'classic-editor': '',
'cloudflare-error': '',
} ),
},
],
},
);
}
};

/**
Expand Down