entityManager = $entityManager; $this->metadata = $metadata; $this->config = $config; $this->injectableFactory = $injectableFactory; } protected function getMetadata() { return $this->metadata; } protected function getEntityManager() { return $this->entityManager; } protected function getConfig() { return $this->config; } public function storeAccessToken($hash, $data) { if (!empty($this->clientMap[$hash]) && !empty($this->clientMap[$hash]['externalAccountEntity'])) { $externalAccountEntity = $this->clientMap[$hash]['externalAccountEntity']; $externalAccountEntity->set('accessToken', $data['accessToken']); $externalAccountEntity->set('tokenType', $data['tokenType']); $externalAccountEntity->set('expiresAt', $data['expiresAt'] ?? null); if ($data['refreshToken'] ?? null) { $externalAccountEntity->set('refreshToken', $data['refreshToken']); } $copy = $this->getEntityManager()->getEntity('ExternalAccount', $externalAccountEntity->id); if ($copy) { if (!$copy->get('enabled')) { throw new Error("External Account Client Manager: Account got disabled."); } $copy->set('accessToken', $data['accessToken']); $copy->set('tokenType', $data['tokenType']); $copy->set('expiresAt', $data['expiresAt'] ?? null); if ($data['refreshToken'] ?? null) { $copy->set('refreshToken', $data['refreshToken'] ?? null); } $this->getEntityManager()->saveEntity($copy, ['isTokenRenewal' => true]); } } } public function create(string $integration, string $userId) { $authMethod = $this->getMetadata()->get("integrations.{$integration}.authMethod"); $methodName = 'create' . ucfirst($authMethod); if (method_exists($this, $methodName)) { return $this->$methodName($integration, $userId); } if (!$this->injectableFactory) { throw new Error(); } $integrationEntity = $this->getEntityManager()->getEntity('Integration', $integration); $externalAccountEntity = $this->getEntityManager()->getEntity('ExternalAccount', $integration . '__' . $userId); if (!$externalAccountEntity) { throw new Error("External Account {$integration} not found for {$userId}"); } if (!$integrationEntity->get('enabled')) return null; if (!$externalAccountEntity->get('enabled')) return null; $className = $this->getMetadata()->get("integrations.{$integration}.clientClassName"); $client = $this->injectableFactory->createByClassName($className); $client->setup( $userId, $integrationEntity, $externalAccountEntity, $this ); $this->addToClientMap($client, $integrationEntity, $externalAccountEntity, $userId); return $client; } protected function createOAuth2(string $integration, string $userId) { $integrationEntity = $this->getEntityManager()->getEntity('Integration', $integration); $externalAccountEntity = $this->getEntityManager()->getEntity('ExternalAccount', $integration . '__' . $userId); $className = $this->getMetadata()->get("integrations.{$integration}.clientClassName"); $redirectUri = $this->getConfig()->get('siteUrl') . '?entryPoint=oauthCallback'; $redirectUriPath = $this->getMetadata()->get(['integrations', $integration, 'params', 'redirectUriPath']); if ($redirectUriPath) { $redirectUri = rtrim($this->getConfig()->get('siteUrl'), '/') . '/' . $redirectUriPath; } if (!$externalAccountEntity) { throw new Error("External Account {$integration} not found for {$userId}"); } if (!$integrationEntity->get('enabled')) { return null; } if (!$externalAccountEntity->get('enabled')) { return null; } $oauth2Client = new \Espo\Core\ExternalAccount\OAuth2\Client(); $params = [ 'endpoint' => $this->getMetadata()->get("integrations.{$integration}.params.endpoint"), 'tokenEndpoint' => $this->getMetadata()->get("integrations.{$integration}.params.tokenEndpoint"), 'clientId' => $integrationEntity->get('clientId'), 'clientSecret' => $integrationEntity->get('clientSecret'), 'redirectUri' => $redirectUri, 'accessToken' => $externalAccountEntity->get('accessToken'), 'refreshToken' => $externalAccountEntity->get('refreshToken'), 'tokenType' => $externalAccountEntity->get('tokenType'), 'expiresAt' => $externalAccountEntity->get('expiresAt'), ]; foreach (get_object_vars($integrationEntity->getValueMap()) as $k => $v) { if (array_key_exists($k, $params)) continue; if ($integrationEntity->hasAttribute($k)) continue; $params[$k] = $v; } $client = new $className($oauth2Client, $params, $this); $this->addToClientMap($client, $integrationEntity, $externalAccountEntity, $userId); return $client; } protected function addToClientMap($client, $integrationEntity, $externalAccountEntity, $userId) { $this->clientMap[spl_object_hash($client)] = array( 'client' => $client, 'userId' => $userId, 'integration' => $integrationEntity->id, 'integrationEntity' => $integrationEntity, 'externalAccountEntity' => $externalAccountEntity, ); } protected function getClientRecord($client) : \Espo\ORM\Entity { $data = $this->clientMap[spl_object_hash($client)]; if (!$data) { throw new Error("External Account Client Manager: Client not found in hash."); } return $data['externalAccountEntity']; } public function isClientLocked($client) : bool { $externalAccountEntity = $this->getClientRecord($client); $id = $externalAccountEntity->id; $e = $this->getEntityManager()->getRepository('ExternalAccount') ->select(['id', 'isLocked'])->where(['id' => $id])->findOne(); if (!$e) { throw new Error("External Account Client Manager: Client {$id} not found in DB."); } return $e->get('isLocked'); } public function lockClient($client) { $externalAccountEntity = $this->getClientRecord($client); $id = $externalAccountEntity->id; $e = $this->getEntityManager()->getRepository('ExternalAccount') ->select(['id', 'isLocked'])->where(['id' => $id])->findOne(); if (!$e) { throw new Error("External Account Client Manager: Client {$id} not found in DB."); } $e->set('isLocked', true); $this->getEntityManager()->saveEntity($e); } public function unlockClient($client) { $externalAccountEntity = $this->getClientRecord($client); $id = $externalAccountEntity->id; $e = $this->getEntityManager()->getRepository('ExternalAccount') ->select(['id', 'isLocked'])->where(['id' => $id])->findOne(); if (!$e) { throw new Error("External Account Client Manager: Client {$id} not found in DB."); } $e->set('isLocked', false); $this->getEntityManager()->saveEntity($e); } public function reFetchClient($client) { $externalAccountEntity = $this->getClientRecord($client); $id = $externalAccountEntity->id; $e = $this->getEntityManager()->getEntity('ExternalAccount', $id); if (!$e) { throw new Error("External Account Client Manager: Client {$id} not found in DB."); } $data = $e->getValueMap(); $externalAccountEntity->set($data); $client->setParams(get_object_vars($data)); } }