type fixes

This commit is contained in:
Yuri Kuznetsov
2022-03-06 13:04:41 +02:00
parent 9449d8364b
commit dbf20bfff6
4 changed files with 230 additions and 5 deletions

View File

@@ -67,6 +67,10 @@ class ClientManager
*/
protected $injectableFactory = null;
/**
*
* @var array<string,array<string,mixed>>
*/
protected $clientMap = [];
public function __construct(
@@ -81,6 +85,14 @@ class ClientManager
$this->injectableFactory = $injectableFactory;
}
/**
* @param array{
* accessToken: ?string,
* tokenType: ?string,
* expiresAt?: ?string,
* refreshToken?: ?string,
* } $data
*/
public function storeAccessToken(string $hash, array $data): void
{
if (empty($this->clientMap[$hash]) || empty($this->clientMap[$hash]['externalAccountEntity'])) {
@@ -154,6 +166,7 @@ class ClientManager
return null;
}
/** @var class-string */
$className = $this->metadata->get("integrations.{$integration}.clientClassName");
$client = $this->injectableFactory->create($className);
@@ -178,6 +191,7 @@ class ClientManager
/** @var ExternalAccountEntity|null $externalAccountEntity */
$externalAccountEntity = $this->entityManager->getEntity('ExternalAccount', $integration . '__' . $userId);
/** @var class-string */
$className = $this->metadata->get("integrations.{$integration}.clientClassName");
$redirectUri = $this->config->get('siteUrl') . '?entryPoint=oauthCallback';
@@ -245,6 +259,10 @@ class ClientManager
return $client;
}
/**
* @param object $client
* @return void
*/
protected function addToClientMap(
$client,
IntegrationEntity $integrationEntity,
@@ -260,6 +278,9 @@ class ClientManager
];
}
/**
* @param object $client
*/
protected function getClientRecord($client): Entity
{
$data = $this->clientMap[spl_object_hash($client)];
@@ -271,6 +292,9 @@ class ClientManager
return $data['externalAccountEntity'];
}
/**
* @param object $client
*/
public function isClientLocked($client): bool
{
$externalAccountEntity = $this->getClientRecord($client);

View File

@@ -31,12 +31,27 @@ namespace Espo\Core\ExternalAccount\Clients;
interface IClient
{
/**
* @param string $name
* @return mixed
*/
public function getParam($name);
/**
* @param string $name
* @param mixed $value
* @return mixed
*/
public function setParam($name, $value);
/**
* @param array<string,mixed> $params
* @return mixed
*/
public function setParams(array $params);
/**
* @return bool
*/
public function ping();
}

View File

@@ -42,12 +42,24 @@ use DateTime;
abstract class OAuth2Abstract implements IClient
{
/**
* @var ?Client
*/
protected $client = null;
/**
* @var ?ClientManager
*/
protected $manager = null;
/**
* @var Log
*/
protected $log;
/**
* @var string[]
*/
protected $paramList = [
'endpoint',
'tokenEndpoint',
@@ -60,16 +72,34 @@ abstract class OAuth2Abstract implements IClient
'expiresAt',
];
/**
* @var ?string
*/
protected $clientId = null;
/**
* @var ?string
*/
protected $clientSecret = null;
/**
* @var ?string
*/
protected $accessToken = null;
/**
* @var ?string
*/
protected $refreshToken = null;
/**
* @var ?string
*/
protected $redirectUri = null;
/**
* @var ?string
*/
protected $expiresAt = null;
const ACCESS_TOKEN_EXPIRATION_MARGIN = '20 seconds';
@@ -78,6 +108,9 @@ abstract class OAuth2Abstract implements IClient
const LOCK_CHECK_STEP = 0.5;
/**
* @param array<string,mixed> $params
*/
public function __construct(
Client $client,
array $params = [],
@@ -91,6 +124,10 @@ abstract class OAuth2Abstract implements IClient
$this->setParams($params);
}
/**
* @param string $name
* @return mixed
*/
public function getParam($name)
{
if (in_array($name, $this->paramList)) {
@@ -100,6 +137,11 @@ abstract class OAuth2Abstract implements IClient
return null;
}
/**
* @param string $name
* @param mixed $value
* @return void
*/
public function setParam($name, $value)
{
if (in_array($name, $this->paramList)) {
@@ -113,6 +155,10 @@ abstract class OAuth2Abstract implements IClient
}
}
/**
* @param array<string,mixed> $params
* @return void
*/
public function setParams(array $params)
{
foreach ($this->paramList as $name) {
@@ -122,6 +168,10 @@ abstract class OAuth2Abstract implements IClient
}
}
/**
* @param array<string,mixed> $data
* @return void
*/
protected function afterTokenRefreshed(array $data): void
{
if ($this->manager) {
@@ -129,6 +179,19 @@ abstract class OAuth2Abstract implements IClient
}
}
/**
* @param array{
* access_token: string,
* token_type: string,
* refresh_token?: string,
* expires_in?: int,
* } $result
* @return array{
* accessToken: string,
* tokenType: string,
* expiresAt: ?string,
* }
*/
protected function getAccessTokenDataFromResponseResult($result): array
{
$data = [];
@@ -152,7 +215,12 @@ abstract class OAuth2Abstract implements IClient
}
/**
* @return array|null
* @return ?array{
* accessToken: string,
* tokenType: string,
* expiresAt: ?string,
* refreshToken: string,
* }
*/
public function getAccessTokenFromAuthorizationCode(string $code)
{
@@ -292,7 +360,7 @@ abstract class OAuth2Abstract implements IClient
/**
*
* @param string $url
* @param array|string|null $params
* @param array<string,mixed>|string|null $params
* @param string $httpMethod
* @param ?string $contentType
* @param bool $allowRenew
@@ -414,6 +482,12 @@ abstract class OAuth2Abstract implements IClient
return false;
}
/**
* @param array<string,mixed> $r
* @return ?array{
* action: string,
* }
*/
protected function handleErrorResponse($r)
{
if ($r['code'] == 401 && !empty($r['result'])) {

View File

@@ -58,24 +58,54 @@ class Client
const GRANT_TYPE_PASSWORD = 'password';
const GRANT_TYPE_CLIENT_CREDENTIALS = 'client_credentials';
/**
* @var ?string
*/
protected $clientId = null;
/**
* @var ?string
*/
protected $clientSecret = null;
/**
* @var ?string
*/
protected $accessToken = null;
/**
* @var ?string
*/
protected $expiresAt = null;
/**
* @var int
*/
protected $authType = self::AUTH_TYPE_URI;
/**
* @var string
*/
protected $tokenType = self::TOKEN_TYPE_URI;
/**
* @var ?string
*/
protected $accessTokenSecret = null;
/**
* @var string
*/
protected $accessTokenParamName = 'access_token';
/**
* @var ?string
*/
protected $certificateFile = null;
/**
* @var array<string,mixed>
*/
protected $curlOptions = [];
public function __construct()
@@ -85,56 +115,110 @@ class Client
}
}
/**
* @param string $clientId
* @return void
*/
public function setClientId($clientId)
{
$this->clientId = $clientId;
}
/**
* @param ?string $clientSecret
* @return void
*/
public function setClientSecret($clientSecret)
{
$this->clientSecret = $clientSecret;
}
/**
* @param ?string $accessToken
* @return void
*/
public function setAccessToken($accessToken)
{
$this->accessToken = $accessToken;
}
/**
* @param int $authType
* @return void
*/
public function setAuthType($authType)
{
$this->authType = $authType;
}
/**
* @param string $certificateFile
* @return void
*/
public function setCertificateFile($certificateFile)
{
$this->certificateFile = $certificateFile;
}
/**
* @param string $option
* @param mixed $value
* @return void
*/
public function setCurlOption($option, $value)
{
$this->curlOptions[$option] = $value;
}
/**
* @param array<string,mixed> $options
* @return void
*/
public function setCurlOptions($options)
{
$this->curlOptions = array_merge($this->curlOptions, $options);
}
/**
* @param string $tokenType
* @return void
*/
public function setTokenType($tokenType)
{
$this->tokenType = $tokenType;
}
/**
* @param ?string $value
* @return void
*/
public function setExpiresAt($value)
{
$this->expiresAt = $value;
}
/**
* @param ?string $accessTokenSecret
* @return void
*/
public function setAccessTokenSecret($accessTokenSecret)
{
$this->accessTokenSecret = $accessTokenSecret;
}
/**
* @param string $url
* @param array<string,mixed>|string|null $params
* @param string $httpMethod
* @param array<string,string> $httpHeaders
* @return array{
* result: array<string,mixed>|string,
* code: int,
* contentType: string,
* header: string,
* }
* @throws Exception
*/
public function request($url, $params = null, $httpMethod = self::HTTP_METHOD_GET, array $httpHeaders = [])
{
if ($this->accessToken) {
@@ -162,6 +246,19 @@ class Client
return $this->execute($url, $params, $httpMethod, $httpHeaders);
}
/**
* @param string $url
* @param array<string,mixed>|string|null $params
* @param string $httpMethod
* @param array<string,string> $httpHeaders
* @return array{
* result: array<string,mixed>|string,
* code: int,
* contentType: string,
* header: string,
* }
* @throws Exception
*/
private function execute($url, $params, $httpMethod, array $httpHeaders = [])
{
$curlOptions = [
@@ -267,6 +364,21 @@ class Client
];
}
/**
* @param string $url
* @param string $grantType
* @param array{
* client_id?: string,
* client_secret?: string,
* } $params
* @return array{
* result: array<string,mixed>|string,
* code: int,
* contentType: string,
* header: string,
* }
* @throws Exception
*/
public function getAccessToken($url, $grantType, array $params)
{
$params['grant_type'] = $grantType;