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>
This commit is contained in:
Aina Sitraka
2023-10-10 23:22:23 +03:00
committed by GitHub
parent be9a6b3ed3
commit 529a95ecfa
27 changed files with 1757 additions and 1595 deletions

View File

@@ -13,5 +13,5 @@ module.exports = {
setupDir: _root + 'tests/setup/node.js',
karmaConf: _root + 'config/karma.conf.js',
// change this version when you change JS file for lazy loading
assetFileVersion: 93
assetFileVersion: 94
};

View File

@@ -96,7 +96,7 @@ return /******/ (function(modules) { // webpackBootstrap
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.src = __webpack_require__.p + "lazy-" + ({}[chunkId]||chunkId) + ".js?v=93";
/******/ script.src = __webpack_require__.p + "lazy-" + ({}[chunkId]||chunkId) + ".js?v=94";
/******/ var timeout = setTimeout(onScriptComplete, 120000);
/******/ script.onerror = script.onload = onScriptComplete;
/******/ function onScriptComplete() {

View File

@@ -96,7 +96,7 @@ return /******/ (function(modules) { // webpackBootstrap
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.src = __webpack_require__.p + "lazy-" + ({}[chunkId]||chunkId) + ".min.js?v=93";
/******/ script.src = __webpack_require__.p + "lazy-" + ({}[chunkId]||chunkId) + ".min.js?v=94";
/******/ var timeout = setTimeout(onScriptComplete, 120000);
/******/ script.onerror = script.onload = onScriptComplete;
/******/ function onScriptComplete() {

View File

@@ -91,7 +91,7 @@
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.src = __webpack_require__.p + "lazy-" + ({}[chunkId]||chunkId) + ".js?v=93";
/******/ script.src = __webpack_require__.p + "lazy-" + ({}[chunkId]||chunkId) + ".js?v=94";
/******/ var timeout = setTimeout(onScriptComplete, 120000);
/******/ script.onerror = script.onload = onScriptComplete;
/******/ function onScriptComplete() {

View File

@@ -91,7 +91,7 @@
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.src = __webpack_require__.p + "lazy-" + ({}[chunkId]||chunkId) + ".min.js?v=93";
/******/ script.src = __webpack_require__.p + "lazy-" + ({}[chunkId]||chunkId) + ".min.js?v=94";
/******/ var timeout = setTimeout(onScriptComplete, 120000);
/******/ script.onerror = script.onload = onScriptComplete;
/******/ function onScriptComplete() {

View File

@@ -11528,11 +11528,13 @@ var workzone = function workzone(services) {
},
dataType: 'json',
success: function success(data) {
if (data.success) {
setTimeout(function () {
getPublicationAssetsList(publicationId, exposeName, assetsContainer, 1);
}, 6000);
console.log(data.message);
} else {
(0, _jquery2.default)('.refresh-list').trigger('click');
}
}
});
}

View File

@@ -11528,11 +11528,13 @@ var workzone = function workzone(services) {
},
dataType: 'json',
success: function success(data) {
if (data.success) {
setTimeout(function () {
getPublicationAssetsList(publicationId, exposeName, assetsContainer, 1);
}, 6000);
console.log(data.message);
} else {
(0, _jquery2.default)('.refresh-list').trigger('click');
}
}
});
}

View File

@@ -1641,12 +1641,15 @@ const workzone = (services) => {
},
dataType: 'json',
success: function (data) {
if (data.success) {
setTimeout(function () {
getPublicationAssetsList(publicationId, exposeName, assetsContainer, 1);
}
, 6000);
} else {
$('.refresh-list').trigger('click');
}
console.log(data.message);
}
});
}

View File

