Added API credentials validation

This commit is contained in:
gleemand 2022-06-17 10:43:18 +03:00 committed by GitHub
parent fb811c7bdf
commit 13e0df6cf3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 125 additions and 19 deletions

View File

@ -389,6 +389,22 @@ class RetailcrmTools
return false;
}
/**
* Validate crm api key
*
* @param $apiKey
*
* @return bool
*/
public static function validateCrmApiKey($apiKey)
{
if (32 === mb_strlen($apiKey)) {
return Validate::isGenericName($apiKey);
}
return false;
}
public static function getDate($file)
{
if (file_exists($file)) {

View File

@ -89,19 +89,16 @@ class RetailcrmSettingsValidator
$urlAndApiKeyValidated = false;
}
if ($this->settings->issetValue('apiKey') && !$this->settings->getValue('apiKey')) {
if ($this->settings->issetValue('apiKey') && !RetailcrmTools::validateCrmApiKey($this->settings->getValue('apiKey'))) {
$this->addError('errors.key');
$urlAndApiKeyValidated = false;
}
if ($urlAndApiKeyValidated && ($this->settings->issetValue('url') || $this->settings->issetValue('apiKey'))) {
if (!$this->validateApiVersion(
$this->validateApiCredentials(
$this->settings->getValueWithStored('url'),
$this->settings->getValueWithStored('apiKey')
)
) {
$this->addError('errors.version');
}
);
}
// check abandoned carts status
@ -269,12 +266,7 @@ class RetailcrmSettingsValidator
return true;
}
/**
* Returns true if provided connection supports API v5
*
* @return bool
*/
private function validateApiVersion($url, $apiKey)
public function validateApiCredentials($url, $apiKey)
{
/** @var RetailcrmProxy|RetailcrmApiClientV5 $api */
$api = new RetailcrmProxy(
@ -282,9 +274,20 @@ class RetailcrmSettingsValidator
$apiKey
);
return $this->validateApiVersion($api) && $this->validateApiAccess($api);
}
/**
* Returns true if provided connection supports API v5
*
* @return bool
*/
private function validateApiVersion($api)
{
$response = $api->apiVersions();
if (false !== $response && isset($response['versions']) && !empty($response['versions'])) {
if (false !== $response && isset($response['success']) && $response['success']) {
if (isset($response['versions']) && !empty($response['versions'])) {
foreach ($response['versions'] as $version) {
if ($version == static::LATEST_API_VERSION
|| Tools::substr($version, 0, 1) == static::LATEST_API_VERSION
@ -292,7 +295,57 @@ class RetailcrmSettingsValidator
return true;
}
}
$this->addError('errors.version');
}
} else {
$this->addError('errors.connect');
}
return false;
}
/**
* Returns true if provided connection support necessary scopes and access_selective
*
* @return bool
*/
private function validateApiAccess($api)
{
$response = $api->credentials();
if (false !== $response) {
return $this->validateApiSiteAccess($response) && $this->validateApiScopes($response);
}
return false;
}
private function validateApiSiteAccess($credentials)
{
if (isset($credentials['siteAccess'], $credentials['sitesAvailable'])
&& RetailCRM::REQUIRED_CRM_SITE_ACCESS === $credentials['siteAccess']
&& is_array($credentials['sitesAvailable'])
&& RetailCRM::REQUIRED_CRM_SITE_COUNT === count($credentials['sitesAvailable'])
) {
return true;
}
$this->addError('errors.access');
return false;
}
private function validateApiScopes($credentials)
{
if (isset($credentials['scopes'])
&& is_array($credentials['scopes'])
&& !array_diff(RetailCRM::REQUIRED_CRM_SCOPES, $credentials['scopes'])
) {
return true;
}
$this->addError('errors.scopes');
return false;
}

View File

@ -76,6 +76,43 @@ class RetailCRM extends Module
const CONSULTANT_RCCT = 'RETAILCRM_CONSULTANT_RCCT';
const ENABLE_WEB_JOBS = 'RETAILCRM_ENABLE_WEB_JOBS';
const REQUIRED_CRM_SITE_ACCESS = 'access_selective';
const REQUIRED_CRM_SITE_COUNT = 1;
const REQUIRED_CRM_SCOPES = [
'order_read',
'order_write',
'customer_read',
'customer_write',
'store_read',
'store_write',
'reference_read',
'reference_write',
'analytics_write',
'telephony_read',
'telephony_write',
'delivery_read',
'delivery_write',
'user_read',
'user_write',
'segment_read',
'custom_fields_write',
'custom_fields_read',
'task_read',
'task_write',
'integration_read',
'integration_write',
'cost_read',
'cost_write',
'payments_read',
'payments_write',
'file_read',
'file_write',
'loyalty_read',
'loyalty_write',
'verification_write',
'verification_read',
];
// todo dynamically define controller classes
const ADMIN_CONTROLLERS
= [

File diff suppressed because one or more lines are too long