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

Handle previously unhandled exceptions with social plugin and Hybridauth #4643

Merged
merged 3 commits into from
Dec 29, 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
2 changes: 1 addition & 1 deletion e107_core/controllers/system/xup.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public function actionTest()


$testUrl = SITEURL."?route=system/xup/test";
$providers = $manager->getValidConfiguredProviderConfigs();
$providers = $manager->getSupportedConfiguredProviderConfigs();

foreach($providers as $key=>$var)
{
Expand Down
2 changes: 1 addition & 1 deletion e107_core/shortcodes/batch/signup_shortcodes.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private function generateXupLoginButtons($type, $size, $class)


$manager = new social_login_config(e107::getConfig());
$providers = $manager->getValidConfiguredProviderConfigs();
$providers = $manager->getSupportedConfiguredProviderConfigs();

foreach ($providers as $p => $v)
{
Expand Down
64 changes: 50 additions & 14 deletions e107_handlers/user_handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -1117,24 +1117,43 @@ class e_user_provider

/**
* Hybridauth adapter
* @var \Hybridauth\Adapter\AdapterInterface
*
* @var \Hybridauth\Adapter\AdapterInterface|null
*/
public $adapter;

/**
* Hybridauth object
*
* @var Hybridauth\Hybridauth
*/
protected $hybridauth;
protected $_config = array();
/**
* @var social_login_config
* @var social_login_config|null
*/
protected $social_login_config_manager;
protected $social_login_config_manager = null;

public function __construct($provider = null, $config = array())
/**
* Create a new Hybridauth-backed social login provider
*
* This constructor suppresses exceptions due to client usages not handling exceptions and instead sends error
* messages to logged in admins. To check if a Hybridauth configuration is valid, use
* {@link e107::getUserProvider()} with the provider name while logged in as an admin.
*
* @param string|null $provider The name of the provider to use
* @param array $config An override Hybridauth configuration that takes precedence over the
* database Hybridauth configuration for this provider. Leave blank to use
* the database configuration.
* @param bool $suppress_exceptions Set to false to propagate Hybridauth exceptions
* @throws \Hybridauth\Exception\UnexpectedValueException if the provider is disabled
* @throws \Hybridauth\Exception\InvalidArgumentException if the provider configuration validation failed
*/
public function __construct($provider = null, $config = array(), $suppress_exceptions = true)
{
require_once(e_PLUGIN . "social/includes/social_login_config.php");
@include_once(e_PLUGIN . "social/includes/social_login_config.php");
if (!class_exists('social_login_config')) return;

$this->social_login_config_manager = new social_login_config(e107::getConfig());

if (!empty($config))
Expand All @@ -1144,24 +1163,38 @@ public function __construct($provider = null, $config = array())
else
{
$this->_config = array(
"callback" => $this->generateCallbackUrl($provider),
"providers" => $this->social_login_config_manager->getValidConfiguredProviderConfigs(),
"callback" => $this->generateCallbackUrl($provider),
"providers" => $this->social_login_config_manager->getSupportedConfiguredProviderConfigs(),
"debug_mode" => 'error',
"debug_file" => e_LOG . "hybridAuth.log"
);

}

$this->respawnHybridauth();
$this->setProvider($provider);
try
{
$this->respawnHybridauth();
$this->setProvider($provider);

$providerId = $this->getProvider();
if ($providerId && $this->hybridauth->isConnectedWith($providerId))
$providerId = $this->getProvider();
if ($providerId && $this->hybridauth->isConnectedWith($providerId))
{
$this->adapter = $this->hybridauth->getAdapter($providerId);
}
}
catch (\Hybridauth\Exception\InvalidArgumentException $e)
{
$this->adapter = $this->hybridauth->getAdapter($providerId);
if (!$suppress_exceptions) throw $e;
}
catch (\Hybridauth\Exception\UnexpectedValueException $e)
{
if (!$suppress_exceptions) throw $e;
}
}

/**
* @throws \Hybridauth\Exception\InvalidArgumentException
*/
private function respawnHybridauth()
{
$this->hybridauth = new Hybridauth\Hybridauth($this->_config);
Expand Down Expand Up @@ -1218,9 +1251,10 @@ public function userId()
/**
* Get the social login providers for which we have adapters
*
* This function is slow! Please cache the output instead of calling it multiple times.
* Despite this being a static method, it memoizes (caches) the slow reflection code in the {@link e107} registry
* after the first run, so subsequent calls to this method are fast.
*
* @return array String list of supported providers. Empty if Hybridauth is broken.
* @return string[] String list of supported providers. Empty if Hybridauth is broken.
*/
public static function getSupportedProviders()
{
Expand Down Expand Up @@ -1466,6 +1500,8 @@ private static function array_merge_recursive_distinct(&$array1, &$array2)
*/
public function isSocialLoginEnabled()
{
if ($this->social_login_config_manager === null) return false;

return $this->social_login_config_manager->isFlagActive(social_login_config::ENABLE_BIT_GLOBAL);
}

Expand Down
13 changes: 13 additions & 0 deletions e107_plugins/social/admin_config.php
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,19 @@ private function generateSocialLoginSection($provider_names, $readonly=false)

foreach ($provider_names as $provider_name)
{
// Check if the current configuration for the provider is valid
try
{
new e_user_provider($provider_name, [], false);
}
catch (\Hybridauth\Exception\InvalidArgumentException $e)
{
e107::getMessage()->addError("[{$e->getCode()}] {$e->getMessage()}");
}
catch (\Hybridauth\Exception\UnexpectedValueException $ignored)
{
}

$text .= $this->generateSocialLoginRow($provider_name, $readonly);
}

Expand Down
9 changes: 8 additions & 1 deletion e107_plugins/social/includes/social_login_config.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,13 @@ public function getProviderConfig($providerName, $path = "")

/**
* Get configs of providers that are supported and configured
*
* These configs are not validated here by the social login implementation.
* This method only filters out providers that are not supported and not configured.
*
* @return array Associative array where the key is the denormalized provider name and the value is its config
*/
public function getValidConfiguredProviderConfigs()
public function getSupportedConfiguredProviderConfigs()
{
$supported_providers = $this->getSupportedProviders();
$configured_providers = $this->getConfiguredProviders();
Expand Down Expand Up @@ -233,6 +237,9 @@ public function getConfiguredProviders()
return $output;
}

/**
* @return array
*/
protected function getSocialLoginConfig()
{
$config = $this->config->get(self::SOCIAL_LOGIN_PREF);
Expand Down
28 changes: 28 additions & 0 deletions e107_tests/tests/unit/e_user_providerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,32 @@ public function testGetSupplementalFieldsOf()
$result = e_user_provider::getSupplementalFieldsOf("Vkontakte");
$this->assertTrue(array_key_exists('photo_size', $result));
}

public function testNewSuppressExceptions()
{
$this->assertInstanceOf(
e_user_provider::class,
new e_user_provider("Facebook", ["providers" => ["Facebook", ["enabled" => true]]])
);
}

public function testNewNoSuppressConfigurationException()
{
$this->expectException(\Hybridauth\Exception\InvalidArgumentException::class);
new e_user_provider(
"Facebook",
["providers" => ["Facebook" => ["enabled" => true]]],
false
);
}

public function testNewNoSuppressDisabledException()
{
$this->expectException(\Hybridauth\Exception\UnexpectedValueException::class);
new e_user_provider(
"Facebook",
["providers" => ["Facebook" => ["enabled" => false]]],
false
);
}
}