Skip to content

Commit

Permalink
PHRAS-3921 prod - expose-cli - became compatible with Phrasea V3 keyc…
Browse files Browse the repository at this point in the history
…loak 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 <[email protected]>
  • Loading branch information
aynsix and nmaillat authored Oct 10, 2023
1 parent be9a6b3 commit 529a95e
Show file tree
Hide file tree
Showing 27 changed files with 1,756 additions and 1,594 deletions.
2 changes: 1 addition & 1 deletion Phraseanet-production-client/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
2 changes: 1 addition & 1 deletion Phraseanet-production-client/dist/authenticate.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion Phraseanet-production-client/dist/authenticate.min.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion Phraseanet-production-client/dist/commons.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion Phraseanet-production-client/dist/commons.min.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
12 changes: 7 additions & 5 deletions Phraseanet-production-client/dist/production.js
Original file line number Diff line number Diff line change
Expand Up @@ -11528,11 +11528,13 @@ var workzone = function workzone(services) {
},
dataType: 'json',
success: function success(data) {
setTimeout(function () {
getPublicationAssetsList(publicationId, exposeName, assetsContainer, 1);
}, 6000);

console.log(data.message);
if (data.success) {
setTimeout(function () {
getPublicationAssetsList(publicationId, exposeName, assetsContainer, 1);
}, 6000);
} else {
(0, _jquery2.default)('.refresh-list').trigger('click');
}
}
});
}
Expand Down
12 changes: 7 additions & 5 deletions Phraseanet-production-client/dist/production.min.js
Original file line number Diff line number Diff line change
Expand Up @@ -11528,11 +11528,13 @@ var workzone = function workzone(services) {
},
dataType: 'json',
success: function success(data) {
setTimeout(function () {
getPublicationAssetsList(publicationId, exposeName, assetsContainer, 1);
}, 6000);

console.log(data.message);
if (data.success) {
setTimeout(function () {
getPublicationAssetsList(publicationId, exposeName, assetsContainer, 1);
}, 6000);
} else {
(0, _jquery2.default)('.refresh-list').trigger('click');
}
}
});
}
Expand Down
13 changes: 8 additions & 5 deletions Phraseanet-production-client/src/components/ui/workzone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1641,12 +1641,15 @@ const workzone = (services) => {
},
dataType: 'json',
success: function (data) {
setTimeout(function(){
getPublicationAssetsList(publicationId, exposeName, assetsContainer, 1);
}
, 6000);
if (data.success) {
setTimeout(function () {
getPublicationAssetsList(publicationId, exposeName, assetsContainer, 1);
}
, 6000);
} else {
$('.refresh-list').trigger('click');
}

console.log(data.message);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function exposeAction(PhraseaApplication $app, Request $request)
{
$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);

Expand Down
187 changes: 147 additions & 40 deletions lib/Alchemy/Phrasea/PhraseanetService/Controller/PSExposeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,14 @@ public function authenticateAction(PhraseaApplication $app, Request $request)

$proxyConfig = new NetworkProxiesConfiguration($this->app['conf']);
$clientOptions = [
'base_uri' => $exposeConfiguration['auth_base_uri'],
'http_errors' => false,
'verify' => $exposeConfiguration['verify_ssl']
];

$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,
Expand Down Expand Up @@ -84,7 +76,21 @@ public function authenticateAction(PhraseaApplication $app, Request $request)
$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'));
Expand Down Expand Up @@ -200,8 +206,9 @@ public function listPublicationAction(PhraseaApplication $app, Request $request)
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) {
Expand Down Expand Up @@ -903,9 +910,26 @@ public function addPublicationAssetsAction(PhraseaApplication $app, Request $req
]);
}

$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,
Expand Down Expand Up @@ -1283,7 +1307,13 @@ private function getPassSessionName($exposeName)
{
$expose_name = str_replace(' ', '_', $exposeName);

return 'password_access_token_'.$expose_name;
return 'password_access_token_' . $expose_name;
}

private function getCredentialSessionName($exposeName)
{
$expose_name = str_replace(' ', '_', $exposeName);
return 'credential_access_token_' . $expose_name;
}

/**
Expand Down Expand Up @@ -1311,46 +1341,123 @@ private function getAndSaveToken($exposeName)
$session = $this->getSession();
$passSessionName = $this->getPassSessionName($exposeName);

$expose_name = str_replace(' ', '_', $exposeName);
$credentialSessionName = 'credential_access_token_'.$expose_name;
$proxyConfig = new NetworkProxiesConfiguration($this->app['conf']);
$oauthClient = $proxyConfig->getClientWithOptions([
'verify' => $config['verify_ssl'],
]);

$credentialSessionName = $this->getCredentialSessionName($exposeName);

$accessToken = '';
if ($config['connection_kind'] == 'password') {
$accessToken = $session->get($passSessionName);
$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)) {
$accessToken = $session->get($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 {
$proxyConfig = new NetworkProxiesConfiguration($this->app['conf']);
$accessToken = $this->getTokenByCredential($oauthClient, $config, $credentialSessionName);
}
}

$oauthClient = $proxyConfig->getClientWithOptions([
'verify' => $config['verify_ssl'],
]);
return $accessToken;
}

$response = $oauthClient->post($config['expose_base_uri'] . '/oauth/v2/token', [
'json' => [
'client_id' => $config['expose_client_id'],
'client_secret' => $config['expose_client_secret'],
'grant_type' => 'client_credentials',
'scope' => 'publish'
]
]);
private function getTokenByCredential(Client $oauthClient, array $exposeConfiguration, $credentialSessionName)
{
$session = $this->getSession();

if ($response->getStatusCode() !== 200) {
return null;
}
$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',
]
]);

if ($response->getStatusCode() !== 200) {
throw new \Exception("Error when get credential token with status code: " . $response->getStatusCode());
}

$tokenBody = $response->getBody()->getContents();
$tokenBody = $response->getBody()->getContents();

$tokenBody = json_decode($tokenBody,true);
$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 $accessToken;
return $tokenBody['access_token'];
}

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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -12,6 +13,13 @@

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);
Expand All @@ -26,7 +34,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
])
->add('exposes', CollectionType::class, [
'label' => false,
'entry_type' => PSExposeConnectionType::class,
'entry_type' => new PSExposeConnectionType($this->app),
'prototype' => true,
'allow_add' => true,
'allow_delete' => true,
Expand Down
Loading

0 comments on commit 529a95e

Please sign in to comment.