PHRAS-3857 Check CSRF token on Prod and Admin forms (#4361)

* csrf token form

* add csrf token

* add csrf

* add csrf

* add csrf

* test

* test

* test

* add form token in report

* csrf token upload

* lazaret csrf form

* upload test

* lazaret test

* add csrf token

* fix test

* fix set cover publication

---------

Co-authored-by: jygaulier <gaulier@alchemy.fr>
This commit is contained in:
Aina Sitraka
2023-10-03 17:28:33 +03:00
committed by GitHub
parent 78a36aec21
commit b6a5f90fd3
71 changed files with 567 additions and 100 deletions

View File

@@ -1064,7 +1064,8 @@ var lightbox = function lightbox(services) {
url: '/lightbox/ajax/SET_NOTE/' + sselcont_id + '/',
dataType: 'json',
data: {
note: note
note: note,
lightbox_token: (0, _jquery2.default)(button).closest('form').find('input[name=lightbox_token]').val()
},
success: function success(datas) {
_hideNotes(container);

View File

@@ -1064,7 +1064,8 @@ var lightbox = function lightbox(services) {
url: '/lightbox/ajax/SET_NOTE/' + sselcont_id + '/',
dataType: 'json',
data: {
note: note
note: note,
lightbox_token: (0, _jquery2.default)(button).closest('form').find('input[name=lightbox_token]').val()
},
success: function success(datas) {
_hideNotes(container);

View File

@@ -10135,6 +10135,10 @@ var workzone = function workzone(services) {
data: formData,
success: function success(data) {
(0, _jquery2.default)('#DIALOG-field-mapping').dialog('close');
},
error: function error(xhr, status, _error) {
var err = JSON.parse(xhr.responseText);
alert(err.message);
}
});
});
@@ -10221,6 +10225,10 @@ var workzone = function workzone(services) {
data: formData,
success: function success(data) {
(0, _jquery2.default)('#DIALOG-field-mapping').dialog('close');
},
error: function error(xhr, status, _error2) {
var err = JSON.parse(xhr.responseText);
alert(err.message);
}
});
});
@@ -10981,7 +10989,8 @@ var workzone = function workzone(services) {
dataType: 'json',
data: {
exposeName: '' + exposeName,
publicationData: publicationData
publicationData: publicationData,
prodExposeEdit_token: (0, _jquery2.default)(this).find('input[name="prodExposeEdit_token"]').val()
},
success: function success(data) {
if (data.success) {
@@ -12282,7 +12291,9 @@ var thesaurusService = function thesaurusService(services) {
sbas[i].seeker = _jquery2.default.ajax({
url: _zurl,
type: 'POST',
data: [],
data: {
prodTabThesaurus_token: (0, _jquery2.default)('form.thesaurus-filter-submit-action input[name=prodTabThesaurus_token]').val()
},
dataType: 'json',
success: function success(j) {
var z = '#TX_P\\.' + j.parm.sbid + '\\.T';
@@ -12319,7 +12330,9 @@ var thesaurusService = function thesaurusService(services) {
sbas[i].seeker = _jquery2.default.ajax({
url: zurl,
type: 'POST',
data: [],
data: {
prodTabThesaurus_token: (0, _jquery2.default)('form.thesaurus-filter-submit-action input[name=prodTabThesaurus_token]').val()
},
dataType: 'json',
success: function success(j) {
var z = '#TX_P\\.' + j.parm.sbid + '\\.T';
@@ -22040,7 +22053,8 @@ var moveRecord = function moveRecord(services) {
var datas = {
lst: (0, _jquery2.default)('input[name="lst"]', $form).val(),
base_id: (0, _jquery2.default)('select[name="base_id"]', $form).val(),
chg_coll_son: coll_son
chg_coll_son: coll_son,
prodMoveCollection_token: (0, _jquery2.default)('input[name="prodMoveCollection_token"]', $form).val()
};
var buttonPanel = $dialog.getDomElement().closest('.ui-dialog').find('.ui-dialog-buttonpane');
@@ -62298,6 +62312,7 @@ var deleteRecord = function deleteRecord(services) {
$trash_counter = $form.find(".to_trash_count"),
$loader = $form.find(".form-action-loader");
var lst = (0, _jquery2.default)("input[name='lst']", $form).val().split(';');
var csrfToken = (0, _jquery2.default)("input[name='prodDeleteRecord_token']", $form).val();
/**
* same parameters for every delete call, except the list of (CHUNKSIZE) records
@@ -62307,9 +62322,10 @@ var deleteRecord = function deleteRecord(services) {
type: $form.attr("method"),
url: $form.attr("action"),
data: {
'lst': "" // set in f
lst: '', // set in f
prodDeleteRecord_token: csrfToken
},
dataType: "json"
dataType: 'json'
};
var runningTasks = 0,
@@ -62335,7 +62351,11 @@ var deleteRecord = function deleteRecord(services) {
}
// pop & truncate
ajaxParms.data.lst = lst.splice(0, CHUNKSIZE).join(';');
_jquery2.default.ajax(ajaxParms).success(function (data) {
_jquery2.default.ajax(ajaxParms).error(function (data) {
fCancel();
$dialog.close();
alert('invalid csrf token delete form');
}).success(function (data) {
// prod feedback only if result ok
_jquery2.default.each(data, function (i, n) {
var imgt = (0, _jquery2.default)('#IMGT_' + n),
@@ -68256,6 +68276,8 @@ var uploader = function uploader(services) {
params.push((0, _jquery2.default)('input', (0, _jquery2.default)('.collection-status:visible', uploaderInstance.getSettingsBox())).serializeArray());
params.push((0, _jquery2.default)('select', uploaderInstance.getSettingsBox()).serializeArray());
params.push([{ name: 'prodUpload_token', value: (0, _jquery2.default)('input[name=prodUpload_token]').val() }]);
_jquery2.default.each(params, function (i, p) {
_jquery2.default.each(p, function (i, f) {
data.formData.push(f);

View File

@@ -10135,6 +10135,10 @@ var workzone = function workzone(services) {
data: formData,
success: function success(data) {
(0, _jquery2.default)('#DIALOG-field-mapping').dialog('close');
},
error: function error(xhr, status, _error) {
var err = JSON.parse(xhr.responseText);
alert(err.message);
}
});
});
@@ -10221,6 +10225,10 @@ var workzone = function workzone(services) {
data: formData,
success: function success(data) {
(0, _jquery2.default)('#DIALOG-field-mapping').dialog('close');
},
error: function error(xhr, status, _error2) {
var err = JSON.parse(xhr.responseText);
alert(err.message);
}
});
});
@@ -10981,7 +10989,8 @@ var workzone = function workzone(services) {
dataType: 'json',
data: {
exposeName: '' + exposeName,
publicationData: publicationData
publicationData: publicationData,
prodExposeEdit_token: (0, _jquery2.default)(this).find('input[name="prodExposeEdit_token"]').val()
},
success: function success(data) {
if (data.success) {
@@ -12282,7 +12291,9 @@ var thesaurusService = function thesaurusService(services) {
sbas[i].seeker = _jquery2.default.ajax({
url: _zurl,
type: 'POST',
data: [],
data: {
prodTabThesaurus_token: (0, _jquery2.default)('form.thesaurus-filter-submit-action input[name=prodTabThesaurus_token]').val()
},
dataType: 'json',
success: function success(j) {
var z = '#TX_P\\.' + j.parm.sbid + '\\.T';
@@ -12319,7 +12330,9 @@ var thesaurusService = function thesaurusService(services) {
sbas[i].seeker = _jquery2.default.ajax({
url: zurl,
type: 'POST',
data: [],
data: {
prodTabThesaurus_token: (0, _jquery2.default)('form.thesaurus-filter-submit-action input[name=prodTabThesaurus_token]').val()
},
dataType: 'json',
success: function success(j) {
var z = '#TX_P\\.' + j.parm.sbid + '\\.T';
@@ -22040,7 +22053,8 @@ var moveRecord = function moveRecord(services) {
var datas = {
lst: (0, _jquery2.default)('input[name="lst"]', $form).val(),
base_id: (0, _jquery2.default)('select[name="base_id"]', $form).val(),
chg_coll_son: coll_son
chg_coll_son: coll_son,
prodMoveCollection_token: (0, _jquery2.default)('input[name="prodMoveCollection_token"]', $form).val()
};
var buttonPanel = $dialog.getDomElement().closest('.ui-dialog').find('.ui-dialog-buttonpane');
@@ -62298,6 +62312,7 @@ var deleteRecord = function deleteRecord(services) {
$trash_counter = $form.find(".to_trash_count"),
$loader = $form.find(".form-action-loader");
var lst = (0, _jquery2.default)("input[name='lst']", $form).val().split(';');
var csrfToken = (0, _jquery2.default)("input[name='prodDeleteRecord_token']", $form).val();
/**
* same parameters for every delete call, except the list of (CHUNKSIZE) records
@@ -62307,9 +62322,10 @@ var deleteRecord = function deleteRecord(services) {
type: $form.attr("method"),
url: $form.attr("action"),
data: {
'lst': "" // set in f
lst: '', // set in f
prodDeleteRecord_token: csrfToken
},
dataType: "json"
dataType: 'json'
};
var runningTasks = 0,
@@ -62335,7 +62351,11 @@ var deleteRecord = function deleteRecord(services) {
}
// pop & truncate
ajaxParms.data.lst = lst.splice(0, CHUNKSIZE).join(';');
_jquery2.default.ajax(ajaxParms).success(function (data) {
_jquery2.default.ajax(ajaxParms).error(function (data) {
fCancel();
$dialog.close();
alert('invalid csrf token delete form');
}).success(function (data) {
// prod feedback only if result ok
_jquery2.default.each(data, function (i, n) {
var imgt = (0, _jquery2.default)('#IMGT_' + n),
@@ -68256,6 +68276,8 @@ var uploader = function uploader(services) {
params.push((0, _jquery2.default)('input', (0, _jquery2.default)('.collection-status:visible', uploaderInstance.getSettingsBox())).serializeArray());
params.push((0, _jquery2.default)('select', uploaderInstance.getSettingsBox()).serializeArray());
params.push([{ name: 'prodUpload_token', value: (0, _jquery2.default)('input[name=prodUpload_token]').val() }]);
_jquery2.default.each(params, function (i, p) {
_jquery2.default.each(p, function (i, f) {
data.formData.push(f);

View File

@@ -1036,7 +1036,8 @@ const lightbox = services => {
url: '/lightbox/ajax/SET_NOTE/' + sselcont_id + '/',
dataType: 'json',
data: {
note: note
note: note,
lightbox_token: $(button).closest('form').find('input[name=lightbox_token]').val()
},
success: function (datas) {
_hideNotes(container);

View File

@@ -76,6 +76,7 @@ const deleteRecord = (services) => {
$trash_counter = $form.find(".to_trash_count"),
$loader = $form.find(".form-action-loader");
let lst = $("input[name='lst']", $form).val().split(';');
let csrfToken = $("input[name='prodDeleteRecord_token']", $form).val();
/**
* same parameters for every delete call, except the list of (CHUNKSIZE) records
@@ -85,9 +86,10 @@ const deleteRecord = (services) => {
type: $form.attr("method"),
url: $form.attr("action"),
data: {
'lst': "" // set in f
lst: '', // set in f
prodDeleteRecord_token: csrfToken
},
dataType: "json"
dataType: 'json'
};
let runningTasks = 0, // number of running tasks
@@ -113,6 +115,11 @@ const deleteRecord = (services) => {
// pop & truncate
ajaxParms.data.lst = lst.splice(0, CHUNKSIZE).join(';');
$.ajax(ajaxParms)
.error(function (data) {
fCancel();
$dialog.close();
alert('invalid csrf token delete form');
})
.success(function (data) { // prod feedback only if result ok
$.each(data, function (i, n) {
let imgt = $('#IMGT_' + n),

View File

@@ -48,7 +48,8 @@ const moveRecord = (services) => {
var datas = {
lst: $('input[name="lst"]', $form).val(),
base_id: $('select[name="base_id"]', $form).val(),
chg_coll_son: coll_son
chg_coll_son: coll_son,
prodMoveCollection_token: $('input[name="prodMoveCollection_token"]', $form).val()
};
var buttonPanel = $dialog.getDomElement()

View File

@@ -636,7 +636,9 @@ const thesaurusService = services => {
sbas[i].seeker = $.ajax({
url: zurl,
type: 'POST',
data: [],
data: {
prodTabThesaurus_token: $('form.thesaurus-filter-submit-action input[name=prodTabThesaurus_token]').val()
},
dataType: 'json',
success: function (j) {
var z = '#TX_P\\.' + j.parm.sbid + '\\.T';
@@ -680,7 +682,9 @@ const thesaurusService = services => {
sbas[i].seeker = $.ajax({
url: zurl,
type: 'POST',
data: [],
data: {
prodTabThesaurus_token: $('form.thesaurus-filter-submit-action input[name=prodTabThesaurus_token]').val()
},
dataType: 'json',
success: function (j) {
var z = '#TX_P\\.' + j.parm.sbid + '\\.T';

View File

@@ -210,6 +210,10 @@ const workzone = (services) => {
data: formData,
success: function (data) {
$('#DIALOG-field-mapping').dialog('close');
},
error: function (xhr, status, error) {
let err = JSON.parse(xhr.responseText);
alert(err.message);
}
});
});
@@ -296,6 +300,10 @@ const workzone = (services) => {
data: formData,
success: function (data) {
$('#DIALOG-field-mapping').dialog('close');
},
error: function (xhr, status, error) {
let err = JSON.parse(xhr.responseText);
alert(err.message);
}
});
@@ -1068,7 +1076,8 @@ const workzone = (services) => {
dataType: 'json',
data: {
exposeName: `${exposeName}`,
publicationData: publicationData
publicationData: publicationData,
prodExposeEdit_token: $(this).find('input[name="prodExposeEdit_token"]').val()
},
success: function (data) {
if (data.success) {

View File

@@ -417,6 +417,8 @@ const uploader = (services) => {
params.push($('input', $('.collection-status:visible', uploaderInstance.getSettingsBox())).serializeArray());
params.push($('select', uploaderInstance.getSettingsBox()).serializeArray());
params.push([{name: 'prodUpload_token', value: $('input[name=prodUpload_token]').val()}]);
$.each(params, function (i, p) {
$.each(p, function (i, f) {
data.formData.push(f);

View File

@@ -15,7 +15,9 @@ use Alchemy\Phrasea\Authentication\ACLProvider;
use Alchemy\Phrasea\Authentication\Authenticator;
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
use Alchemy\Phrasea\Model\Entities\User;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
class Controller
{
@@ -112,6 +114,35 @@ class Controller
return $this->getAuthenticator()->getUser();
}
public function setSessionFormToken($formName)
{
$randomValue = bin2hex(random_bytes(35));
$this->app['session']->set($formName.'_token', $randomValue);
return $randomValue;
}
public function getSessionFormToken($formName)
{
return $this->app['session']->get($formName.'_token');
}
public function isCrsfValid(Request $request, $formName)
{
if (!$request->isMethod("POST") && !$request->isMethod("PUT")) {
return false;
}
$formTokenName = $formName . '_token';
$formToken = (string) $request->request->get($formTokenName);
if (empty($formToken) || $formToken != $this->getSessionFormToken($formName)) {
return false;
}
return true;
}
/**
* @return PropertyAccess
*/

View File

@@ -264,6 +264,8 @@ class LightboxController extends Controller
*/
private function getValidationTemplate()
{
$this->setSessionFormToken('lightbox');
return 'lightbox/validate.html.twig';
}
@@ -338,6 +340,10 @@ class LightboxController extends Controller
*/
public function ajaxSetNoteAction(Request $request, $sselcont_id)
{
if (!$this->isCrsfValid($request, 'lightbox')) {
return new Response('invalid crsf token form', 403);
}
$note = $request->request->get('note');
if (is_null($note)) {

View File

@@ -203,6 +203,10 @@ class BasketController extends Controller
public function createBasket(Request $request)
{
if (!$this->isCrsfValid($request, 'prodCreateBasket')) {
return $this->app->json(['success' => false , 'message' => 'invalid form'], 403);
}
$basket = new Basket();
$basket->setName($request->request->get('name', ''));
@@ -271,6 +275,10 @@ class BasketController extends Controller
public function updateBasket(Request $request, Basket $basket)
{
if (!$this->isCrsfValid($request, 'prodBasketRename')) {
return $this->app->json(['success' => false , 'message' => 'invalid form'], 403);
}
$success = false;
try {
@@ -305,16 +313,24 @@ class BasketController extends Controller
public function displayUpdateForm(Basket $basket)
{
$this->setSessionFormToken('prodBasketRename');
return $this->render('prod/Baskets/Update.html.twig', ['basket' => $basket]);
}
public function displayReorderForm(Basket $basket)
{
$this->setSessionFormToken('prodBasketReorder');
return $this->render('prod/Baskets/Reorder.html.twig', ['basket' => $basket]);
}
public function reorder(Request $request, Basket $basket)
{
if (!$this->isCrsfValid($request, 'prodBasketReorder')) {
return $this->app->json(['success' => false , 'message' => 'invalid form'], 403);
}
$ret = ['success' => false, 'message' => $this->app->trans('An error occured')];
try {
$order = $request->request->get('element');
@@ -417,6 +433,8 @@ class BasketController extends Controller
public function displayCreateForm()
{
$this->setSessionFormToken('prodCreateBasket');
return $this->render('prod/Baskets/Create.html.twig');
}

View File

@@ -29,6 +29,10 @@ class DownloadController extends Controller
*/
public function checkDownload(Request $request)
{
if (!$this->isCrsfValid($request, 'prodExportDownload')) {
$this->app->abort(403);
}
$lst = $request->request->get('lst');
$ssttid = $request->request->get('ssttid', '');
$subdefs = $request->request->get('obj', []);

View File

@@ -44,6 +44,11 @@ class ExportController extends Controller
$request->request->get('story')
);
$this->setSessionFormToken('prodExportDownload');
$this->setSessionFormToken('prodExportEmail');
$this->setSessionFormToken('prodExportFTP');
$this->setSessionFormToken('prodExportOrder');
return new Response($this->render('common/dialog_export.html.twig', [
'download' => $download,
'ssttid' => $request->request->get('ssel'),
@@ -90,6 +95,10 @@ class ExportController extends Controller
*/
public function exportFtp(Request $request)
{
if (!$this->isCrsfValid($request, 'prodExportFTP')) {
return $this->app->json(['message' => 'invalid export ftp form'], 403);
}
$download = new \set_exportftp($this->app, $request->request->get('lst'), $request->request->get('ssttid'));
$mandatoryParameters = ['address', 'login', 'obj'];
@@ -153,6 +162,10 @@ class ExportController extends Controller
*/
public function exportMail(Request $request)
{
if (!$this->isCrsfValid($request, 'prodExportEmail')) {
return $this->app->json(['message' => 'invalid export mail form'], 403);
}
set_time_limit(0);
session_write_close();
ignore_user_abort(true);

View File

@@ -53,6 +53,8 @@ class LazaretController extends Controller
$lazaretFiles = $this->getLazaretFileRepository()->findPerPage($baseIds, $offset, $perPage);
}
$this->setSessionFormToken('prodLazaret');
return $this->render('prod/upload/lazaret.html.twig', [
'lazaretFiles' => $lazaretFiles,
'currentPage' => $page,
@@ -110,6 +112,12 @@ class LazaretController extends Controller
{
$ret = ['success' => false, 'message' => '', 'result' => []];
if (!$this->isCrsfValid($request, 'prodLazaret')) {
$ret['message'] = 'invalid prodLazaret token';
return $this->app->json($ret, 403);
}
//Mandatory parameter
if (null === $request->request->get('bas_id')) {
$ret['message'] = $this->app->trans('You must give a destination collection');
@@ -146,8 +154,14 @@ class LazaretController extends Controller
*
* @return Response
*/
public function denyElement($file_id)
public function denyElement(Request $request, $file_id)
{
if (!$this->isCrsfValid($request, 'prodLazaret')) {
$ret['message'] = 'invalid prodLazaret token';
return $this->app->json($ret, 403);
}
/** @var LazaretManipulator $lazaretManipulator */
$lazaretManipulator = $this->app['manipulator.lazaret'];
@@ -193,6 +207,12 @@ class LazaretController extends Controller
{
$ret = ['success' => false, 'message' => '', 'result' => []];
if (!$this->isCrsfValid($request, 'prodLazaret')) {
$ret['message'] = 'invalid prodLazaret token';
return $this->app->json($ret, 403);
}
//Mandatory parameter
if (null === $recordId = $request->request->get('record_id')) {
$ret['message'] = $this->app->trans('You must give a destination record');

View File

@@ -62,6 +62,8 @@ class MoveCollectionController extends Controller
// sort the collections
array_multisort($aName, $uorder, SORT_REGULAR, $collections);
$this->setSessionFormToken('prodMoveCollection');
$parameters = [
'records' => $records,
'message' => '',
@@ -81,6 +83,10 @@ class MoveCollectionController extends Controller
public function apply(Request $request)
{
if (!$this->isCrsfValid($request, 'prodMoveCollection')) {
return $this->app->json(['success' => false, 'message' => 'invalid move collection form']);
}
/** @var \record_adapter[] $records */
$records = RecordsRequest::fromRequest($this->app, $request, false, [\ACL::CANDELETERECORD]);

View File

@@ -48,6 +48,8 @@ class PrinterController extends Controller
$storyId = $r->singleStory()->getId();
}
$this->setSessionFormToken('prodPrint');
return $this->render('prod/actions/printer_default.html.twig', [
'printer' => $printer,
'message' => '',
@@ -59,6 +61,10 @@ class PrinterController extends Controller
public function printAction(Request $request)
{
if (!$this->isCrsfValid($request, 'prodPrint')) {
$this->app->abort(403);
}
$printer = new RecordHelper\Printer($this->app, $request);
$printer->setThumbnailName($request->request->get('thumbnail-chosen'));
$printer->setPreviewName($request->request->get('preview-chosen'));

View File

@@ -33,6 +33,8 @@ class PropertyController extends Controller
$records = RecordsRequest::fromRequest($this->app, $request, false, [\ACL::CHGSTATUS]);
$this->setSessionFormToken('prodPropertyStatus');
$databoxes = $records->databoxes();
if (count($databoxes) > 1) {
return new Response($this->render('prod/actions/Property/index.html.twig', [
@@ -103,6 +105,8 @@ class PropertyController extends Controller
$recordsType[$sbasId][$record->getType()][] = $record;
}
$this->setSessionFormToken('prodPropertyType');
return new Response($this->render('prod/actions/Property/type.html.twig', [
'records' => $records,
'recordsType' => $recordsType,
@@ -117,6 +121,10 @@ class PropertyController extends Controller
*/
public function changeStatus(Request $request)
{
if (!$this->isCrsfValid($request, 'prodPropertyStatus')) {
return $this->app->json(['message' => 'invalid change status form'], 403);
}
$applyStatusToChildren = $request->request->get('apply_to_children', []);
$records = RecordsRequest::fromRequest($this->app, $request, false, [\ACL::CHGSTATUS]);
$updated = [];
@@ -151,6 +159,10 @@ class PropertyController extends Controller
*/
public function changeType(Request $request)
{
if (!$this->isCrsfValid($request, 'prodPropertyType')) {
return $this->app->json(['message' => 'invalid change type form'], 403);
}
$typeLst = $request->request->get('types', []);
$records = RecordsRequest::fromRequest($this->app, $request, false, [\ACL::CANMODIFRECORD]);
$mimeLst = $request->request->get('mimes', []);

View File

@@ -215,6 +215,10 @@ class PushController extends Controller
*/
public function sharebasketAction(Request $request)
{
if (!$this->isCrsfValid($request, 'prodShareBasket')) {
return $this->app->json(['success' => false, 'message' => 'invalid form']);
}
$ret = [
'success' => false,
'message' => $this->app->trans('Unable to send the documents')
@@ -393,6 +397,10 @@ class PushController extends Controller
*/
public function addUserAction(Request $request)
{
if (!$this->isCrsfValid($request, 'prodShareAddUser')) {
return $this->app->json(['success' => false , 'message' => 'invalid add user form'], 403);
}
$result = ['success' => false, 'message' => '', 'user' => null];
try {
@@ -470,6 +478,8 @@ class PushController extends Controller
{
$params = ['callback' => $request->query->get('callback')];
$this->setSessionFormToken('prodShareAddUser');
return $this->render('prod/User/Add.html.twig', $params);
}
@@ -817,6 +827,8 @@ class PushController extends Controller
$repository = $this->getUserListRepository();
$recommendedUsers = $this->getUsersInSelectionExtractor($push->get_elements());
$this->setSessionFormToken('prodShareBasket');
return $this->render(
'prod/actions/Push.html.twig',
[

View File

@@ -21,6 +21,7 @@ use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
use Alchemy\Phrasea\Utilities\StringHelper;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use unicode;
class QueryController extends Controller
@@ -121,6 +122,10 @@ class QueryController extends Controller
*/
public function query(Request $request)
{
if (!$this->isCrsfValid($request, 'searchForm')) {
return $this->app->json(['message' => 'invalid search token'], 403);
}
$query = (string) $request->request->get('qry');
// since the query comes from a submited form, normalize crlf,cr,lf ...

View File

@@ -224,6 +224,10 @@ class RecordController extends Controller
*/
public function doDeleteRecords(Request $request)
{
if (!$this->isCrsfValid($request, 'prodDeleteRecord')) {
return $this->app->json(['success' => false , 'message' => 'invalid delete form'], 403);
}
$records = RecordsRequest::fromRequest(
$this->app,
$request,
@@ -351,6 +355,8 @@ class RecordController extends Controller
'deletableCount' => count($filteredRecords['delete'])
];
$this->setSessionFormToken('prodDeleteRecord');
return $this->render(
'prod/actions/delete_records_confirm.html.twig',
$viewParms

View File

@@ -104,6 +104,10 @@ class RootController extends Controller
'actionbar' => $filter('actionbar'),
];
$this->setSessionFormToken('searchForm');
$this->setSessionFormToken('prodExposeNew');
$this->setSessionFormToken('prodTabThesaurus');
return $this->render('prod/index.html.twig', [
'module_name' => 'Production',
'WorkZone' => new WorkzoneHelper($this->app, $request),

View File

@@ -45,6 +45,8 @@ class StoryController extends Controller
}
}
$this->setSessionFormToken('prodCreateStory');
return $this->render('prod/Story/Create.html.twig', [
'isMultipleDataboxes' => count($databoxes) > 1 ? 1 : 0,
'isMultipleCollections' => count($collections) > 1 ? 1 : 0,
@@ -56,6 +58,10 @@ class StoryController extends Controller
public function postCreateFormAction(Request $request)
{
if (!$this->isCrsfValid($request, 'prodCreateStory')) {
return $this->app->json(['success' => false , 'message' => 'invalid form'], 403);
}
$collection = \collection::getByBaseId($this->app, $request->request->get('base_id'));
if (!$this->getAclForUser()->has_right_on_base($collection->get_base_id(), \ACL::CANADDRECORD)) {
@@ -209,6 +215,8 @@ class StoryController extends Controller
throw new \Exception('This is not a story');
}
$this->setSessionFormToken('prodStoryReorder');
return $this->renderResponse('prod/Story/Reorder.html.twig', [
'story' => $story,
]);
@@ -216,6 +224,10 @@ class StoryController extends Controller
public function reorderAction(Request $request, $sbas_id, $record_id)
{
if (!$this->isCrsfValid($request, 'prodStoryReorder')) {
return $this->app->json(['success' => false , 'message' => 'invalid form'], 403);
}
try {
$story = new \record_adapter($this->app, $sbas_id, $record_id);
$previousDescription = $story->getRecordDescriptionAsArray();

View File

@@ -113,6 +113,11 @@ class ToolsController extends Controller
}
}
$this->setSessionFormToken('prodToolsSubdef');
$this->setSessionFormToken('prodToolsRotate');
$this->setSessionFormToken('prodToolsHDSubstitution');
$this->setSessionFormToken('prodToolsThumbSubstitution');
return $this->render('prod/actions/Tools/index.html.twig', [
'records' => $records,
'record' => $record,
@@ -127,6 +132,10 @@ class ToolsController extends Controller
public function rotateAction(Request $request)
{
if (!$this->isCrsfValid($request, 'prodToolsRotate')) {
return $this->app->json(['success' => false , 'message' => 'invalid rotate form'], 403);
}
$records = RecordsRequest::fromRequest($this->app, $request, false);
$rotation = (int)$request->request->get('rotation', 90);
$rotation %= 360;
@@ -165,6 +174,10 @@ class ToolsController extends Controller
public function imageAction(Request $request)
{
if (!$this->isCrsfValid($request, 'prodToolsSubdef')) {
return $this->app->json(['success' => false , 'message' => 'invalid create subview form'], 403);
}
$return = ['success' => true];
$force = $request->request->get('force_substitution') == '1';
@@ -211,6 +224,10 @@ class ToolsController extends Controller
public function hddocAction(Request $request)
{
if (!$this->isCrsfValid($request, 'prodToolsHDSubstitution')) {
return $this->app->json(['success' => false , 'message' => 'invalid document substitution form'], 403);
}
$success = false;
$message = $this->app->trans('An error occured');
@@ -269,6 +286,10 @@ class ToolsController extends Controller
public function changeThumbnailAction(Request $request)
{
if (!$this->isCrsfValid($request, 'prodToolsThumbSubstitution')) {
return $this->app->json(['success' => false , 'message' => 'invalid thumbnail substitution form'], 403);
}
$file = $request->files->get('newThumb');
if (empty($file)) {

View File

@@ -28,6 +28,7 @@ use DataURI\Exception\Exception as DataUriException;
use DataURI\Parser;
use GuzzleHttp\Client as Guzzle;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -56,6 +57,8 @@ class UploadController extends Controller
public function getHtml5UploadForm()
{
$this->setSessionFormToken('prodUpload');
$maxFileSize = $this->getUploadMaxFileSize();
return $this->render('prod/upload/upload.html.twig', [
@@ -68,6 +71,8 @@ class UploadController extends Controller
public function getUploadForm()
{
$this->setSessionFormToken('prodUpload');
$maxFileSize = $this->getUploadMaxFileSize();
return $this->render('prod/upload/upload.html.twig', [
@@ -126,6 +131,10 @@ class UploadController extends Controller
'id' => '',
];
if (!$this->isCrsfValid($request, 'prodUpload')) {
throw new AccessDeniedHttpException('Invalid prodUpload token');
}
if (null === $request->files->get('files')) {
throw new BadRequestHttpException('Missing file parameter');
}

View File

@@ -90,6 +90,11 @@ class RootController extends Controller
$conf = $this->getConf();
$this->setSessionFormToken('reportConnection');
$this->setSessionFormToken('reportDownload');
$this->setSessionFormToken('reportRecord');
return $this->render('report/report_layout_child.html.twig', [
'ajax_dash' => true,
'dashboard' => null,

View File

@@ -1440,6 +1440,10 @@ class ThesaurusXmlHttpController extends Controller
public function searchTermJson(Request $request)
{
if (!$this->isCrsfValid($request, 'prodTabThesaurus')) {
return $this->app->json(['success' => false , 'message' => 'invalid form token'], 403);
}
$lng = $request->get('lng');
$html = '';

View File

@@ -37,6 +37,10 @@ class ProdOrderController extends BaseOrderController
*/
public function createOrder(Request $request)
{
if (!$this->isCrsfValid($request, 'prodExportOrder')) {
return $this->app->json(['message' => 'invalid export order form'], 403);
}
$records = RecordsRequest::fromRequest($this->app, $request, true, [\ACL::CANCMD]);
try {

View File

@@ -25,6 +25,10 @@ class PSExposeController extends Controller
*/
public function authenticateAction(PhraseaApplication $app, Request $request)
{
if (!$this->isCrsfValid($request, 'prodExposeLogin')) {
return $this->app->json(['success' => false , 'error_description' => 'invalid csrf form']);
}
$exposeConfiguration = $app['conf']->get(['phraseanet-service', 'expose-service', 'exposes'], []);
$exposeConfiguration = $exposeConfiguration[$request->request->get('exposeName')];
@@ -205,7 +209,9 @@ class PSExposeController extends Controller
}
if (!$session->has($passSessionName) && $exposeConfiguration['connection_kind'] == 'password' && $request->get('format') != 'json') {
return $app->json([
$this->setSessionFormToken('prodExposeLogin');
return $app->json([
'twig' => $this->render("prod/WorkZone/ExposeOauthLogin.html.twig", [
'exposeName' => $exposeName
]),
@@ -296,6 +302,8 @@ class PSExposeController extends Controller
]);
}
$this->setSessionFormToken('prodExposeEdit');
$exposeListTwig = $this->render("prod/WorkZone/ExposeList.html.twig", [
'publications' => $publications,
'exposeFrontBasePath' => $exposeFrontBasePath
@@ -614,6 +622,10 @@ class PSExposeController extends Controller
*/
public function createPublicationAction(PhraseaApplication $app, Request $request)
{
if (!$this->isCrsfValid($request, 'prodExposeNew')) {
return $this->app->json(['success' => false , 'message' => 'invalid crsf token form']);
}
$exposeName = $request->get('exposeName');
if ( $exposeName == null) {
return $app->json([
@@ -682,6 +694,10 @@ class PSExposeController extends Controller
*/
public function updatePublicationAction(PhraseaApplication $app, Request $request)
{
if (!$this->isCrsfValid($request, 'prodExposeEdit')) {
return $this->app->json(['success' => false , 'message' => 'invalid crsf token form']);
}
$exposeName = $request->get('exposeName');
$exposeClient = $this->getExposeClient($exposeName);
if ($exposeClient == null) {
@@ -966,6 +982,9 @@ class PSExposeController extends Controller
public function getFieldMappingAction(PhraseaApplication $app, Request $request)
{
$this->setSessionFormToken('prodExposeFieldMapping');
$this->setSessionFormToken('prodExposeSubdefMapping');
return $this->render('prod/WorkZone/ExposeFieldMapping.html.twig', [
'exposeName' => $request->get('exposeName')
]);
@@ -979,6 +998,10 @@ class PSExposeController extends Controller
*/
public function saveFieldMappingAction(PhraseaApplication $app, Request $request)
{
if (!$this->isCrsfValid($request, 'prodExposeFieldMapping')) {
return $this->app->json(['success' => false , 'message' => 'invalid crsf token form'], 403);
}
$exposeName = $request->get('exposeName');
$profile = $request->request->get('profile');
$sendGeolocField = !empty($request->request->get('sendGeolocField')) ? array_keys($request->request->get('sendGeolocField')): [];
@@ -1055,6 +1078,10 @@ class PSExposeController extends Controller
public function saveSubdefMappingAction(PhraseaApplication $app, Request $request)
{
if (!$this->isCrsfValid($request, 'prodExposeSubdefMapping')) {
return $this->app->json(['success' => false , 'message' => 'invalid crsf token form'], 403);
}
$exposeName = $request->get('exposeName');
$profile = $request->request->get('profile');
$exposeClient = $this->getExposeClient($exposeName);

View File

@@ -15,6 +15,7 @@ use Alchemy\Phrasea\Report\ReportConnections;
use Alchemy\Phrasea\Report\ReportActions;
use Alchemy\Phrasea\Report\ReportFactory;
use Alchemy\Phrasea\Report\ReportRecords;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -57,6 +58,8 @@ class ProdReportController extends Controller
$this->anonymousReport = $anonymousReport;
$this->acl = $acl;
$this->appbox = $appbox;
parent::__construct($appbox->getPhraseApplication());
}
/**
@@ -77,11 +80,15 @@ class ProdReportController extends Controller
*
* @param Request $request
* @param $sbasId
* @return RedirectResponse|StreamedResponse
* @return RedirectResponse|StreamedResponse|JsonResponse
*/
public function connectionsAction(Request $request, $sbasId)
{
if ($request->isMethod("POST")) {
if (!$this->isCrsfValid($request, 'reportConnection')) {
return new JsonResponse(['message' => 'invalid report connection token'], 403);
}
if (!($extension = $request->get('format'))) {
$extension = 'csv';
}
@@ -123,11 +130,15 @@ class ProdReportController extends Controller
*
* @param Request $request
* @param $sbasId
* @return RedirectResponse|StreamedResponse
* @return RedirectResponse|StreamedResponse|JsonResponse
*/
public function downloadsAction(Request $request, $sbasId)
{
if ($request->isMethod("POST")) {
if (!$this->isCrsfValid($request, 'reportDownload')) {
return new JsonResponse(['message' => 'invalid report download token'], 403);
}
if(!($extension = $request->get('format'))) {
$extension = 'csv';
}
@@ -172,11 +183,15 @@ class ProdReportController extends Controller
*
* @param Request $request
* @param $sbasId
* @return RedirectResponse|StreamedResponse
* @return RedirectResponse|StreamedResponse|JsonResponse
*/
public function recordsAction(Request $request, $sbasId)
{
if ($request->isMethod("POST")) {
if (!$this->isCrsfValid($request, 'reportRecord')) {
return new JsonResponse(['message' => 'invalid report record token'], 403);
}
if (!($extension = $request->get('format'))) {
$extension = 'csv';
}

View File

@@ -108,7 +108,7 @@
<div id="download">
<div style="padding:10px; text-align: center;">
<h4>{{ 'export:: telechargement' | trans }}</h4>
<form method="post" target="_blank" action="{{ path('check_download') }}" style="text-align: left;">
<form method="post" target="_blank" name="prodExportDownload" action="{{ path('check_download') }}" style="text-align: left;">
<input type="hidden" name="lst" value="{{lst}}"/>
<input type="hidden" name="ssttid" value="{{ssttid}}"/>
{% for name, values in download.get_display_download() %}
@@ -168,13 +168,14 @@
<button type="button" class="download_button btn btn-inverse">{{ 'boutton::telecharger' | trans }}</button>
<button type="button" class="close_button btn btn-inverse">{{ 'boutton::annuler' | trans }}</button>
</div>
<input type="hidden" name="prodExportDownload_token" value="{{ app['session'].get('prodExportDownload_token') }}">
</form>
</div>
</div>
<div id="sendmail">
<div style="padding:10px; text-align: center;">
<h4>{{ 'export:: envoi par mail' | trans }}</h4>
<form action="{{ path('export_mail') }}" method="post" target="sendmail_target" style="text-align: left;">
<form action="{{ path('export_mail') }}" method="post" name="prodExportEmail" target="sendmail_target" style="text-align: left;">
<input type="hidden" name="lst" value="{{lst}}"/>
<input type="hidden" name="ssttid" value="{{ssttid}}"/>
<div class="acceptDl-info" style="padding-top: 4px; margin-left: 25px; margin-bottom: 8px;">
@@ -257,6 +258,7 @@
<img class="sendmail_button_loader" src="/assets/common/images/icons/loader404040.gif" style="visibility:hidden;margin:0 5px;"/>
<button type="button" class="close_button btn btn-inverse">{{ 'boutton::annuler' | trans }}</button>
</div>
<input type="hidden" name="prodExportEmail_token" value="{{ app['session'].get('prodExportEmail_token') }}">
</form>
</div>
</div>
@@ -296,7 +298,7 @@
{% endif %}
{% endfor %}
<hr />
<form class="form-horizontal">
<form class="form-horizontal" name="prodExportOrder">
<input type="hidden" name="lst" value="{{lst}}"/>
<input type="hidden" name="ssel" value="{{ssttid}}"/>
@@ -404,6 +406,7 @@
<img class="order_button_loader" src="/assets/common/images/icons/loader404040.gif" style="visibility:hidden;margin:0 5px;"/>
<button type="button" class="close_button btn btn-inverse">{{ 'boutton::annuler' | trans }}</button>
</div>
<input type="hidden" name="prodExportOrder_token" value="{{ app['session'].get('prodExportOrder_token') }}">
</form>
</div>
{% endif %}
@@ -430,7 +433,7 @@
{% endfor %}
</div>
</div>
<form id="ftp_joined" class="form-horizontal" style="text-align: left;">
<form id="ftp_joined" class="form-horizontal" name="prodExportFTP" style="text-align: left;">
<input type="hidden" name="lst" value="{{lst}}"/>
<input type="hidden" name="ssttid" value="{{ssttid}}"/>
<div>
@@ -479,6 +482,7 @@
</label>
</div>
{% endif %}
<input type="hidden" name="prodExportFTP_token" value="{{ app['session'].get('prodExportFTP_token') }}">
</form>
<div class="buttons_line">
<button type="button" class="tryftp_button btn btn-inverse">{{ 'boutton::essayer' | trans }}</button>

View File

@@ -26,6 +26,7 @@
{{ 'boutton::enregistrer' | trans }}
</button>
</div>
<input type="hidden" name="lightbox_token" value="{{ app['session'].get('lightbox_token') }}">
</form>
</div>
</div>

View File

@@ -9,4 +9,5 @@
<input type="checkbox" name="lst" value="" id="new_basket_add_sel"/>
{{ 'Ajouter ma selection courrante' | trans }}
</label>
<input type="hidden" name="prodCreateBasket_token" value="{{ app['session'].get('prodCreateBasket_token') }}">
</form>

View File

@@ -2,22 +2,23 @@
<div id="reorder_box">
<div id="reorder_options" class="row-fluid">
<form class="form-inline span10">
<label for="auto_order">{{ 'Reordonner automatiquement' | trans }}</label>
<select id="auto_order">
<option value="">{{ 'Choisir' | trans }}</option>
<option value="default">{{ 'Re-initialiser' | trans }}</option>
<option value="title">{{ 'Titre' | trans }}</option>
<option value="date_created">{{ 'Date de création' | trans }}</option>
<option value="date_updated">{{ 'Date de modification' | trans }}</option>
</select>
<button type="button" class="autoorder btn btn-inverse">{{ 'Re-ordonner' | trans }}</button>
<button type="button" class="reverseorder btn btn-inverse">{{ 'Inverser' | trans }}</button>
</form>
<form class="form-inline span2" name="reorder" method="POST" action="{{ path('prod_baskets_basket_reorder', { 'basket' : basket.getId() }) }}">
{% for element in basket.getElements() %}
<input type="hidden" name="element[{{ element.getId() }}]" value="{{ element.getOrd() }}"/>
{% endfor %}
<input type="submit" class="btn btn-inverse" value="{{ 'boutton::valider' | trans }}" />
<label for="auto_order">{{ 'Reordonner automatiquement' | trans }}</label>
<select id="auto_order">
<option value="">{{ 'Choisir' | trans }}</option>
<option value="default">{{ 'Re-initialiser' | trans }}</option>
<option value="title">{{ 'Titre' | trans }}</option>
<option value="date_created">{{ 'Date de création' | trans }}</option>
<option value="date_updated">{{ 'Date de modification' | trans }}</option>
</select>
<button type="button" class="autoorder btn btn-inverse">{{ 'Re-ordonner' | trans }}</button>
<button type="button" class="reverseorder btn btn-inverse">{{ 'Inverser' | trans }}</button>
</form>
<form class="form-inline span2" name="reorder" method="POST" action="{{ path('prod_baskets_basket_reorder', { 'basket' : basket.getId() }) }}">
{% for element in basket.getElements() %}
<input type="hidden" name="element[{{ element.getId() }}]" value="{{ element.getOrd() }}"/>
{% endfor %}
<input type="submit" class="btn btn-inverse" value="{{ 'boutton::valider' | trans }}" />
<input type="hidden" name="prodBasketReorder_token" value="{{ app['session'].get('prodBasketReorder_token') }}">
</form>
</div>
<div class="elements row-fluid">

View File

@@ -5,5 +5,6 @@
<label style="margin:5px 0 0 0;">{{ 'panier:: description' | trans }}</label>
<textarea style="width:98%;height:120px;" name="description">{{ basket.getDescription() }}</textarea>
<button type='button' class="btn btn-inverse" style="margin: 5px 40%;">{{ 'boutton::valider' | trans }}</button>
<input type="hidden" name="prodBasketRename_token" value="{{ app['session'].get('prodBasketRename_token') }}">
</form>
</div>

View File

@@ -43,5 +43,5 @@
<input {% if isMultipleDataboxes %} disabled {% endif %} type="checkbox" name="lst" value="" id="new_story_add_sel"/>
{{ 'Ajouter ma selection courrante' | trans }}
</label>
<input type="hidden" name="prodCreateStory_token" value="{{ app['session'].get('prodCreateStory_token') }}">
</form>

View File

@@ -18,6 +18,7 @@
<input type="hidden" name="element[{{ element.get_record_id() }}]" value="{{ element.getNumber() }}"/>
{% endfor %}
<input type="submit" class="btn btn-inverse" value="{{ 'boutton::valider' | trans }}"/>
<input type="hidden" name="prodStoryReorder_token" value="{{ app['session'].get('prodStoryReorder_token') }}">
</form>
</div>
<div style="top:45px;overflow:auto;" id="reorder_box" class="row-fluid">

View File

@@ -35,6 +35,7 @@
<td class="messages"></td>
</tr>
</table>
<input type="hidden" name="prodShareAddUser_token" value="{{ app['session'].get('prodShareAddUser_token') }}">
</form>
</div>

View File

@@ -175,7 +175,7 @@
</div>
</div>
</div>
<input type="hidden" name="prodExposeEdit_token" value="{{ app['session'].get('prodExposeEdit_token') }}">
</form>
@@ -382,7 +382,8 @@
dataType: 'json',
data: {
exposeName: "{{ exposeName }}",
publicationData: advancedSetting.val()
publicationData: advancedSetting.val(),
prodExposeEdit_token: $('#publication-json input[name="prodExposeEdit_token"]').val()
},
success: function (data) {
if (data.success) {

View File

@@ -41,6 +41,7 @@
</div>
</div>
</div>
<input type="hidden" name="prodExposeFieldMapping_token" value="{{ app['session'].get('prodExposeFieldMapping_token') }}">
</form>
{% else %}
<h3>{{ 'expose::setting You have to select an expose to continue' | trans }}</h3>
@@ -76,6 +77,7 @@
</div>
</div>
</div>
<input type="hidden" name="prodExposeSubdefMapping_token" value="{{ app['session'].get('prodExposeSubdefMapping_token') }}">
</form>
</div>
</div>

View File

@@ -131,7 +131,7 @@
</div>
</div>
</div>
<input type="hidden" name="prodExposeNew_token" value="{{ app['session'].get('prodExposeNew_token') }}">
</form>
@@ -373,7 +373,8 @@
dataType: 'json',
data: {
exposeName: $('#expose_list').val(),
publicationData: $('#DIALOG-expose-add').find('#advancedSetting').val()
publicationData: $('#DIALOG-expose-add').find('#advancedSetting').val(),
prodExposeNew_token: $('#publication-json input[name="prodExposeNew_token"]').val()
},
success: function (data) {
if (data.success) {

View File

@@ -17,6 +17,7 @@
<div>
<button class="btn btn-primary auth-sign-in">{{ 'prod:expose:connection:Sign in' |trans }}</button>
</div>
<input type="hidden" name="prodExposeLogin_token" value="{{ app['session'].get('prodExposeLogin_token') }}">
</form>
</div>
</div>

View File

@@ -73,6 +73,7 @@
{% if capabilitiesEdit %}
<div class="set-cover" style="position: absolute;bottom: 0;cursor: pointer;" title="Set as Cover"
data-publication-id="{{ publicationId }}" data-asset-id="{{ asset.id }}">
<input name="prodExposeEdit_token" type="hidden" value="{{ app['session'].get('prodExposeEdit_token') }}"/>
<img src="/assets/common/images/icons/icon_story.gif" title="Set as Cover">
</div>

View File

@@ -116,6 +116,7 @@
<img src="/assets/common/images/icons/loader414141.gif" />
</span>
</div>
<input type="hidden" name="prodPropertyStatus_token" value="{{ app['session'].get('prodPropertyStatus_token') }}">
</form>
</div>
<div id="type-status"></div>

View File

@@ -52,4 +52,5 @@
<img src="/assets/common/images/icons/loader414141.gif" />
</span>
</div>
<input type="hidden" name="prodPropertyType_token" value="{{ app['session'].get('prodPropertyType_token') }}">
</form>

View File

@@ -508,6 +508,7 @@
{% endif %}
</div>
<input type="hidden" name="prodShareBasket_token" value="{{ app['session'].get('prodShareBasket_token') }}">
</form>
<div class="footer">

View File

@@ -61,7 +61,7 @@
</div>
{# subdef section #}
<div id="subdefs" class="tabBox">
<form id="new-img-form" action="{{ path('prod_tools_image') }}" method="post">
<form id="new-img-form" action="{{ path('prod_tools_image') }}" method="post" name="prodToolsSubdef">
<fieldset style='border:1px solid #999; padding:20px;'>
<legend style="margin-bottom: 0px;">&nbsp;<b>{{ "Reconstruire les sous definitions" | trans }}</b>&nbsp;</legend>
{% if nbSubdefSubstitute > 0 %}
@@ -107,7 +107,9 @@
<div class="confirm_block text-center hide" style="margin-top: 45px;">
<span class="alert alert-info">
{{ 'prod::tool:recreatesubviews: warning for rebuild sub-definitions' | trans }}
</span></div>
</span>
</div>
<input type="hidden" name="prodToolsSubdef_token" value="{{ app['session'].get('prodToolsSubdef_token') }}">
</form>
</div>
@@ -136,6 +138,7 @@
<button class="action_submiter btn btn-inverse">{{ "validate"|trans }}</button>
<button class="action_cancel btn btn-inverse">{{ "cancel"|trans }}</button>
</div>
<input type="hidden" name="prodToolsRotate_token" value="{{ app['session'].get('prodToolsRotate_token') }}">
</form>
</div>
@@ -176,6 +179,7 @@
<button class="iframe_submiter btn btn-inverse">{{ "validate" | trans }}</button>
<button class="action_cancel btn btn-inverse">{{ "cancel" | trans }}</button>
</div>
<input type="hidden" name="prodToolsHDSubstitution_token" value="{{ app['session'].get('prodToolsHDSubstitution_token') }}">
</form>
<div class='resultAction'></div>
</div>
@@ -202,6 +206,7 @@
<button class="iframe_submiter btn btn-inverse">{{ "validate" | trans }}</button>
<button class="action_cancel btn btn-inverse">{{ "cancel" | trans }}</button>
</div>
<input type="hidden" name="prodToolsThumbSubstitution_token" value="{{ app['session'].get('prodToolsThumbSubstitution_token') }}">
</form>
<div class='resultAction'></div>
</div>

View File

@@ -38,5 +38,6 @@
<input type="hidden" name="act" value="WORK">
<input type="hidden" name="lst" value="{{ records.serializedList() }}">
<input type="hidden" name="prodMoveCollection_token" value="{{ app['session'].get('prodMoveCollection_token') }}">
</form>
</div>

View File

@@ -37,6 +37,7 @@
<img src="/assets/common/images/icons/loader000.gif"/>
</span>
</div>
<input type="hidden" name="prodDeleteRecord_token" value="{{ app['session'].get('prodDeleteRecord_token') }}">
</form>
{% elseif records.received().count() == 0 %}
<div class="well-small" style="text-align:center;">

View File

@@ -191,7 +191,8 @@
</div>
</div>
</form>
<input type="hidden" name="prodPrint_token" value="{{ app['session'].get('prodPrint_token') }}">
</form>
<script type="text/javascript">
$(document).ready(function() {

View File

@@ -744,6 +744,7 @@
</tr>
</table>
</div>
<input type="hidden" name="searchForm_token" value="{{ app['session'].get('searchForm_token') }}">
</form>
<div id="facet_filter_in_search" style="width:100%;height:40px;overflow-y: scroll;">
</div>

View File

@@ -30,6 +30,7 @@
</button>
<input type="button" class="th_clear"/>
</div>
<input type="hidden" name="prodTabThesaurus_token" value="{{ app['session'].get('prodTabThesaurus_token') }}">
</form>
</div>
<div id="THPD_T">

View File

@@ -237,6 +237,9 @@
type: 'POST',
url: '/prod/lazaret/' + lazaretId + '/deny/',
dataType: 'json',
data: {
'prodLazaret_token' : form.find('input[name=prodLazaret_token]').val()
},
beforeSend: function () {
startAjax(that);
},
@@ -530,6 +533,7 @@
{% endif %}
</div>
</div>
<input type="hidden" name="prodLazaret_token" value="{{ app['session'].get('prodLazaret_token') }}">
</form>
<div class="hidden form-backup"></div>
{# bloc to backup initial value of status list#}

View File

@@ -140,7 +140,7 @@
{# download box #}
<div class="download-box"></div>
</div>
<input type="hidden" name="prodUpload_token" value="{{ app['session'].get('prodUpload_token') }}">
</form>
{% else %}
{{ 'You can not upload files' | trans }}

View File

@@ -20,6 +20,7 @@
<option value="res" id="connections_res">{{ 'report:: (connexions) res' | trans }}</option>
</select>
</div>
<input type="hidden" name="reportConnection_token" value="{{ app['session'].get('reportConnection_token') }}">
{% endblock form_connexion %}
</form>
@@ -57,6 +58,7 @@
{% endfor %}
</select>
</div>
<input type="hidden" name="reportDownload_token" value="{{ app['session'].get('reportDownload_token') }}">
</form>
<div class="form_submit">
@@ -115,6 +117,7 @@
</select>
</div>
<input type="hidden" name="reportRecord_token" value="{{ app['session'].get('reportRecord_token') }}">
</form>
<div class="form_submit">

View File

@@ -292,13 +292,15 @@ class LightboxTest extends \PhraseanetAuthenticatedWebTestCase
$validationBasket = $app['orm.em']->find('Phraseanet:Basket', 4);
$validationBasketElement = $validationBasket->getElements()->first();
$client->request('POST', '/lightbox/ajax/SET_NOTE/' . $validationBasketElement->getId() . '/');
$randomValue = $this->setSessionFormToken('lightbox');
$client->request('POST', '/lightbox/ajax/SET_NOTE/' . $validationBasketElement->getId() . '/', ['lightbox_token' => $randomValue]);
$this->assertEquals(400, $client->getResponse()->getStatusCode());
$client->request(
'POST'
, '/lightbox/ajax/SET_NOTE/' . $validationBasketElement->getId() . '/'
, ['note' => 'une jolie note']
, ['note' => 'une jolie note', 'lightbox_token' => $randomValue]
);
$this->assertEquals(200, $client->getResponse()->getStatusCode(), sprintf('set note to element %s ', $validationBasketElement->getId()));

View File

@@ -20,6 +20,8 @@ class BasketTest extends \PhraseanetAuthenticatedWebTestCase
self::$DI['record_2'];
$route = '/prod/baskets/';
$randomValue = $this->setSessionFormToken('prodCreateBasket');
$records = [
self::$DI['record_1']->get_serialize_key(),
self::$DI['record_2']->get_serialize_key(),
@@ -34,7 +36,9 @@ class BasketTest extends \PhraseanetAuthenticatedWebTestCase
'POST', $route, [
'name' => 'panier',
'desc' => 'mon beau panier',
'lst' => $lst]
'lst' => $lst,
'prodCreateBasket_token' => $randomValue
]
);
$response = self::$DI['client']->getResponse();
@@ -60,6 +64,8 @@ class BasketTest extends \PhraseanetAuthenticatedWebTestCase
$query = $entityManager->createQuery('SELECT COUNT(b.id) FROM Phraseanet:Basket b');
$count = $query->getSingleScalarResult();
$randomValue = $this->setSessionFormToken('prodCreateBasket');
$route = '/prod/baskets/';
$client = $this->getClient();
@@ -69,6 +75,7 @@ class BasketTest extends \PhraseanetAuthenticatedWebTestCase
[
'name' => 'panier',
'desc' => 'mon beau panier',
'prodCreateBasket_token' => $randomValue
],
[],
[
@@ -200,10 +207,14 @@ class BasketTest extends \PhraseanetAuthenticatedWebTestCase
$basket = self::$DI['app']['orm.em']->find('Phraseanet:Basket', 1);
$route = sprintf('/prod/baskets/%s/update/', $basket->getId());
$randomValue = $this->setSessionFormToken('prodBasketRename');
self::$DI['client']->request(
'POST', $route, [
'name' => 'new_name',
'description' => 'new_desc']
'description' => 'new_desc',
'prodBasketRename_token' => $randomValue
]
);
$response = self::$DI['client']->getResponse();
@@ -217,10 +228,13 @@ class BasketTest extends \PhraseanetAuthenticatedWebTestCase
$basket = self::$DI['app']['orm.em']->find('Phraseanet:Basket', 1);
$route = sprintf('/prod/baskets/%s/update/', $basket->getId());
$randomValue = $this->setSessionFormToken('prodBasketRename');
self::$DI['client']->request(
'POST', $route, [
'name' => 'new_name',
'description' => 'new_desc'
'description' => 'new_desc',
'prodBasketRename_token' => $randomValue
], [], [
"HTTP_ACCEPT" => "application/json"]
);

View File

@@ -22,6 +22,8 @@ class DownloadTest extends \PhraseanetAuthenticatedWebTestCase
public function testDownloadRecords()
{
$triggered = false;
$randomValue = $this->setSessionFormToken('prodExportDownload');
self::$DI['app']['dispatcher']->addListener(PhraseaEvents::EXPORT_CREATE, function (Event $event) use (&$triggered) {
$triggered = true;
});
@@ -30,7 +32,8 @@ class DownloadTest extends \PhraseanetAuthenticatedWebTestCase
'ssttid' => '',
'obj' => ['preview', 'document'],
'title' => 'export_title_test',
'businessfields' => '1'
'businessfields' => '1',
'prodExportDownload_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();
@@ -46,6 +49,8 @@ class DownloadTest extends \PhraseanetAuthenticatedWebTestCase
public function testDownloadRestricted()
{
$triggered = false;
$randomValue = $this->setSessionFormToken('prodExportDownload');
self::$DI['app']['dispatcher']->addListener(PhraseaEvents::EXPORT_CREATE, function (Event $event) use (&$triggered) {
$triggered = true;
});
@@ -84,7 +89,8 @@ class DownloadTest extends \PhraseanetAuthenticatedWebTestCase
'ssttid' => '',
'obj' => ['preview', 'document'],
'title' => 'export_title_test',
'businessfields' => '1'
'businessfields' => '1',
'prodExportDownload_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();
@@ -100,6 +106,7 @@ class DownloadTest extends \PhraseanetAuthenticatedWebTestCase
public function testDownloadBasket()
{
$basket = self::$DI['app']['orm.em']->find('Phraseanet:Basket', 4);
$randomValue = $this->setSessionFormToken('prodExportDownload');
$triggered = false;
self::$DI['app']['dispatcher']->addListener(PhraseaEvents::EXPORT_CREATE, function (Event $event) use (&$triggered) {
@@ -111,7 +118,8 @@ class DownloadTest extends \PhraseanetAuthenticatedWebTestCase
'ssttid' => $basket->getId(),
'obj' => ['preview', 'document'],
'title' => 'export_title_test',
'businessfields' => '1'
'businessfields' => '1',
'prodExportDownload_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();
@@ -127,6 +135,7 @@ class DownloadTest extends \PhraseanetAuthenticatedWebTestCase
public function testDownloadBasketValidation()
{
$basket = self::$DI['app']['orm.em']->find('Phraseanet:Basket', 4);
$randomValue = $this->setSessionFormToken('prodExportDownload');
$triggered = false;
self::$DI['app']['dispatcher']->addListener(PhraseaEvents::EXPORT_CREATE, function (Event $event) use (&$triggered) {
@@ -138,7 +147,8 @@ class DownloadTest extends \PhraseanetAuthenticatedWebTestCase
'ssttid' => $basket->getId(),
'obj' => ['preview', 'document'],
'title' => 'export_title_test',
'businessfields' => '1'
'businessfields' => '1',
'prodExportDownload_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();

View File

@@ -87,13 +87,17 @@ class ExportTest extends \PhraseanetAuthenticatedWebTestCase
*/
public function testExportFtpNoDocs()
{
$randomValue = $this->setSessionFormToken('prodExportFTP');
self::$DI['client']->request('POST', '/prod/export/ftp/', [
'address' => 'test.ftp',
'login' => 'login',
'dest_folder' => 'documents',
'prefix_folder' => 'documents',
'obj' => ['preview']
'obj' => ['preview'],
'prodExportFTP_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();
$this->assertTrue($response->isOk());
$datas = (array) json_decode($response->getContent());
@@ -109,7 +113,8 @@ class ExportTest extends \PhraseanetAuthenticatedWebTestCase
*/
public function testExportFtpBadRequest($params)
{
self::$DI['client']->request('POST', '/prod/export/ftp/', $params);
$randomValue = $this->setSessionFormToken('prodExportFTP');
self::$DI['client']->request('POST', '/prod/export/ftp/', array_merge($params, ['prodExportFTP_token' => $randomValue]));
$this->assertBadResponse(self::$DI['client']->getResponse());
}
@@ -131,6 +136,7 @@ class ExportTest extends \PhraseanetAuthenticatedWebTestCase
public function testExportFtp()
{
$app = $this->getApplication();
$randomValue = $this->setSessionFormToken('prodExportFTP');
$bkp = $app['conf']->get('registry');
@@ -150,7 +156,8 @@ class ExportTest extends \PhraseanetAuthenticatedWebTestCase
'login' => $user->getEmail(),
'dest_folder' => '/home/test/',
'prefix_folder' => 'test2/',
'obj' => ['preview']
'obj' => ['preview'],
'prodExportFTP_token' => $randomValue
]);
$response = $this->getClient()->getResponse();
@@ -172,10 +179,13 @@ class ExportTest extends \PhraseanetAuthenticatedWebTestCase
// deliver method removed in the listener
// $this->mockNotificationDeliverer('Alchemy\Phrasea\Notification\Mail\MailRecordsExport');
$randomValue = $this->setSessionFormToken('prodExportEmail');
$this->getClient()->request('POST', '/prod/export/mail/', [
'lst' => $this->getRecord1()->getId(),
'destmail' => 'user@example.com',
'obj' => ['preview'],
'prodExportEmail_token' => $randomValue
]);
$response = $this->getClient()->getResponse();

View File

@@ -169,10 +169,14 @@ class LazaretTest extends \PhraseanetAuthenticatedWebTestCase
->method('flush');
self::$DI['app']['orm.em'] = $em;
$randomValue = $this->setSessionFormToken('prodLazaret');
self::$DI['client']->request('POST', '/prod/lazaret/' . $id . '/force-add/', [
'bas_id' => $lazaretFile->getBaseId(),
'keep_attributes' => 1,
'attributes' => [1, 2, 3, 4] //Check only the four first attributes
'attributes' => [1, 2, 3, 4], //Check only the four first attributes
'prodLazaret_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();
@@ -191,10 +195,13 @@ class LazaretTest extends \PhraseanetAuthenticatedWebTestCase
{
$id = 1;
$randomValue = $this->setSessionFormToken('prodLazaret');
//Ommit base_id mandatory param
self::$DI['client']->request('POST', '/prod/lazaret/' . $id . '/force-add/', [
'keep_attributes' => 1,
'attributes' => [1, 2, 3, 4] //Check only the four first attributes
'attributes' => [1, 2, 3, 4], //Check only the four first attributes
'prodLazaret_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();
@@ -208,10 +215,13 @@ class LazaretTest extends \PhraseanetAuthenticatedWebTestCase
*/
public function testAddElementException()
{
$randomValue = $this->setSessionFormToken('prodLazaret');
self::$DI['client']->request('POST', '/prod/lazaret/99999/force-add/', [
'bas_id' => 1,
'keep_attributes' => 1,
'attributes' => [1, 2, 3, 4] //Check only the four first attributes
'attributes' => [1, 2, 3, 4], //Check only the four first attributes
'prodLazaret_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();
@@ -226,10 +236,11 @@ class LazaretTest extends \PhraseanetAuthenticatedWebTestCase
public function testDenyElement()
{
$lazaretFile = self::$DI['lazaret_1'];
$randomValue = $this->setSessionFormToken('prodLazaret');
$route = sprintf('/prod/lazaret/%s/deny/', $lazaretFile->getId());
self::$DI['client']->request('POST', $route);
self::$DI['client']->request('POST', $route, ['prodLazaret_token' => $randomValue]);
$response = self::$DI['client']->getResponse();
@@ -272,9 +283,11 @@ class LazaretTest extends \PhraseanetAuthenticatedWebTestCase
*/
public function testDenyElementException()
{
$randomValue = $this->setSessionFormToken('prodLazaret');
$route = sprintf('/prod/lazaret/%s/deny/', '99999');
self::$DI['client']->request('POST', $route);
self::$DI['client']->request('POST', $route, ['prodLazaret_token' => $randomValue]);
$response = self::$DI['client']->getResponse();
@@ -362,8 +375,12 @@ class LazaretTest extends \PhraseanetAuthenticatedWebTestCase
});
self::$DI['app']['orm.em'] = $em;
$randomValue = $this->setSessionFormToken('prodLazaret');
self::$DI['client']->request('POST', '/prod/lazaret/' . $id . '/accept/', [
'record_id' => self::$DI['record_1']->get_record_id()
'record_id' => self::$DI['record_1']->get_record_id(),
'prodLazaret_token' => $randomValue
]);
$this->assertTrue($called);
@@ -400,8 +417,11 @@ class LazaretTest extends \PhraseanetAuthenticatedWebTestCase
$id = 1;
$randomValue = $this->setSessionFormToken('prodLazaret');
self::$DI['client']->request('POST', '/prod/lazaret/' . $id . '/accept/', [
'record_id' => self::$DI['record_1']->get_record_id()
'record_id' => self::$DI['record_1']->get_record_id(),
'prodLazaret_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();
@@ -415,9 +435,11 @@ class LazaretTest extends \PhraseanetAuthenticatedWebTestCase
*/
public function testAcceptElementException()
{
$randomValue = $this->setSessionFormToken('prodLazaret');
$route = sprintf('/prod/lazaret/%s/accept/', '99999');
self::$DI['client']->request('POST', $route, ['record_id' => 1]);
self::$DI['client']->request('POST', $route, ['record_id' => 1, 'prodLazaret_token' => $randomValue]);
$response = self::$DI['client']->getResponse();
@@ -432,8 +454,10 @@ class LazaretTest extends \PhraseanetAuthenticatedWebTestCase
{
$id = 1;
$randomValue = $this->setSessionFormToken('prodLazaret');
//Ommit record_id mandatory param
self::$DI['client']->request('POST', '/prod/lazaret/' . $id . '/accept/');
self::$DI['client']->request('POST', '/prod/lazaret/' . $id . '/accept/', ['prodLazaret_token' => $randomValue]);
$response = self::$DI['client']->getResponse();

View File

@@ -19,6 +19,7 @@ class OrderTest extends \PhraseanetAuthenticatedWebTestCase
public function testCreateOrder()
{
$app = $this->getApplication();
$randomValue = $this->setSessionFormToken('prodExportOrder');
$triggered = false;
$app['dispatcher']->addListener(PhraseaEvents::ORDER_CREATE, function () use (&$triggered) {
@@ -27,7 +28,8 @@ class OrderTest extends \PhraseanetAuthenticatedWebTestCase
$response = $this->request('POST', '/prod/order/', [
'lst' => $this->getRecord1()->getId(),
'deadline' => '+10 minutes'
'deadline' => '+10 minutes',
'prodExportOrder_token' => $randomValue
]);
$this->assertTrue($response->isRedirect(), 'Response should be redirect');
@@ -41,6 +43,7 @@ class OrderTest extends \PhraseanetAuthenticatedWebTestCase
public function testCreateOrderJson()
{
$app = $this->getApplication();
$randomValue = $this->setSessionFormToken('prodExportOrder');
$triggered = false;
$app['dispatcher']->addListener(PhraseaEvents::ORDER_CREATE, function (Event $event) use (&$triggered) {
@@ -49,7 +52,8 @@ class OrderTest extends \PhraseanetAuthenticatedWebTestCase
$response = $this->XMLHTTPRequest('POST', '/prod/order/', [
'lst' => $this->getRecord1()->getId(),
'deadline' => '+10 minutes'
'deadline' => '+10 minutes',
'prodExportOrder_token' => $randomValue
]);
$this->assertTrue($response->isOk(), 'Invalid response from create order');

View File

@@ -33,6 +33,8 @@ class PrinterTest extends \PhraseanetAuthenticatedWebTestCase
public function testRoutePrintPdf()
{
$randomValue = $this->setSessionFormToken('prodPrint');
$records = [
self::$DI['record_1']->get_serialize_key(),
self::$DI['record_2']->get_serialize_key(),
@@ -53,7 +55,8 @@ class PrinterTest extends \PhraseanetAuthenticatedWebTestCase
foreach ($layouts as $layout) {
self::$DI['client']->request('POST', '/prod/printer/print.pdf', [
'lst' => $lst,
'lay' => $layout
'lay' => $layout,
'prodPrint_token' => $randomValue
]
);

View File

@@ -100,6 +100,7 @@ class PropertyTest extends \PhraseanetAuthenticatedWebTestCase
->will($this->returnValue($acl));
self::$DI['app']['acl'] = $aclProvider;
$randomValue = $this->setSessionFormToken('prodPropertyStatus');
self::$DI['client']->request('POST', '/prod/records/property/status/', [
'apply_to_children' => [$story->getDataboxId() => true],
@@ -108,8 +109,10 @@ class PropertyTest extends \PhraseanetAuthenticatedWebTestCase
],
'lst' => implode(';', [
$record->getId(),$story->getId()
])
]),
'prodPropertyStatus_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();
$datas = (array) json_decode($response->getContent());
$this->assertArrayHasKey('success', $datas);
@@ -152,6 +155,7 @@ class PropertyTest extends \PhraseanetAuthenticatedWebTestCase
$file = new File(self::$DI['app'], self::$DI['app']['mediavorus']->guess(__DIR__ . '/../../../../../files/cestlafete.jpg'), self::$DI['collection']);
$record = \record_adapter::createFromFile($file, self::$DI['app']);
$record2 = \record_adapter::createFromFile($file, self::$DI['app']);
$randomValue = $this->setSessionFormToken('prodPropertyType');
self::$DI['client']->request('POST', '/prod/records/property/type/', [
'lst' => implode(';', [
@@ -160,7 +164,8 @@ class PropertyTest extends \PhraseanetAuthenticatedWebTestCase
'types' => [
$record->getId() => 'document',
$record2->getId() => 'flash',
]
],
'prodPropertyType_token' => $randomValue
]);
$response = self::$DI['client']->getResponse();
$datas = (array) json_decode($response->getContent());

View File

@@ -29,11 +29,12 @@ class QueryTest extends \PhraseanetAuthenticatedWebTestCase
->getMock();
self::$DI['app']['manipulator.user'] = $userManipulator;
$randomValue = $this->setSessionFormToken('searchForm');
$userManipulator->expects($this->once())->method('logQuery');
$client = $this->getClient();
$client->request('POST', $route);
$client->request('POST', $route, ['searchForm_token' => $randomValue]);
$response = $client->getResponse();
$this->assertEquals('application/json', $response->headers->get('Content-type'));

View File

@@ -30,7 +30,10 @@ class RecordsTest extends \PhraseanetAuthenticatedWebTestCase
{
$file = new File(self::$DI['app'], self::$DI['app']['mediavorus']->guess(__DIR__ . '/../../../../../files/cestlafete.jpg'), self::$DI['collection']);
$record = \record_adapter::createFromFile($file, self::$DI['app']);
$response = $this->XMLHTTPRequest('POST', '/prod/records/delete/', ['lst' => $record->getId()]);
$randomValue = $this->setSessionFormToken('prodDeleteRecord');
$response = $this->XMLHTTPRequest('POST', '/prod/records/delete/', ['lst' => $record->getId(), 'prodDeleteRecord_token' => $randomValue]);
$datas = (array) json_decode($response->getContent());
$this->assertContains($record->getId(), $datas);
try {

View File

@@ -15,6 +15,8 @@ class StoryTest extends \PhraseanetAuthenticatedWebTestCase
public function testRootPost()
{
self::$DI['app']['phraseanet.SE'] = $this->createSearchEngineMock();
$randomValue = $this->setSessionFormToken('prodCreateStory');
$route = "/prod/story/";
$collections = self::$DI['app']->getAclForUser(self::$DI['app']->getAuthenticatedUser())
@@ -25,7 +27,8 @@ class StoryTest extends \PhraseanetAuthenticatedWebTestCase
self::$DI['client']->request(
'POST', $route, [
'base_id' => $collection->get_base_id(),
'name' => ['1-1' => 'test story'] //db-metastructId => storyname
'name' => ['1-1' => 'test story'], //db-metastructId => storyname
'prodCreateStory_token' => $randomValue
]
);
@@ -44,6 +47,7 @@ class StoryTest extends \PhraseanetAuthenticatedWebTestCase
public function testRootPostJSON()
{
$randomValue = $this->setSessionFormToken('prodCreateStory');
$route = "/prod/story/";
$collections = self::$DI['app']->getAclForUser(self::$DI['app']->getAuthenticatedUser())
@@ -52,10 +56,17 @@ class StoryTest extends \PhraseanetAuthenticatedWebTestCase
$collection = array_shift($collections);
$crawler = self::$DI['client']->request(
'POST', $route, [
'base_id' => $collection->get_base_id(),
'name' => 'test story'], [], [
"HTTP_ACCEPT" => "application/json"]
'POST',
$route,
[
'base_id' => $collection->get_base_id(),
'name' => 'test story',
'prodCreateStory_token' => $randomValue
],
[],
[
"HTTP_ACCEPT" => "application/json"
]
);
$response = self::$DI['client']->getResponse();

View File

@@ -35,9 +35,13 @@ class ToolsTest extends \PhraseanetAuthenticatedWebTestCase
self::$DI['app']['phraseanet.SE'] = $this->createSearchEngineMock();
$record = self::$DI['record_1'];
$randomValue = bin2hex(random_bytes(35));
self::$DI['app']['session']->set('prodToolsHDSubstitution_token', $randomValue);
$crawler = self::$DI['client']->request('POST', '/prod/tools/hddoc/', [
'sbas_id' => $record->get_sbas_id(),
'record_id' => $record->get_record_id(),
'prodToolsHDSubstitution_token' => $randomValue
], [
'newHD' => new UploadedFile(
$this->tmpFile, 'KIKOO.JPG', 'image/jpg', 2000
@@ -53,10 +57,13 @@ class ToolsTest extends \PhraseanetAuthenticatedWebTestCase
public function testRouteChangeThumb()
{
$record = self::$DI['record_1'];
$randomValue = bin2hex(random_bytes(35));
self::$DI['app']['session']->set('prodToolsThumbSubstitution_token', $randomValue);
$crawler = self::$DI['client']->request('POST', '/prod/tools/chgthumb/', [
'sbas_id' => $record->get_sbas_id(),
'record_id' => $record->get_record_id(),
'prodToolsThumbSubstitution_token' => $randomValue
], [
'newThumb' => new UploadedFile(
$this->tmpFile, 'KIKOO.JPG', 'image/jpg', 2000

View File

@@ -73,10 +73,13 @@ class UploadTest extends \PhraseanetAuthenticatedWebTestCase
->disableOriginalConstructor()
->getMock();
$randomValue = $this->setSessionFormToken('prodUpload');
$data = DataURI\Data::buildFromFile(__DIR__ . '/../../../../../files/cestlafete.jpg');
$params = [
'base_id' => self::$DI['collection']->get_base_id(),
'b64_image' => DataURI\Dumper::dump($data)
'base_id' => self::$DI['collection']->get_base_id(),
'b64_image' => DataURI\Dumper::dump($data),
'prodUpload_token' => $randomValue
];
$files = [
@@ -122,8 +125,11 @@ class UploadTest extends \PhraseanetAuthenticatedWebTestCase
->disableOriginalConstructor()
->getMock();
$randomValue = $this->setSessionFormToken('prodUpload');
$params = [
'base_id' => self::$DI['collection']->get_base_id()
'base_id' => self::$DI['collection']->get_base_id(),
'prodUpload_token' => $randomValue
];
$files = [
@@ -162,8 +168,11 @@ class UploadTest extends \PhraseanetAuthenticatedWebTestCase
$this->mockNotificationDeliverer('Alchemy\Phrasea\Notification\Mail\MailInfoRecordQuarantined');
$this->mockUserNotificationSettings('eventsmanager_notify_uploadquarantine');
$randomValue = $this->setSessionFormToken('prodUpload');
$params = [
'base_id' => self::$DI['collection']->get_base_id()
'base_id' => self::$DI['collection']->get_base_id(),
'prodUpload_token' => $randomValue
];
$files = [
@@ -313,9 +322,12 @@ class UploadTest extends \PhraseanetAuthenticatedWebTestCase
public function testUploadForceRecord()
{
self::$DI['app']['phraseanet.SE'] = $this->createSearchEngineMock();
$randomValue = $this->setSessionFormToken('prodUpload');
$params = [
'base_id' => self::$DI['collection']->get_base_id(),
'forceAction' => Manager::FORCE_RECORD,
'base_id' => self::$DI['collection']->get_base_id(),
'forceAction' => Manager::FORCE_RECORD,
'prodUpload_token' => $randomValue
];
$files = [
@@ -349,10 +361,13 @@ class UploadTest extends \PhraseanetAuthenticatedWebTestCase
public function testUploadRecordStatus()
{
self::$DI['app']['phraseanet.SE'] = $this->createSearchEngineMock();
$randomValue = $this->setSessionFormToken('prodUpload');
$params = [
'base_id' => self::$DI['collection']->get_base_id(),
'forceAction' => Manager::FORCE_RECORD,
'status' => [ self::$DI['collection']->get_base_id() => [ 4 => 1]],
'base_id' => self::$DI['collection']->get_base_id(),
'forceAction' => Manager::FORCE_RECORD,
'status' => [ self::$DI['collection']->get_base_id() => [ 4 => 1]],
'prodUpload_token' => $randomValue
];
$files = [

View File

@@ -811,4 +811,12 @@ abstract class PhraseanetTestCase extends WebTestCase
return $mock;
}
protected function setSessionFormToken($formName)
{
$randomValue = bin2hex(random_bytes(35));
self::$DI['app']['session']->set($formName.'_token', $randomValue);
return $randomValue;
}
}

View File

@@ -76,6 +76,9 @@ class record_adapterTest extends \PhraseanetAuthenticatedTestCase
$app['phraseanet.user-query']->expects($this->any())->method('who_have_right')->will($this->returnSelf());
$app['phraseanet.user-query']->expects($this->any())->method('execute')->will($this->returnSelf());
$randomValue = bin2hex(random_bytes(35));
$app['session']->set('prodExportOrder_token', $randomValue);
$app['notification.deliverer'] = $this->getMockBuilder('Alchemy\Phrasea\Notification\Deliverer')
->disableOriginalConstructor()
->getMock();
@@ -87,7 +90,8 @@ class record_adapterTest extends \PhraseanetAuthenticatedTestCase
$this->getClient()->request(
'POST', $app['url_generator']->generate('prod_order_new'), [
'lst' => $this->getRecord1()->getId(),
'deadline' => '+10 minutes'
'deadline' => '+10 minutes',
'prodExportOrder_token' => $randomValue
]);
$this->assertTrue($triggered);