mirror of
https://github.com/espocrm/espocrm.git
synced 2026-06-27 22:46:04 +00:00
external account changes
This commit is contained in:
@@ -93,12 +93,7 @@ class ExternalAccount extends \Espo\Core\Controllers\Record
|
||||
{
|
||||
list($integration, $userId) = explode('__', $params['id']);
|
||||
|
||||
if ($this->getUser()->id != $userId && !$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
$entity = $this->getEntityManager()->getEntity('ExternalAccount', $params['id']);
|
||||
return $entity->toArray();
|
||||
return $this->getRecordService()->read($params['id'])->getValueMap();
|
||||
}
|
||||
|
||||
public function actionUpdate($params, $data, $request)
|
||||
|
||||
@@ -69,11 +69,13 @@ class ClientManager
|
||||
$externalAccountEntity = $this->clientMap[$hash]['externalAccountEntity'];
|
||||
$externalAccountEntity->set('accessToken', $data['accessToken']);
|
||||
$externalAccountEntity->set('tokenType', $data['tokenType']);
|
||||
$externalAccountEntity->set('expiresAt', $data['expiresAt'] ?? null);
|
||||
|
||||
$copy = $this->getEntityManager()->getEntity('ExternalAccount', $externalAccountEntity->id);
|
||||
if ($copy) {
|
||||
$copy->set('accessToken', $data['accessToken']);
|
||||
$copy->set('tokenType', $data['tokenType']);
|
||||
$copy->set('expiresAt', $data['expiresAt'] ?? null);
|
||||
$this->getEntityManager()->saveEntity($copy, ['isTokenRenewal' => true]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
|
||||
namespace Espo\Core\ExternalAccount\Clients;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
use \Espo\Core\ExternalAccount\OAuth2\Client;
|
||||
use Espo\Core\ExternalAccount\OAuth2\Client;
|
||||
|
||||
abstract class OAuth2Abstract implements IClient
|
||||
{
|
||||
@@ -39,7 +39,7 @@ abstract class OAuth2Abstract implements IClient
|
||||
|
||||
protected $manager = null;
|
||||
|
||||
protected $paramList = array(
|
||||
protected $paramList = [
|
||||
'endpoint',
|
||||
'tokenEndpoint',
|
||||
'clientId',
|
||||
@@ -48,7 +48,8 @@ abstract class OAuth2Abstract implements IClient
|
||||
'accessToken',
|
||||
'refreshToken',
|
||||
'redirectUri',
|
||||
);
|
||||
'expiresAt',
|
||||
];
|
||||
|
||||
protected $clientId = null;
|
||||
|
||||
@@ -60,7 +61,9 @@ abstract class OAuth2Abstract implements IClient
|
||||
|
||||
protected $redirectUri = null;
|
||||
|
||||
public function __construct($client, array $params = array(), $manager = null)
|
||||
protected $expiresAt = null;
|
||||
|
||||
public function __construct($client, array $params = [], $manager = null)
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
@@ -103,6 +106,25 @@ abstract class OAuth2Abstract implements IClient
|
||||
}
|
||||
}
|
||||
|
||||
protected function getAccessTokenDataFromResponseResult($result)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
$data['accessToken'] = $result['access_token'];
|
||||
$data['tokenType'] = $result['token_type'];
|
||||
|
||||
$data['expiresAt'] = null;
|
||||
|
||||
if (isset($result['expires_in']) && is_numeric($result['expires_in'])) {
|
||||
$data['expiresAt'] = (new \DateTime())
|
||||
->modify('+' . $result['expires_in'] . ' seconds')
|
||||
->modify('-1 seconds')
|
||||
->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getAccessTokenFromAuthorizationCode($code)
|
||||
{
|
||||
$r = $this->client->getAccessToken($this->getParam('tokenEndpoint'), Client::GRANT_TYPE_AUTHORIZATION_CODE, [
|
||||
@@ -111,15 +133,16 @@ abstract class OAuth2Abstract implements IClient
|
||||
]);
|
||||
|
||||
if ($r['code'] == 200) {
|
||||
$data = [];
|
||||
if (!empty($r['result'])) {
|
||||
$data['accessToken'] = $r['result']['access_token'];
|
||||
$data['tokenType'] = $r['result']['token_type'];
|
||||
$data = $this->getAccessTokenDataFromResponseResult($r['result']);
|
||||
|
||||
$data['refreshToken'] = $r['result']['refresh_token'];
|
||||
|
||||
return $data;
|
||||
} else {
|
||||
$GLOBALS['log']->debug("OAuth getAccessTokenFromAuthorizationCode; Response: " . json_encode($r));
|
||||
return null;
|
||||
}
|
||||
return $data;
|
||||
} else {
|
||||
$GLOBALS['log']->debug("OAuth getAccessTokenFromAuthorizationCode; Response: " . json_encode($r));
|
||||
}
|
||||
@@ -193,15 +216,13 @@ abstract class OAuth2Abstract implements IClient
|
||||
protected function refreshToken()
|
||||
{
|
||||
if (!empty($this->refreshToken)) {
|
||||
$r = $this->client->getAccessToken($this->getParam('tokenEndpoint'), Client::GRANT_TYPE_REFRESH_TOKEN, array(
|
||||
$r = $this->client->getAccessToken($this->getParam('tokenEndpoint'), Client::GRANT_TYPE_REFRESH_TOKEN, [
|
||||
'refresh_token' => $this->refreshToken,
|
||||
));
|
||||
]);
|
||||
if ($r['code'] == 200) {
|
||||
if (is_array($r['result'])) {
|
||||
if (!empty($r['result']['access_token'])) {
|
||||
$data = array();
|
||||
$data['accessToken'] = $r['result']['access_token'];
|
||||
$data['tokenType'] = $r['result']['token_type'];
|
||||
$data = $this->getAccessTokenDataFromResponseResult($r['result']);
|
||||
|
||||
$this->setParams($data);
|
||||
$this->afterTokenRefreshed($data);
|
||||
@@ -209,6 +230,11 @@ abstract class OAuth2Abstract implements IClient
|
||||
}
|
||||
}
|
||||
}
|
||||
$GLOBALS['log']->notice("Oauth: Refreshing token failed for client {$this->clientId}: " . json_encode($r));
|
||||
} else {
|
||||
$GLOBALS['log']->notice(
|
||||
"Oauth: Could not refresh token for client {$this->clientId}, because refreshToken is empty.");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,21 +243,20 @@ abstract class OAuth2Abstract implements IClient
|
||||
if ($r['code'] == 401 && !empty($r['result'])) {
|
||||
$result = $r['result'];
|
||||
if (strpos($r['header'], 'error=invalid_token') !== false) {
|
||||
return array(
|
||||
return [
|
||||
'action' => 'refreshToken'
|
||||
);
|
||||
];
|
||||
} else {
|
||||
return array(
|
||||
return [
|
||||
'action' => 'renew'
|
||||
);
|
||||
];
|
||||
}
|
||||
} else if ($r['code'] == 400 && !empty($r['result'])) {
|
||||
if ($r['result']['error'] == 'invalid_token') {
|
||||
return array(
|
||||
return [
|
||||
'action' => 'refreshToken'
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ class Client
|
||||
|
||||
protected $accessToken = null;
|
||||
|
||||
protected $expiresAt = null;
|
||||
|
||||
protected $authType = self::AUTH_TYPE_URI;
|
||||
|
||||
protected $tokenType = self::TOKEN_TYPE_URI;
|
||||
@@ -72,9 +74,9 @@ class Client
|
||||
|
||||
protected $certificateFile = null;
|
||||
|
||||
protected $curlOptions = array();
|
||||
protected $curlOptions = [];
|
||||
|
||||
public function __construct(array $params = array())
|
||||
public function __construct(array $params = [])
|
||||
{
|
||||
if (!extension_loaded('curl')) {
|
||||
throw new \Exception('CURL extension not found.');
|
||||
@@ -121,12 +123,17 @@ class Client
|
||||
$this->tokenType = $tokenType;
|
||||
}
|
||||
|
||||
public function setExpiresAt($value)
|
||||
{
|
||||
$this->expiresAt = $value;
|
||||
}
|
||||
|
||||
public function setAccessTokenSecret($accessTokenSecret)
|
||||
{
|
||||
$this->accessTokenSecret = $accessTokenSecret;
|
||||
}
|
||||
|
||||
public function request($url, $params = null, $httpMethod = self::HTTP_METHOD_GET, array $httpHeaders = array())
|
||||
public function request($url, $params = null, $httpMethod = self::HTTP_METHOD_GET, array $httpHeaders = [])
|
||||
{
|
||||
if ($this->accessToken) {
|
||||
switch ($this->tokenType) {
|
||||
@@ -148,7 +155,7 @@ class Client
|
||||
return $this->execute($url, $params, $httpMethod, $httpHeaders);
|
||||
}
|
||||
|
||||
private function execute($url, $params = null, $httpMethod, array $httpHeaders = array())
|
||||
private function execute($url, $params = null, $httpMethod, array $httpHeaders = [])
|
||||
{
|
||||
$curlOptions = array(
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
@@ -243,7 +250,7 @@ class Client
|
||||
{
|
||||
$params['grant_type'] = $grantType;
|
||||
|
||||
$httpHeaders = array();
|
||||
$httpHeaders = [];
|
||||
switch ($this->tokenType) {
|
||||
case self::AUTH_TYPE_URI:
|
||||
case self::AUTH_TYPE_FORM:
|
||||
@@ -261,4 +268,3 @@ class Client
|
||||
return $this->execute($url, $params, self::HTTP_METHOD_POST, $httpHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
|
||||
namespace Espo\Services;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
use \Espo\Core\Exceptions\Forbidden;
|
||||
use \Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class ExternalAccount extends Record
|
||||
{
|
||||
@@ -92,6 +92,7 @@ class ExternalAccount extends Record
|
||||
$entity->clear('accessToken');
|
||||
$entity->clear('refreshToken');
|
||||
$entity->clear('tokenType');
|
||||
$entity->clear('expiresAt');
|
||||
foreach ($result as $name => $value) {
|
||||
$entity->set($name, $value);
|
||||
}
|
||||
@@ -109,4 +110,29 @@ class ExternalAccount extends Record
|
||||
throw new Error("Could not load client for {$integration}.");
|
||||
}
|
||||
}
|
||||
|
||||
public function read($id)
|
||||
{
|
||||
list($integration, $userId) = explode('__', $id);
|
||||
|
||||
if ($this->getUser()->id != $userId && !$this->getUser()->isAdmin()) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
$entity = $this->getEntityManager()->getEntity('ExternalAccount', $id);
|
||||
|
||||
if (!$entity) throw new NotFoundSilent("Record does not exist.");
|
||||
|
||||
list($integration, $id) = explode('__', $entity->id);
|
||||
|
||||
$externalAccountSecretAttributeList = $this->getMetadata()->get(
|
||||
['integrations', $integration, 'externalAccountSecretAttributeList']) ?? [];
|
||||
|
||||
foreach ($externalAccountSecretAttributeList as $a) {
|
||||
$entity->clear($a);
|
||||
}
|
||||
|
||||
return $entity;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user