mirror of
https://gh.wpcy.net/https://github.com/discourse/wp-discourse.git
synced 2026-05-23 03:20:46 +08:00
* Don't try to add url to <head> if it's not present * Update js config and formatting for comment block and sidebar * PHP Linting * FIX: Don't auto-publish updates to existing posts. See: https://meta.discourse.org/t/disable-posting-wordpress-articles-to-discourse-when-theyre-updated/204488 * Bump version and release notes. * Fix remote-post.php linting * Update tests.yml to install svn * Re-generate comments js build
258 lines
7.6 KiB
PHP
Vendored
258 lines
7.6 KiB
PHP
Vendored
<?php
|
|
/**
|
|
* Class DiscourseSSOTest
|
|
*
|
|
* @package WPDiscourse
|
|
*/
|
|
|
|
namespace WPDiscourse\Test;
|
|
|
|
use WPDiscourse\DiscourseSSO\DiscourseSSO;
|
|
use WPDiscourse\Test\UnitTest;
|
|
|
|
/**
|
|
* DiscourseSSO test case.
|
|
*/
|
|
class DiscourseSSOTest extends UnitTest {
|
|
|
|
/**
|
|
* User id
|
|
*
|
|
* @access protected
|
|
* @var int
|
|
*/
|
|
protected $user_id;
|
|
|
|
/**
|
|
* Secret
|
|
*
|
|
* @access protected
|
|
* @var string
|
|
*/
|
|
protected $secret;
|
|
|
|
/**
|
|
* Nonce
|
|
*
|
|
* @access protected
|
|
* @var string
|
|
*/
|
|
protected $nonce;
|
|
|
|
/**
|
|
* Query vars
|
|
*
|
|
* @access protected
|
|
* @var array
|
|
*/
|
|
protected $query_vars;
|
|
|
|
/**
|
|
* Client
|
|
*
|
|
* @access protected
|
|
* @var \WPDiscourse\DiscourseSSO\DiscourseSSO
|
|
*/
|
|
protected $discourse_sso;
|
|
|
|
/**
|
|
* Signaure
|
|
*
|
|
* @access protected
|
|
* @var string
|
|
*/
|
|
protected $signature;
|
|
|
|
/**
|
|
* Payload
|
|
*
|
|
* @access protected
|
|
* @var string
|
|
*/
|
|
protected $payload;
|
|
|
|
public function setUp(): void {
|
|
$this->secret = 'secret';
|
|
$this->nonce = 'abcd';
|
|
$this->payload = base64_encode( "nonce={$this->nonce}" );
|
|
$this->signature = hash_hmac( 'sha256', $this->payload, $this->secret );
|
|
|
|
self::$plugin_options['sso-secret'] = $this->secret;
|
|
|
|
$this->discourse_sso = \Mockery::mock( DiscourseSSO::class )->makePartial();
|
|
$this->discourse_sso->shouldReceive( 'redirect_to' )->andReturnArg( 0 );
|
|
$this->discourse_sso->setup_options( array_merge( self::$plugin_options, array( 'enable-sso' => true ) ) );
|
|
$this->discourse_sso->setup_logger();
|
|
|
|
$this->query_vars = array(
|
|
'sso' => $this->payload,
|
|
'sig' => rawurlencode( $this->signature ),
|
|
);
|
|
$this->user_id = self::factory()->user->create();
|
|
}
|
|
|
|
public function tearDown(): void {
|
|
parent::tearDown();
|
|
|
|
$_GET['request'] = null;
|
|
delete_user_meta( $this->user_id, 'discourse_sso_user_id', true );
|
|
}
|
|
|
|
/**
|
|
* sso_parse_request without a user redirects to login with correct redirect_to url.
|
|
*
|
|
*/
|
|
public function test_sso_parse_request_no_user() {
|
|
$parse_result = $this->discourse_sso->sso_parse_request( (object) array( 'query_vars' => $this->query_vars ) );
|
|
$wp_redirect_url = add_query_arg( $this->payload, rawurlencode( $this->signature ) );
|
|
$wp_login_url = wp_login_url( esc_url_raw( $wp_redirect_url ) );
|
|
|
|
$this->assertEquals( $parse_result, $wp_login_url );
|
|
}
|
|
|
|
/**
|
|
* sso_parse_request with a user validates payload and redirects to Discourse.
|
|
*
|
|
*/
|
|
public function test_sso_parse_request_user() {
|
|
$user = wp_set_current_user( $this->user_id );
|
|
$parse_result = $this->discourse_sso->sso_parse_request( (object) array( 'query_vars' => $this->query_vars ) );
|
|
|
|
$params = array_merge( $this->discourse_sso->get_sso_params( $user ), array( 'nonce' => $this->nonce ) );
|
|
$payload = base64_encode( http_build_query( $params ) );
|
|
$signature = hash_hmac( 'sha256', $payload, $this->secret );
|
|
$query_vars = array(
|
|
'sso' => $payload,
|
|
'sig' => $signature,
|
|
);
|
|
$discourse_url = self::$plugin_options['url'] . '/session/sso_login?' . http_build_query( $query_vars );
|
|
|
|
$this->assertEquals( $parse_result, $discourse_url );
|
|
}
|
|
|
|
/**
|
|
* sso_parse_request handles logout requests from Discourse
|
|
*
|
|
*/
|
|
public function test_sso_parse_request_logout() {
|
|
$user = wp_set_current_user( $this->user_id );
|
|
|
|
$_GET['request'] = 'logout';
|
|
$this->discourse_sso->sso_parse_request( (object) array( 'query_vars' => array() ) );
|
|
|
|
$this->assertEquals( is_user_logged_in(), false );
|
|
}
|
|
|
|
/**
|
|
* sso_parse_request handles invalid signature
|
|
*
|
|
*/
|
|
public function test_sso_parse_request_invalid_signature() {
|
|
$user = wp_set_current_user( $this->user_id );
|
|
|
|
$query_vars = array(
|
|
'sso' => $this->query_vars['sso'],
|
|
'sig' => 'i2v0a8l9i6d',
|
|
);
|
|
$parse_result = $this->discourse_sso->sso_parse_request( (object) array( 'query_vars' => $query_vars ) );
|
|
|
|
$this->assertTrue( is_wp_error( $parse_result ) );
|
|
$this->assertEquals( $parse_result->get_error_message(), 'SSO error' );
|
|
|
|
$log = $this->get_last_log();
|
|
$this->assertMatchesRegularExpression( '/sso_provider.ERROR: parse_request.invalid_sso/', $log );
|
|
}
|
|
|
|
/**
|
|
* sso_parse_request handles invalid nonce
|
|
*
|
|
*/
|
|
public function test_sso_parse_request_invalid_nonce() {
|
|
$user = wp_set_current_user( $this->user_id );
|
|
|
|
$payload = base64_encode( "not_nonce={$this->nonce}" );
|
|
$query_vars = array(
|
|
'sso' => $payload,
|
|
'sig' => hash_hmac( 'sha256', $payload, $this->secret ),
|
|
);
|
|
$parse_result = $this->discourse_sso->sso_parse_request( (object) array( 'query_vars' => $query_vars ) );
|
|
|
|
$error_message = 'Nonce not found in payload!';
|
|
$this->assertTrue( is_wp_error( $parse_result ) );
|
|
$this->assertEquals( $parse_result->get_error_message(), $error_message );
|
|
|
|
$log = $this->get_last_log();
|
|
$this->assertMatchesRegularExpression( '/sso_provider.ERROR: parse_request.invalid_sso/', $log );
|
|
$this->assertMatchesRegularExpression( '/"message":"' . $error_message . '"/', $log );
|
|
}
|
|
|
|
/**
|
|
* logout_from_discourse logs out user from Discourse
|
|
*
|
|
*/
|
|
public function test_logout_from_discourse() {
|
|
$user = wp_set_current_user( $this->user_id );
|
|
|
|
$second_request = array(
|
|
'url' => 'log_out',
|
|
'method' => 'POST',
|
|
'response' => $this->build_response( 'success' ),
|
|
);
|
|
$discourse_user = $this->mock_remote_post_success( 'user', 'GET', $second_request );
|
|
|
|
$logout_result = $this->discourse_sso->logout_from_discourse();
|
|
$this->assertTrue( $logout_result );
|
|
|
|
$discourse_user_id = get_user_meta( $user->ID, 'discourse_sso_user_id', true );
|
|
$this->assertEquals( $discourse_user_id, $discourse_user->user->id );
|
|
}
|
|
|
|
/**
|
|
* logout_from_discourse handles failure to get Discourse user
|
|
*
|
|
*/
|
|
public function test_logout_from_discourse_failed_to_get_discourse_user() {
|
|
$user = wp_set_current_user( $this->user_id );
|
|
|
|
$request = array(
|
|
'method' => 'POST',
|
|
'response' => $this->build_response( 'invalid_parameters' ),
|
|
);
|
|
$this->mock_remote_post( $request );
|
|
|
|
$logout_result = $this->discourse_sso->logout_from_discourse();
|
|
|
|
$error_message = 'The Discourse user_id could not be returned when trying to logout the user.';
|
|
$this->assertTrue( is_wp_error( $logout_result ) );
|
|
$this->assertEquals( $logout_result->get_error_message(), $error_message );
|
|
|
|
$log = $this->get_last_log();
|
|
$this->assertMatchesRegularExpression( '/sso_provider.ERROR: logout.discourse_user/', $log );
|
|
$this->assertMatchesRegularExpression( '/"message":"' . $error_message . '"/', $log );
|
|
}
|
|
|
|
/**
|
|
* logout_from_discourse handles failure to logout
|
|
*
|
|
*/
|
|
public function test_logout_from_discourse_failed_to_logout() {
|
|
$user = wp_set_current_user( $this->user_id );
|
|
$response = $this->build_response( 'not_found' );
|
|
$second_request = array(
|
|
'url' => 'log_out',
|
|
'method' => 'POST',
|
|
'response' => $response,
|
|
);
|
|
$discourse_user = $this->mock_remote_post_success( 'user', 'GET', $second_request );
|
|
|
|
$logout_result = $this->discourse_sso->logout_from_discourse();
|
|
|
|
$error_message = 'There was an error in logging out the user from Discourse.';
|
|
$this->assertTrue( is_wp_error( $logout_result ) );
|
|
$this->assertEquals( $logout_result->get_error_message(), $error_message );
|
|
|
|
$log = $this->get_last_log();
|
|
$this->assertMatchesRegularExpression( '/sso_provider.ERROR: logout.response_error/', $log );
|
|
$this->assertMatchesRegularExpression( '/"message":"' . $error_message . '"/', $log );
|
|
}
|
|
}
|