@@ -28,7 +28,7 @@ class PSAdminController extends Controller
{
$exposeConfiguration = $app['conf']->get(['phraseanet-service', 'expose-service'], null);
$form = $app->form(new PSExposeConfigurationType(), $exposeConfiguration);
$form = $app->form(new PSExposeConfigurationType($this->app), $exposeConfiguration);
$form->handleRequest($request);

View File

@@ -41,7 +41,6 @@ class PSExposeController extends Controller
$proxyConfig = new NetworkProxiesConfiguration($this->app['conf']);
$clientOptions = [
'base_uri' => $exposeConfiguration['auth_base_uri'],
'http_errors' => false,
'verify' => $exposeConfiguration['verify_ssl']
];
@@ -49,14 +48,7 @@ class PSExposeController extends Controller
$oauthClient = $proxyConfig->getClientWithOptions($clientOptions);
try {
$response = $oauthClient->post('/oauth/v2/token', [
'json' => [
'client_id' => $exposeConfiguration['auth_client_id'],
'client_secret' => $exposeConfiguration['auth_client_secret'],
'grant_type' => 'password',
'username' => $request->request->get('auth-username'),
'password' => $request->request->get('auth-password') ]
]);
$response = $this->getTokenByPassword($oauthClient, $exposeConfiguration, $request->request->get('auth-username'), $request->request->get('auth-password'));
} catch(\Exception $e) {
return $this->app->json([
'success' => false,
@@ -84,7 +76,21 @@ class PSExposeController extends Controller
$session = $this->getSession();
$passSessionName = $this->getPassSessionName($request->request->get('exposeName'));
$session->set($passSessionName, $tokenBody['access_token']);
if (isset($tokenBody['refresh_expires_in'])) {
$passSessionNameValue = [
'access_token' => $tokenBody['access_token'],
'expires_at' => time() + $tokenBody['expires_in'],
'refresh_token'=> $tokenBody['refresh_token'],
'refresh_expires_at' => time() + $tokenBody['refresh_expires_in']
];
} else {
$passSessionNameValue = [
'access_token' => $tokenBody['access_token'],
'expires_at' => time() + $tokenBody['expires_in'],
];
}
$session->set($passSessionName, $passSessionNameValue);
$loginSessionName = $this->getLoginSessionName($request->request->get('exposeName'));
$session->set($loginSessionName, $request->request->get('auth-username'));
@@ -200,8 +206,9 @@ class PSExposeController extends Controller
if (!$session->has($passSessionName) && $providerId != null) {
try {
$provider = $this->getAuthenticationProviders()->get($providerId);
if ($provider->getType() == 'PsAuth') {
$session->set($passSessionName, $provider->getAccessToken());
if ($provider->getType() == 'PsAuth' && $exposeConfiguration['auth_provider_name'] == $providerId) {
$session->set($passSessionName, ['access_token' => $provider->getAccessToken()]);
$session->set($this->getLoginSessionName($exposeName), $provider->getUserName());
}
} catch(\Exception $e) {
@@ -903,9 +910,26 @@ class PSExposeController extends Controller
]);
}
$config = $this->getExposeConfiguration($exposeName);
// used to set or refresh token session
$accessToken = $this->getAndSaveToken($exposeName);
$this->getEventDispatcher()->dispatch(WorkerEvents::EXPOSE_UPLOAD_ASSETS, new ExposeUploadEvent($lst, $exposeName, $publicationId, $accessToken));
if (empty($accessToken)) {
return $app->json([
'success' => false,
'message' => "Do not have access token!"
]);
}
$accessTokenInfo = [];
if ($config['connection_kind'] == 'password') {
$accessTokenInfo = $this->getSession()->get($this->getPassSessionName($exposeName));
} elseif($config['connection_kind'] == 'client_credentials') {
$accessTokenInfo = $this->getSession()->get($this->getCredentialSessionName($exposeName));
}
$this->getEventDispatcher()->dispatch(WorkerEvents::EXPOSE_UPLOAD_ASSETS, new ExposeUploadEvent($lst, $exposeName, $publicationId, $accessTokenInfo));
return $app->json([
'success' => true,
@@ -1286,6 +1310,12 @@ class PSExposeController extends Controller
return 'password_access_token_' . $expose_name;
}
private function getCredentialSessionName($exposeName)
{
$expose_name = str_replace(' ', '_', $exposeName);
return 'credential_access_token_' . $expose_name;
}
/**
* Get login session name
*
@@ -1311,46 +1341,123 @@ class PSExposeController extends Controller
$session = $this->getSession();
$passSessionName = $this->getPassSessionName($exposeName);
$expose_name = str_replace(' ', '_', $exposeName);
$credentialSessionName = 'credential_access_token_'.$expose_name;
$accessToken = '';
if ($config['connection_kind'] == 'password') {
$accessToken = $session->get($passSessionName);
} elseif ($config['connection_kind'] == 'client_credentials') {
if ($session->has($credentialSessionName)) {
$accessToken = $session->get($credentialSessionName);
} else {
$proxyConfig = new NetworkProxiesConfiguration($this->app['conf']);
$oauthClient = $proxyConfig->getClientWithOptions([
'verify' => $config['verify_ssl'],
]);
$response = $oauthClient->post($config['expose_base_uri'] . '/oauth/v2/token', [
'json' => [
'client_id' => $config['expose_client_id'],
'client_secret' => $config['expose_client_secret'],
$credentialSessionName = $this->getCredentialSessionName($exposeName);
$accessToken = '';
if ($config['connection_kind'] == 'password') {
$tokenInfo = $session->get($passSessionName);
if (!isset($tokenInfo['expires_at'])) {
$accessToken = $tokenInfo['access_token'];
} elseif (is_array($tokenInfo) && $tokenInfo['expires_at'] > time()) {
$accessToken = $tokenInfo['access_token'];
} elseif (is_array($tokenInfo) && $tokenInfo['expires_at'] <= time() && $tokenInfo['refresh_expires_at'] > time()) {
$resToken = $this->refreshToken($oauthClient, $config, $tokenInfo['refresh_token']);
if ($resToken->getStatusCode() !== 200) {
throw new \Exception("Error when get refresh token with status code: " . $resToken->getStatusCode());
}
$refreshtokenBody = $resToken->getBody()->getContents();
$refreshtokenBody = json_decode($refreshtokenBody,true);
if (isset($refreshtokenBody['refresh_expires_in'])) {
$passSessionNameValue = [
'access_token' => $refreshtokenBody['access_token'],
'expires_at' => time() + $refreshtokenBody['expires_in'],
'refresh_token'=> $refreshtokenBody['refresh_token'],
'refresh_expires_at' => time() + $refreshtokenBody['refresh_expires_in']
];
} else {
$passSessionNameValue = [
'access_token' => $refreshtokenBody['access_token'],
'expires_at' => time() + $refreshtokenBody['expires_in'],
];
}
$session->set($passSessionName, $passSessionNameValue);
$accessToken = $refreshtokenBody['access_token'];
} else {
$session->remove($passSessionName);
}
} elseif ($config['connection_kind'] == 'client_credentials') {
if ($session->has($credentialSessionName)) {
$tokenInfoCredential = $session->get($credentialSessionName);
if (!isset($tokenInfoCredential['expires_at'])) {
$accessToken = $tokenInfoCredential['access_token'];
} elseif (is_array($tokenInfoCredential) && $tokenInfoCredential['expires_at'] > time()) {
$accessToken = $tokenInfoCredential['access_token'];
} else {
$accessToken = $this->getTokenByCredential($oauthClient, $config, $credentialSessionName);
}
} else {
$accessToken = $this->getTokenByCredential($oauthClient, $config, $credentialSessionName);
}
}
return $accessToken;
}
private function getTokenByCredential(Client $oauthClient, array $exposeConfiguration, $credentialSessionName)
{
$session = $this->getSession();
$response = $oauthClient->post($exposeConfiguration['oauth_token_uri'] , [
'form_params' => [
'client_id' => $exposeConfiguration['expose_client_id'],
'client_secret' => $exposeConfiguration['expose_client_secret'],
'grant_type' => 'client_credentials',
'scope' => 'publish'
]
]);
if ($response->getStatusCode() !== 200) {
return null;
throw new \Exception("Error when get credential token with status code: " . $response->getStatusCode());
}
$tokenBody = $response->getBody()->getContents();
$tokenBody = json_decode($tokenBody,true);
$session->set($credentialSessionName, $tokenBody['access_token']);
$credentialSessionNameValue = [
'access_token' => $tokenBody['access_token'],
'expires_at' => time() + $tokenBody['expires_in'],
];
$accessToken = $tokenBody['access_token'];
}
$session->set($credentialSessionName, $credentialSessionNameValue);
return $tokenBody['access_token'];
}
return $accessToken;
private function getTokenByPassword(Client $oauthClient, array $exposeConfiguration, $username, $password)
{
return $oauthClient->post($exposeConfiguration['oauth_token_uri'], [
'form_params' => [
'client_id' => $exposeConfiguration['auth_client_id'],
'client_secret' => $exposeConfiguration['auth_client_secret'],
'grant_type' => 'password',
'username' => $username,
'password' => $password
]
]);
}
private function refreshToken(Client $oauthClient, array $exposeConfiguration, $refreshToken)
{
return $oauthClient->post($exposeConfiguration['oauth_token_uri'], [
'form_params' => [
'client_id' => $exposeConfiguration['auth_client_id'],
'client_secret' => $exposeConfiguration['auth_client_secret'],
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken
]
]);
}
private function postPublication(Client $exposeClient, $token, $publicationData)

View File

@@ -2,6 +2,7 @@
namespace Alchemy\Phrasea\PhraseanetService\Form;
use Silex\Application;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\DataMapperInterface;
use Symfony\Component\Form\Exception;
@@ -12,6 +13,13 @@ use Symfony\Component\Form\FormInterface;
class PSExposeConfigurationType extends AbstractType implements DataMapperInterface
{
private $app;
public function __construct(Application $app)
{
$this->app = $app;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
@@ -26,7 +34,7 @@ class PSExposeConfigurationType extends AbstractType implements DataMapperInterf
])
->add('exposes', CollectionType::class, [
'label' => false,
'entry_type' => PSExposeConnectionType::class,
'entry_type' => new PSExposeConnectionType($this->app),
'prototype' => true,
'allow_add' => true,
'allow_delete' => true,

View File

@@ -2,16 +2,24 @@
namespace Alchemy\Phrasea\PhraseanetService\Form;
use Silex\Application;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class PSExposeConnectionType extends AbstractType
{
private $app;
public function __construct(Application $app)
{
$this->app = $app;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
@@ -36,6 +44,13 @@ class PSExposeConnectionType extends AbstractType
'password' => 'password'
]
])
->add('auth_provider_name', ChoiceType::class, [
'label' => 'admin:phrasea-service-setting:tab:expose:: auth provider name with type ps-auth',
'required' => false,
'choice_list' => new ArrayChoiceList(
$this->getEligibleProvider()
)
])
->add('expose_name', TextType::class, [
'label' => 'admin:phrasea-service-setting:tab:expose:: Name',
'attr' => [
@@ -68,11 +83,11 @@ class PSExposeConnectionType extends AbstractType
'class' => 'input-xxlarge'
]
])
->add('auth_base_uri', TextType::class, [
'label' => 'admin:phrasea-service-setting:tab:expose:: Auth Base Uri ',
->add('oauth_token_uri', TextType::class, [
'label' => 'admin:phrasea-service-setting:tab:expose:: OAuth token URI ',
'required' => false,
'attr' => [
'class' => 'input-xxlarge'
'class' => 'input-xxlarge',
]
])
->add('auth_client_secret', TextType::class, [
@@ -96,4 +111,16 @@ class PSExposeConnectionType extends AbstractType
{
return 'ps_expose_connection';
}
private function getEligibleProvider()
{
$values = array_keys(
array_filter($this->app['conf']->get(['authentication', 'providers'], []),
function ($provider) {
return ($provider['type'] == 'ps-auth' || $provider['type'] == 'PsAuth');
})
);
return array_combine($values, $values);
}
}

View File

@@ -62,7 +62,7 @@ class PhraseanetExtension extends \Twig_Extension
{
return [
// change this version when you change JS file to force the navigation to reload js file
'assetFileVersion' => 93
'assetFileVersion' => 94
];
}

View File

@@ -9,14 +9,14 @@ class ExposeUploadEvent extends SfEvent
private $lst;
private $exposeName;
private $publicationId;
private $accessToken;
private $accessTokenInfo;
public function __construct($lst, $exposeName, $publicationId, $accessToken)
public function __construct($lst, $exposeName, $publicationId, $accessTokenInfo)
{
$this->lst = $lst;
$this->exposeName = $exposeName;
$this->publicationId = $publicationId;
$this->accessToken = $accessToken;
$this->accessTokenInfo = $accessTokenInfo;
}
public function getLst()
@@ -34,8 +34,8 @@ class ExposeUploadEvent extends SfEvent
return $this->publicationId;
}
public function getAccessToken()
public function getAccessTokenInfo()
{
return $this->accessToken;
return $this->accessTokenInfo;
}
}

View File

@@ -32,7 +32,7 @@ class ExposeSubscriber implements EventSubscriberInterface
'databoxId' => (int) $basrec[0],
'exposeName' => $event->getExposeName(),
'publicationId' => $event->getPublicationId(),
'accessToken' => $event->getAccessToken()
'accessTokenInfo' => $event->getAccessTokenInfo()
]
];

View File

@@ -22,6 +22,9 @@ class ExposeUploadWorker implements WorkerInterface
private $app;
private $exposeConfiguration;
private $accessTokenInfo;
public function __construct($app)
{
$this->app = $app;
@@ -84,14 +87,15 @@ class ExposeUploadWorker implements WorkerInterface
}
try {
$exposeConfiguration = $this->app['conf']->get(['phraseanet-service', 'expose-service', 'exposes'], []);
$exposeConfiguration = $exposeConfiguration[$payload['exposeName']];
$this->accessTokenInfo = $payload['accessTokenInfo'];
$this->exposeConfiguration = $this->app['conf']->get(['phraseanet-service', 'expose-service', 'exposes'], []);
$this->exposeConfiguration = $this->exposeConfiguration[$payload['exposeName']];
$proxyConfig = new NetworkProxiesConfiguration($this->app['conf']);
$clientOptions = [
'base_uri' => $exposeConfiguration['expose_base_uri'],
'base_uri' => $this->exposeConfiguration['expose_base_uri'],
'http_errors' => false,
'verify' => $exposeConfiguration['verify_ssl']
'verify' => $this->exposeConfiguration['verify_ssl']
];
// add proxy in each request if defined in configuration
@@ -105,7 +109,7 @@ class ExposeUploadWorker implements WorkerInterface
$phraseanetLocalId = $this->app['conf']->get(['phraseanet-service', 'phraseanet_local_id']);
// get mapping if exist
$clientAnnotationProfile = $this->getClientAnnotationProfile($exposeClient, $payload['accessToken'], $payload['publicationId']);
$clientAnnotationProfile = $this->getClientAnnotationProfile($exposeClient, $payload['publicationId']);
$exposeFieldMappingName = $phraseanetLocalId . '_field_mapping';
$fieldMapping = !empty($clientAnnotationProfile[$exposeFieldMappingName]) ? $clientAnnotationProfile[$exposeFieldMappingName] : [];
@@ -247,9 +251,11 @@ class ExposeUploadWorker implements WorkerInterface
$requestBody['webVTT'] = $webVTT;
}
$token = $this->getToken();
$response = $exposeClient->post('/assets', [
'headers' => [
'Authorization' => 'Bearer ' . $payload['accessToken']
'Authorization' => 'Bearer ' . $token
],
'json' => $requestBody
]);
@@ -263,7 +269,7 @@ class ExposeUploadWorker implements WorkerInterface
$assetsResponse = json_decode($response->getBody(),true);
$uploadUrl = $proxyConfig->getClientWithOptions(['verify' => $exposeConfiguration['verify_ssl']]);
$uploadUrl = $proxyConfig->getClientWithOptions(['verify' => $this->exposeConfiguration['verify_ssl']]);
$uploadUrl->put($assetsResponse['uploadURL'], [
'headers' => [
'Content-Type' => 'application/binary'
@@ -304,7 +310,6 @@ class ExposeUploadWorker implements WorkerInterface
if ($record->has_subdef($phraseanetSubdef) && $record->get_subdef($phraseanetSubdef)->is_physically_present()) {
$this->postSubDefinition(
$exposeClient,
$payload['accessToken'],
$assetsResponse['id'],
$record->get_subdef($phraseanetSubdef),
$subdefName,
@@ -358,16 +363,16 @@ class ExposeUploadWorker implements WorkerInterface
$this->finishedJob($workerRunningJob, $em, WorkerRunningJob::ERROR);
return;
return;
}
// tell that the upload is finished
$this->finishedJob($workerRunningJob, $em);
}
private function getClientAnnotationProfile(Client $exposeClient, $accessToken, $publicationId)
private function getClientAnnotationProfile(Client $exposeClient, $publicationId)
{
$accessToken = $this->getToken();
$resPublication = $exposeClient->get('/publications/'.$publicationId , [
'headers' => [
'Authorization' => 'Bearer '. $accessToken,
@@ -385,8 +390,10 @@ class ExposeUploadWorker implements WorkerInterface
return $clientAnnotationProfile;
}
private function postSubDefinition(Client $exposeClient, $token, $assetId, \media_subdef $subdef, $subdefName, $isPreview = false, $isThumbnail = false, $isPoster = false)
private function postSubDefinition(Client $exposeClient, $assetId, \media_subdef $subdef, $subdefName, $isPreview = false, $isThumbnail = false, $isPoster = false)
{
$token = $this->getToken();
$requestBody = [
'asset_id' => $assetId,
'name' => $subdefName,
@@ -450,4 +457,83 @@ class ExposeUploadWorker implements WorkerInterface
$em->rollback();
}
}
private function getToken()
{
$proxyConfig = new NetworkProxiesConfiguration($this->app['conf']);
$clientOptions = [
'http_errors' => false,
'verify' => $this->exposeConfiguration['verify_ssl']
];
$oauthClient = $proxyConfig->getClientWithOptions($clientOptions);
if ($this->exposeConfiguration['connection_kind'] == 'password') {
if (!isset($this->accessTokenInfo['expires_at'])) {
return $this->accessTokenInfo['access_token'];
} elseif ($this->accessTokenInfo['expires_at'] > time() && $this->accessTokenInfo['refresh_expires_at'] > time()) {
return $this->accessTokenInfo['access_token'];
} elseif ($this->accessTokenInfo['expires_at'] <= time() && $this->accessTokenInfo['refresh_expires_at'] > time()) {
$resToken = $oauthClient->post($this->exposeConfiguration['oauth_token_uri'], [
'form_params' => [
'client_id' => $this->exposeConfiguration['auth_client_id'],
'client_secret' => $this->exposeConfiguration['auth_client_secret'],
'grant_type' => 'refresh_token',
'refresh_token' => $this->accessTokenInfo['refresh_token']
]
]);
if ($resToken->getStatusCode() !== 200) {
return null;
}
$refreshtokenBody = $resToken->getBody()->getContents();
$refreshtokenBody = json_decode($refreshtokenBody, true);
// update the access token information
$this->accessTokenInfo = [
'access_token' => $refreshtokenBody['access_token'],
'expires_at' => time() + $refreshtokenBody['expires_in'],
'refresh_token' => $refreshtokenBody['refresh_token'],
'refresh_expires_at' => time() + $refreshtokenBody['refresh_expires_in']
];
return $refreshtokenBody['access_token'];
} else {
return null;
}
} elseif ($this->exposeConfiguration['connection_kind'] == 'client_credentials') {
if (!isset($this->accessTokenInfo['expires_at'])) {
return $this->accessTokenInfo['access_token'];
} elseif ($this->accessTokenInfo['expires_at'] > time()) {
return $this->accessTokenInfo['access_token'];
} else {
$response = $oauthClient->post($this->exposeConfiguration['oauth_token_uri'], [
'form_params' => [
'client_id' => $this->exposeConfiguration['expose_client_id'],
'client_secret' => $this->exposeConfiguration['expose_client_secret'],
'grant_type' => 'client_credentials'
]
]);
if ($response->getStatusCode() !== 200) {
return null;
}
$refreshtokenBody = $response->getBody()->getContents();
$refreshtokenBody = json_decode($refreshtokenBody,true);
// update the access token information
$this->accessTokenInfo = [
'access_token' => $refreshtokenBody['access_token'],
'expires_at' => time() + $refreshtokenBody['expires_in'],
];
return $refreshtokenBody['access_token'];
}
}
}
}

View File

@@ -77,6 +77,12 @@ class PullAssetsWorker implements WorkerInterface
}
}
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'];

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2023-09-20T07:34:27Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
<file date="2023-10-04T11:58:26Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
<header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2023-09-20T07:34:42Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
<file date="2023-10-04T11:58:43Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
<header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2023-09-20T07:35:01Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
<file date="2023-10-04T11:59:05Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
<header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2023-09-20T07:35:23Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available">
<file date="2023-10-04T11:59:27Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available">
<header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>

View File

@@ -8,6 +8,10 @@
</div>
<div class="expose-config-block">
<div class="control-group">
{{ form_row(form.expose_name) }}
</div>
<div class="control-group alert alert-info">
{{ form_widget(form.activate_expose) }}
{{ form_label(form.activate_expose) }}
@@ -18,8 +22,9 @@
</div>
</div>
<div class="control-group">
{{ form_row(form.expose_name) }}
<div class="control-group auth-field" style="margin-bottom: 20px;">
{{ form_label(form.auth_provider_name) }}
{{ form_widget(form.auth_provider_name) }}
</div>
<div class="control-group" style="margin-bottom: 20px;">
@@ -44,7 +49,13 @@
</div>
<div class="control-group auth-field">
{{ form_row(form.auth_base_uri) }}
{{ form_label(form.oauth_token_uri) }}
<div style="margin-top: 10px; margin-bottom: 10px;">
expose v2 : https://api-auth.phrasea.local/oauth/v2/token
<br>
expose v3 : https://api-expose.ps-test.phrasea.fr/oauth/v2/token
</div>
{{ form_widget(form.oauth_token_uri) }}
</div>
<div class="control-group auth-field">
@@ -54,27 +65,6 @@
<div class="control-group auth-field">
{{ form_row(form.auth_client_id) }}
</div>
<div class="control-group auth-connection-field">
<div>
<span class="pull-left-btn">{{ 'admin:phrasea-service-setting:tab:expose:: add Mapping' | trans }}</span><input
type="button" class="btn btn-primary"
value="{{ 'admin:phrasea-service-setting:tab:expose:: Add mapping' | trans }}"></div>
</div>
<div class="control-group auth-connection-field">
<div>
<span class="pull-left-btn">{{ 'admin:phrasea-service-setting:tab:expose:: add user' | trans }}</span><input
type="button" class="btn btn-primary"
value="{{ 'admin:phrasea-service-setting:tab:expose:: Add user' | trans }}"></div>
</div>
<div class="expose-save-btn">
<p><input type="button" class="btn btn-primary btn-grey test-connection"
value="{{ 'admin:phrasea-service-setting:tab:expose:: connection test' | trans }}">
</p>
</div>
</div>
{% endmacro %}
@@ -99,7 +89,7 @@
</div>
</div>
<div id="expose-list" data-prototype="{{ _self.widget_prototype(form.exposes.vars.prototype)|e('html_attr') }}" style="height:800px;overflow-y:auto;">
<div id="expose-list" data-prototype="{{ _self.widget_prototype(form.exposes.vars.prototype)|e('html_attr') }}" style="overflow-y:auto;">
{% for expose_connection in form.exposes %}
{{ _self.widget_prototype(expose_connection) }}
{% endfor %}
@@ -129,6 +119,7 @@
collectionHolder.append(newExpose);
$("#expose-list" ).accordion('refresh');
$( "h3:last" ).trigger( "click" );
displayField($( "h3:last" ).next('.expose-block').find('.auth-connection'));
});
$('#expose-list').on('click', '.delete-expose', function () {
@@ -146,7 +137,8 @@
$("#expose-list" ).accordion(
{ event: "click",
active: false,
collapsible: true
collapsible: true,
heightStyle: "content"
}
);
@@ -162,12 +154,12 @@
switch (connectionKind.val()) {
case 'password':
exposeFields.addClass('hidden');
authFields.removeClass('hidden');
exposeFields.hide();
authFields.show();
break;
case 'client_credentials':
authFields.addClass('hidden');
exposeFields.removeClass('hidden');
authFields.hide();
exposeFields.show();
break;
}
}

View File

@@ -670,22 +670,11 @@
<div class="expose-header">
<div id="expose_sel" class="custom_select_dark" style="padding:10px;">
{% set expose_list = app['conf'].get(['phraseanet-service', 'expose-service', 'exposes']) %}
{% set providerId = app['session'].get('auth_provider.id') %}
{% if providerId is not null %}
{% set provider = app['authentication.providers'].get(providerId) %}
{% if provider.getType() == 'PsAuth' %}
{% set auth_base_url = provider.getOptions()['base-url'] | trim('/') %}
{% endif %}
{% endif %}
<select id="expose_list" name="expose_list" class="expose_list">
<option value="">{{ 'prod:expose:select expose' | trans }}</option>
{% for key in expose_list|keys %}
{% if (
(auth_base_url is defined and expose_list[key].auth_base_uri | trim('/') == auth_base_url)
or providerId is empty)
and expose_list[key].activate_expose %}
{% if expose_list[key].activate_expose %}
<option value="{{ key }}">{{ key }}</option>
{% endif %}
{% endfor %}