Skip to content

Commit

Permalink
Merge pull request #757 from google/feature/755-1.0-migration
Browse files Browse the repository at this point in the history
Add 1.0 Migration
  • Loading branch information
felixarntz authored Oct 31, 2019
2 parents 4ce8f88 + 22c4047 commit cb944a4
Show file tree
Hide file tree
Showing 3 changed files with 270 additions and 0 deletions.
130 changes: 130 additions & 0 deletions includes/Core/Util/Migration_1_0_0.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php
/**
* Migration for v1.0
*
* @package Google\Site_Kit\Core\Util
* @copyright 2019 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\Util;

use Google\Site_Kit\Context;
use Google\Site_Kit\Core\Authentication\Authentication;
use Google\Site_Kit\Core\Authentication\Clients\OAuth_Client;
use Google\Site_Kit\Core\Authentication\Credentials;
use Google\Site_Kit\Core\Storage\Encrypted_Options;
use Google\Site_Kit\Core\Storage\Options;
use Google\Site_Kit\Core\Storage\User_Options;

/**
* Class Migration_1_0_0
*
* @since 1.0.0
* @access private
* @ignore
*/
class Migration_1_0_0 {

/**
* Target DB version.
*/
const DB_VERSION = '1.0.0';

/**
* Context instance.
*
* @var Context
*/
protected $context;

/**
* Options instance.
*
* @var Options
*/
protected $options;

/**
* Constructor.
*
* @since 1.0.0
*
* @param Context $context Plugin context instance.
*/
public function __construct( Context $context ) {
$this->context = $context;
$this->options = new Options( $context );
}

/**
* Registers hooks.
*
* @since 1.0.0
*/
public function register() {
add_action( 'admin_init', array( $this, 'migrate' ) );
}

/**
* Migrates the DB.
*
* @since 1.0.0
*/
public function migrate() {
$db_version = $this->options->get( 'googlesitekit_db_version' );

if ( ! $db_version || version_compare( $db_version, self::DB_VERSION, '<' ) ) {
$this->migrate_install();

$this->options->set( 'googlesitekit_db_version', self::DB_VERSION );
}
}

/**
* Migrates old credentials and disconnects users.
*
* @since 1.0.0
*/
private function migrate_install() {
$credentials = ( new Encrypted_Options( $this->options ) )->get( Credentials::OPTION );

// Credentials can be filtered in so we must also check if there is a saved option present.
if ( isset( $credentials['oauth2_client_id'] ) && strpos( $credentials['oauth2_client_id'], '.apps.sitekit.withgoogle.com' ) ) {
$this->options->delete( Credentials::OPTION );
$this->options->set( Beta_Migration::OPTION_IS_PRE_PROXY_INSTALL, 1 );

$this->disconnect_users();

wp_cache_flush();
}
}

/**
* Disconnects authenticated users.
*
* @since 1.0.0
*/
private function disconnect_users() {
global $wpdb;

$user_options = new User_Options( $this->context );
$authentication = new Authentication( $this->context, $this->options, $user_options );

// User option keys are prefixed in single site and multisite when not in network mode.
$key_prefix = $this->context->is_network_mode() ? '' : $wpdb->get_blog_prefix();
$user_ids = ( new \WP_User_Query(
array(
'fields' => 'id',
'meta_key' => $key_prefix . OAuth_Client::OPTION_ACCESS_TOKEN,
'compare' => 'EXISTS',
)
) )->get_results();

foreach ( $user_ids as $user_id ) {
$user_options->switch_user( (int) $user_id );
$authentication->disconnect();
}
}
}
1 change: 1 addition & 0 deletions includes/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ function( $username, $user ) use ( $user_options ) {

( new Core\Util\Activation( $this->context, $options, $assets ) )->register();
( new Core\Util\Beta_Migration( $this->context ) )->register();
( new Core\Util\Migration_1_0_0( $this->context ) )->register();
( new Core\Util\Uninstallation( $reset ) )->register();

if ( defined( 'WP_DEBUG' ) && true === WP_DEBUG ) {
Expand Down
139 changes: 139 additions & 0 deletions tests/phpunit/integration/Core/Util/Migration_1_0_0Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php
/**
* \Google\Site_Kit\Core\Util\Migration_1_0_0Test
*
* @package Google\Site_Kit\Tests\Core\Util
* @copyright 2019 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\Util;

use Google\Site_Kit\Context;
use Google\Site_Kit\Core\Authentication\Clients\OAuth_Client;
use Google\Site_Kit\Core\Authentication\Credentials;
use Google\Site_Kit\Core\Storage\Options;
use Google\Site_Kit\Core\Util\Migration_1_0_0;
use Google\Site_Kit\Tests\TestCase;

class Migration_1_0_0Test extends TestCase {

public function test_register() {
$migration = new Migration_1_0_0( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) );
remove_all_actions( 'admin_init' );

$migration->register();

$this->assertTrue( has_action( 'admin_init' ) );
}

public function test_migrate() {
$context = new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE );
$options = new Options( $context );
$credentials = new Credentials( $options );
$migration = new Migration_1_0_0( $context );

// Upgrade will update the DB version if run.
$this->delete_db_version();

$migration->migrate();

$this->assertEquals( Migration_1_0_0::DB_VERSION, $this->get_db_version() );

// The upgrade will NOT delete old GCP credentials if present.
$this->delete_db_version();
$this->set_gcp_credentials();
$this->assertTrue( $credentials->has() );

$migration->migrate();

$this->assertTrue( $credentials->has() );
$this->assertEquals( Migration_1_0_0::DB_VERSION, $this->get_db_version() );

// The upgrade WILL delete proxy credentials if present.
$this->delete_db_version();
$this->set_proxy_credentials();
$this->assertTrue( $credentials->has() );

$migration->migrate();

$this->assertFalse( $credentials->has() );
$this->assertEquals( Migration_1_0_0::DB_VERSION, $this->get_db_version() );

// The upgrade will not disconnect any user if GCP credentials are present.
$this->delete_db_version();
$this->set_gcp_credentials();

$users_with_tokens = array(
$this->create_user_with_access_token(),
$this->create_user_with_access_token(),
$this->create_user_with_access_token(),
);
$users_without = array(
$this->factory()->user->create(),
$this->factory()->user->create(),
$this->factory()->user->create(),
);

$migration->migrate();

foreach ( $users_with_tokens as $user_with_token ) {
$this->assertUserHasAccessToken( $user_with_token );
}

// The upgrade will disconnect any user with an auth token if proxy credentials are present.
$this->delete_db_version();
$this->set_proxy_credentials();

$migration->migrate();

foreach ( $users_with_tokens as $user_who_had_token ) {
$this->assertUserNotHasAccessToken( $user_who_had_token );
}
foreach ( $users_without as $user_without ) {
$this->assertUserNotHasAccessToken( $user_without );
}
}

private function assertUserHasAccessToken( $user_id ) {
$this->assertNotEmpty( get_user_option( OAuth_Client::OPTION_ACCESS_TOKEN, $user_id ) );
}

private function assertUserNotHasAccessToken( $user_id ) {
$this->assertEmpty( get_user_option( OAuth_Client::OPTION_ACCESS_TOKEN, $user_id ) );
}

private function create_user_with_access_token() {
$user_id = $this->factory()->user->create();
update_user_option( $user_id, OAuth_Client::OPTION_ACCESS_TOKEN, "test-access-token-$user_id" );

return $user_id;
}

private function get_db_version() {
return ( new Options( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ) )->get( 'googlesitekit_db_version' );
}

private function delete_db_version() {
( new Options( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ) )->delete( 'googlesitekit_db_version' );
}

private function delete_credentials() {
( new Options( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ) )->delete( Credentials::OPTION );
}

private function set_gcp_credentials() {
( new Credentials( new Options( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ) ) )->set( array(
'oauth2_client_id' => 'test-client-id.apps.googleusercontent.com',
'oauth2_client_secret' => 'test-client-secret',
) );
}

private function set_proxy_credentials() {
( new Credentials( new Options( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ) ) )->set( array(
'oauth2_client_id' => 'test-site-id.apps.sitekit.withgoogle.com',
'oauth2_client_secret' => 'test-site-secret',
) );
}
}

0 comments on commit cb944a4

Please sign in to comment.