Detect and save api key access restriction reason during key check

[MAILPOET-5103]
This commit is contained in:
Rostislav Wolny
2023-04-12 14:17:27 +02:00
committed by Aschepikov
parent 1f287e7af0
commit 37d6d612c4
3 changed files with 102 additions and 3 deletions

View File

@@ -18,6 +18,10 @@ class Bridge {
const PREMIUM_KEY_SETTING_NAME = 'premium.premium_key';
const PREMIUM_KEY_STATE_SETTING_NAME = 'premium.premium_key_state';
const KEY_ACCESS_INSUFFICIENT_PRIVILEGES = 'insufficient_privileges';
const KEY_ACCESS_EMAIL_VOLUME_LIMIT = 'email_volume_limit_reached';
const KEY_ACCESS_SUBSCRIBERS_LIMIT = 'subscribers_limit_reached';
const PREMIUM_KEY_VALID = 'valid'; // for backwards compatibility until version 3.0.0
const KEY_VALID = 'valid';
const KEY_INVALID = 'invalid';
@@ -250,9 +254,25 @@ class Bridge {
$keyState = self::KEY_CHECK_ERROR;
}
// Map of access error messages.
// The message is set by shop when a subscription has limited access to the feature.
// Insufficient privileges - is the default state if the plan doesn't include the feature.
// If the bridge returns 403 and there is a message set by the shop it returns the message.
$accessRestrictionsMap = [
'Insufficient privileges' => self::KEY_ACCESS_INSUFFICIENT_PRIVILEGES,
'Subscribers limit reached' => self::KEY_ACCESS_SUBSCRIBERS_LIMIT,
'Email volume limit reached' => self::KEY_ACCESS_EMAIL_VOLUME_LIMIT,
];
$accessRestriction = null;
if (!empty($result['code']) && $result['code'] === 403 && !empty($result['error_message'])) {
$accessRestriction = $accessRestrictionsMap[$result['error_message']] ?? null;
}
return $this->buildKeyState(
$keyState,
$result
$result,
$accessRestriction
);
}
@@ -277,9 +297,10 @@ class Bridge {
);
}
private function buildKeyState($keyState, $result) {
private function buildKeyState($keyState, $result, ?string $accessRestriction) {
$state = [
'state' => $keyState,
'access_restriction' => $accessRestriction,
'data' => !empty($result['data']) ? $result['data'] : null,
'code' => !empty($result['code']) ? $result['code'] : self::CHECK_ERROR_UNKNOWN,
];

View File

@@ -97,6 +97,7 @@ class API {
['site' => strtolower(WPFunctions::get()->homeUrl())]
);
$errorMessage = null;
$code = $this->wp->wpRemoteRetrieveResponseCode($result);
switch ($code) {
case 200:
@@ -108,10 +109,11 @@ class API {
default:
$this->logKeyCheckError((int)$code, $keyCheckType);
$body = null;
$errorMessage = $this->wp->wpRemoteRetrieveBody($result);
break;
}
return ['code' => $code, 'data' => $body];
return ['code' => $code, 'data' => $body, 'error_message' => $errorMessage];
}
public function logCurlInformation($headers, $info) {

View File

@@ -429,6 +429,82 @@ class BridgeTest extends \MailPoetTest {
expect($result['ok'])->equals(true); // verified
}
public function testItSavesAccessRestrictionForUnderprivilegePremiumKeys() {
$api = $this->createMock(API::class);
// Insufficient privileges
$this->checkKeyAccessRestrictionSetProperly(
'premium',
'Insufficient privileges',
Bridge::KEY_ACCESS_INSUFFICIENT_PRIVILEGES
);
// Email volume limit
$this->checkKeyAccessRestrictionSetProperly(
'premium',
'Email volume limit reached',
Bridge::KEY_ACCESS_EMAIL_VOLUME_LIMIT
);
// Subscribers limit
$this->checkKeyAccessRestrictionSetProperly(
'premium',
'Subscribers limit reached',
Bridge::KEY_ACCESS_SUBSCRIBERS_LIMIT
);
// Unknown value
$this->checkKeyAccessRestrictionSetProperly(
'premium',
'Nonsense message',
null
);
}
public function testItSavesAccessRestrictionForUnderprivilegeMSSKeys() {
$api = $this->createMock(API::class);
// Insufficient privileges
$this->checkKeyAccessRestrictionSetProperly(
'mss',
'Insufficient privileges',
Bridge::KEY_ACCESS_INSUFFICIENT_PRIVILEGES
);
// Email volume limit
$this->checkKeyAccessRestrictionSetProperly(
'mss',
'Email volume limit reached',
Bridge::KEY_ACCESS_EMAIL_VOLUME_LIMIT
);
// Subscribers limit
$this->checkKeyAccessRestrictionSetProperly(
'mss',
'Subscribers limit reached',
Bridge::KEY_ACCESS_SUBSCRIBERS_LIMIT
);
// Unknown value
$this->checkKeyAccessRestrictionSetProperly(
'mss',
'Nonsense message',
null
);
}
private function checkKeyAccessRestrictionSetProperly(string $keyType, string $errorMessage, $expectedAccessRestriction) {
$api = $this->createMock(API::class);
$method = $keyType === 'premium' ? 'checkPremiumKey' : 'checkMSSKey';
$api->method($method)->willReturn([
'code' => 403,
'error_message' => $errorMessage,
]);
$this->bridge->api = $api;
$result = $this->bridge->$method('abc');
expect($result)->notEmpty();
expect($result['data'])->null();
expect($result['access_restriction'])->equals($expectedAccessRestriction);
}
private function setMailPoetSendingMethod() {
$this->settings->set(
Mailer::MAILER_CONFIG_SETTING_NAME,