Files
Phraseanet/lib/Alchemy/Phrasea/WorkerManager/Worker/PullAssetsWorker.php
Aina Sitraka 529a95ecfa PHRAS-3921 prod - expose-cli - became compatible with Phrasea V3 keycloak and fix (#4384)
* expose cli phrasea v3

* retrocompatible with v2

* fix connection by idp

* remove placeholder

* some fix

* some fix

* fix

* fix auth from IDP

* list expose

---------

Co-authored-by: Nicolas Maillat <maillat@alchemy.fr>
2023-10-10 22:22:23 +02:00

190 lines
6.9 KiB
PHP

<?php
namespace Alchemy\Phrasea\WorkerManager\Worker;
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
use Alchemy\Phrasea\Model\Entities\WorkerRunningJob;
use Alchemy\Phrasea\Model\Repositories\WorkerRunningJobRepository;
use Alchemy\Phrasea\Utilities\NetworkProxiesConfiguration;
use Alchemy\Phrasea\WorkerManager\Queue\MessagePublisher;
use GuzzleHttp\Client;
class PullAssetsWorker implements WorkerInterface
{
private $messagePublisher;
private $conf;
/** @var WorkerRunningJobRepository $repoWorkerJob */
private $repoWorkerJob;
public function __construct(MessagePublisher $messagePublisher, PropertyAccess $conf, WorkerRunningJobRepository $repoWorkerJob)
{
$this->messagePublisher = $messagePublisher;
$this->conf = $conf;
$this->repoWorkerJob = $repoWorkerJob;
}
public function process(array $payload)
{
$configs = $this->conf->get(['phraseanet-service', 'uploader-service']);
if (isset($configs['pulled_target'])) {
$configs = $configs['pulled_target'];
} else {
$this->messagePublisher->pushLog("No pull target defined in configuration!");
return;
}
foreach ($configs as $targetName => $config) {
if (empty($config['pullmodeUri'])) {
$this->messagePublisher->pushLog("No pull mode uri given in this target : " . $targetName);
continue;
}
$verifySsl = isset($config['verify_ssl']) ? $config['verify_ssl'] : true ;
$proxyConfig = new NetworkProxiesConfiguration($this->conf);
$clientOptions = [
'http_errors' => false,
'verify' => $verifySsl
];
// add proxy in each request if defined in configuration
$uploaderClient = $proxyConfig->getClientWithOptions($clientOptions);
// if a token exist , use it
if (isset($config['assetToken'])) {
$res = $this->getCommits($uploaderClient, $config);
if ($res == null) {
return;
}
// if Unauthorized get a new token first
if ($res->getStatusCode() == 401) {
if (($config = $this->generateToken($uploaderClient, $config, $targetName)) === null) {
return;
};
$res = $this->getCommits($uploaderClient, $config);
}
} else { // if there is not a token , get one from the uploader service
if (($config = $this->generateToken($uploaderClient, $config, $targetName)) === null) {
return;
};
if (($res = $this->getCommits($uploaderClient, $config)) === null) {
return;
}
}
if ($res->getStatusCode() !== 200) {
$this->messagePublisher->pushLog("An error occurred when fetching commit: status-code " . $res->getStatusCode());
return;
}
$body = $res->getBody()->getContents();
$body = json_decode($body,true);
$commits = $body['hydra:member'];
foreach ($commits as $commit) {
// send only payload in ingest-queue if the commit is ack false and it is not being creating
if (!$commit['acknowledged'] && !$this->isCommitToBeCreating($commit['id'])) {
$this->messagePublisher->pushLog("A new commit found in the uploader ! commit_ID : ".$commit['id']);
// this is an uploader PULL mode
$payload = [
'message_type' => MessagePublisher::ASSETS_INGEST_TYPE,
'payload' => [
'assets' => array_map(function($asset) {
return str_replace('/assets/', '', $asset);
}, $commit['assets']),
'publisher' => $commit['userId'],
'commit_id' => $commit['id'],
'token' => $commit['token'],
'base_url' => $this->getBaseUriFromPullmodeUri($config['pullmodeUri']),
'type' => WorkerRunningJob::TYPE_PULL,
'verify_ssl'=> $verifySsl // to be used for AssetsIngestWorker and the createRecordWorker
]
];
$this->messagePublisher->publishMessage($payload, MessagePublisher::ASSETS_INGEST_TYPE);
}
}
}
}
/**
* @param Client $uploaderClient
* @param array $config
* @return \Psr\Http\Message\ResponseInterface|null
*/
private function getCommits(Client $uploaderClient, array $config)
{
// get only unacknowledged
try {
$res = $uploaderClient->get($config['pullmodeUri'] . '&acknowledged=false', [
'headers' => [
'Authorization' => 'Bearer '. $config['assetToken']
]
]);
} catch(\Exception $e) {
$this->messagePublisher->pushLog("An error occurred when fetching endpoint pullmode uri : " . $e->getMessage());
return null;
}
return $res;
}
/**
* @param Client $uploaderClient
* @param array $config
* @return array|null
*/
private function generateToken(Client $uploaderClient, array $config, $targetName)
{
$baseUri = $this->getBaseUriFromPullmodeUri($config['pullmodeUri']);
try {
$tokenBody = $uploaderClient->post($baseUri. '/oauth/v2/token', [
'json' => [
'client_id' => $config['clientId'],
'client_secret' => $config['clientSecret'],
'grant_type' => 'client_credentials',
'scope' => 'commit:list'
]
])->getBody()->getContents();
$tokenBody = json_decode($tokenBody,true);
} catch (\Exception $e) {
$this->messagePublisher->pushLog("An error occurred when fetching endpoint Token : " . $e->getMessage());
return null;
}
$this->conf->set(['phraseanet-service', 'uploader-service', 'pulled_target', $targetName, 'assetToken'], $tokenBody['access_token']);
return $this->conf->get(['phraseanet-service', 'uploader-service', 'pulled_target', $targetName]);
}
/**
* @param $commitId
* @return bool
*/
private function isCommitToBeCreating($commitId)
{
$res = $this->repoWorkerJob->findBy(['commitId' => $commitId, 'status' => WorkerRunningJob::RUNNING]);
return count($res) != 0;
}
private function getBaseUriFromPullmodeUri($pullmodeUri)
{
$result = parse_url($pullmodeUri);
return $result['scheme']."://".$result['host'];
}
}