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

Add dedicated reset tool #3095

Merged
merged 8 commits into from
Apr 6, 2021
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
67 changes: 67 additions & 0 deletions includes/Core/Admin/Available_Tools.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/**
* Class Google\Site_Kit\Core\Admin\Available_Tools
*
* @package Google\Site_Kit\Core\Admin
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/

namespace Google\Site_Kit\Core\Admin;

use Google\Site_Kit\Core\Permissions\Permissions;
use Google\Site_Kit\Core\Util\Method_Proxy_Trait;
use Google\Site_Kit\Core\Util\Reset;

/**
* Class for extending available tools for Site Kit.
*
* @since n.e.x.t
* @access private
* @ignore
*/
class Available_Tools {
use Method_Proxy_Trait;

/**
* Registers functionality through WordPress hooks.
*
* @since n.e.x.t
*/
public function register() {
add_action( 'tool_box', $this->get_method_proxy( 'render_tool_box' ) );
}

/**
* Renders tool box output.
*
* @since n.e.x.t
*/
private function render_tool_box() {
if ( ! current_user_can( Permissions::SETUP ) ) {
return;
}
?>
<div class="card">
<h2 class="title"><?php esc_html_e( 'Reset Site Kit', 'google-site-kit' ); ?></h2>
<p>
<?php
esc_html_e(
'Resetting will disconnect all users and remove all Site Kit settings and data within WordPress. You and any other users who wish to use Site Kit will need to reconnect to restore access.',
'google-site-kit'
)
?>
</p>
<p>
<a
class="button button-primary"
href="<?php echo esc_url( Reset::url() ); ?>"
>
<?php esc_html_e( 'Reset Site Kit', 'google-site-kit' ); ?>
</a>
</p>
</div>
<?php
}
}
62 changes: 62 additions & 0 deletions includes/Core/Util/Reset.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ class Reset {
*/
const REST_ROUTE = 'core/site/data/reset';

/**
* Action for triggering a reset.
*/
const ACTION = 'googlesitekit_reset';

/**
* Plugin context.
*
Expand All @@ -45,6 +50,23 @@ class Reset {
*/
private $context;

/**
* Gets the URL to handle a reset action.
*
* @since n.e.x.t
*
* @return string
*/
public static function url() {
return add_query_arg(
array(
'action' => static::ACTION,
'nonce' => wp_create_nonce( static::ACTION ),
),
admin_url( 'index.php' )
);
}

/**
* Constructor.
*
Expand All @@ -69,6 +91,15 @@ function( $routes ) {
return array_merge( $routes, $this->get_rest_routes() );
}
);

add_action(
'admin_action_' . static::ACTION,
function () {
$this->handle_reset_action(
$this->context->input()->filter( INPUT_GET, 'nonce' )
);
}
);
}

/**
Expand Down Expand Up @@ -178,4 +209,35 @@ private function get_rest_routes() {
),
);
}

/**
* Handles the reset admin action.
*
* @since n.e.x.t
*
* @param string $nonce WP nonce for action.
*/
private function handle_reset_action( $nonce ) {
if ( ! wp_verify_nonce( $nonce, static::ACTION ) ) {
wp_die( esc_html__( 'Invalid nonce.', 'google-site-kit' ), 400 );
eugene-manuilov marked this conversation as resolved.
Show resolved Hide resolved
}
if ( ! current_user_can( Permissions::SETUP ) ) {
wp_die( esc_html__( 'You don\'t have permissions to set up Site Kit.', 'google-site-kit' ), 403 );
}

$this->all();

wp_safe_redirect(
$this->context->admin_url(
'splash',
array(
// Trigger client-side storage reset.
'googlesitekit_reset_session' => 1,
// Show reset-success notification.
'notification' => 'reset_success',
)
)
);
exit;
}
}
1 change: 1 addition & 0 deletions includes/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ function() use ( $options, $activation_flag ) {
( new Core\Util\Tracking( $this->context, $user_options, $screens ) )->register();
( new Core\REST_API\REST_Routes( $this->context, $authentication, $modules ) )->register();
( new Core\Admin_Bar\Admin_Bar( $this->context, $assets, $modules ) )->register();
( new Core\Admin\Available_Tools() )->register();
( new Core\Admin\Notices() )->register();
( new Core\Admin\Dashboard( $this->context, $assets, $modules ) )->register();
( new Core\Notifications\Notifications( $this->context, $options, $authentication ) )->register();
Expand Down
29 changes: 29 additions & 0 deletions tests/phpunit/integration/Core/Admin/Available_ToolsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/**
* Class Google\Site_Kit\Tests\Core\Admin\Available_ToolsTest
*
* @package Google\Site_Kit\Tests\Core\Admin
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/

namespace Google\Site_Kit\Tests\Core\Admin;

use Google\Site_Kit\Core\Admin\Available_Tools;
use PHPUnit\Framework\TestCase;

/**
* @group Admin
*/
class Available_ToolsTest extends TestCase {

public function test_register() {
$tools = new Available_Tools();
remove_all_actions( 'tool_box' );

$tools->register();

$this->assertTrue( has_action( 'tool_box' ) );
}
}
78 changes: 78 additions & 0 deletions tests/phpunit/integration/Core/Util/ResetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,39 @@
namespace Google\Site_Kit\Tests\Core\Util;

use Google\Site_Kit\Context;
use Google\Site_Kit\Core\Permissions\Permissions;
use Google\Site_Kit\Core\Util\Reset;
use Google\Site_Kit\Tests\Exception\RedirectException;
use Google\Site_Kit\Tests\MutableInput;
use Google\Site_Kit\Tests\TestCase;
use Google\Site_Kit\Tests\OptionsTestTrait;
use Google\Site_Kit\Tests\UserOptionsTestTrait;
use Google\Site_Kit\Tests\TransientsTestTrait;
use WPDieException;

/**
* @group Util
*/
class ResetTest extends TestCase {
use OptionsTestTrait, UserOptionsTestTrait, TransientsTestTrait;

const TEST_OPTION = 'googlesitekit_test_option';

/**
* @var Context
*/
protected $context_with_mutable_input;

public function setUp() {
parent::setUp();

// Set up a test option as a way to check if reset ran or not.
// When the reset runs, this option will no longer exist.
update_option( self::TEST_OPTION, 'test-value' );

$this->context_with_mutable_input = new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE, new MutableInput() );
}

public function test_all() {
$context = new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE );
$this->assertFalse( $context->is_network_mode() );
Expand All @@ -47,6 +68,63 @@ public function test_network_mode_all() {
$this->run_reset( $context );
}

public function test_handle_reset_action__with_bad_nonce() {
remove_all_actions( 'admin_action_' . Reset::ACTION );
$reset = new Reset( $this->context_with_mutable_input );
$reset->register();
wp_set_current_user( $this->factory()->user->create( array( 'role' => 'administrator' ) ) );

$_GET['nonce'] = 'bad-nonce';
try {
do_action( 'admin_action_' . Reset::ACTION );
$this->fail( 'Expected invalid nonce exception' );
} catch ( WPDieException $die_exception ) {
$this->assertContains( 'Invalid nonce', $die_exception->getMessage() );
}

$this->assertOptionExists( self::TEST_OPTION );
}

public function test_handle_reset_action__with_valid_nonce_and_insufficient_permissions() {
remove_all_actions( 'admin_action_' . Reset::ACTION );
$reset = new Reset( $this->context_with_mutable_input );
$reset->register();
wp_set_current_user( $this->factory()->user->create() );

$_GET['nonce'] = wp_create_nonce( Reset::ACTION );
// Requires Site Kit setup permissions.
try {
do_action( 'admin_action_' . Reset::ACTION );
$this->fail( 'Expected insufficient permissions exception' );
} catch ( WPDieException $die_exception ) {
$this->assertContains( 'permissions to set up Site Kit', $die_exception->getMessage() );
}
$this->assertOptionExists( self::TEST_OPTION );
}

public function test_handle_reset_action__resets_and_redirects() {
remove_all_actions( 'admin_action_' . Reset::ACTION );
$reset = new Reset( $this->context_with_mutable_input );
$reset->register();
wp_set_current_user( $this->factory()->user->create( array( 'role' => 'administrator' ) ) );
$this->assertTrue( current_user_can( Permissions::SETUP ), 'failed asserting current user can Permissions::SETUP' );

$_GET['nonce'] = wp_create_nonce( Reset::ACTION );
// Expect redirects on success.
try {
do_action( 'admin_action_' . Reset::ACTION );
$this->fail( 'Expected redirection' );
} catch ( RedirectException $redirect ) {
$redirect_url = $redirect->get_location();
$this->assertStringStartsWith( $this->context_with_mutable_input->admin_url( 'splash' ), $redirect_url );
$this->assertContains( '&googlesitekit_reset_session=1', $redirect_url );
$this->assertContains( '&notification=reset_success', $redirect_url );

}
// Reset ran and option no longer exists.
$this->assertOptionNotExists( self::TEST_OPTION );
}

protected function run_reset( Context $context ) {
wp_load_alloptions();
$this->assertNotFalse( wp_cache_get( 'alloptions', 'options' ) );
Expand Down