From 573fa9f7f3c2edae40299365e6912ccf1dc09bd7 Mon Sep 17 00:00:00 2001 From: Kevin Papst Date: Thu, 9 Dec 2021 01:36:58 +0100 Subject: [PATCH] fix create invoice token issue (#3007) --- src/Constants.php | 4 ++-- src/Controller/InvoiceController.php | 22 ++++------------------ templates/invoice/index.html.twig | 6 +++--- tests/Controller/InvoiceControllerTest.php | 17 ++++++++++++++--- 4 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/Constants.php b/src/Constants.php index ef923423..1098424d 100644 --- a/src/Constants.php +++ b/src/Constants.php @@ -17,11 +17,11 @@ class Constants /** * The current release version */ - public const VERSION = '1.16.7'; + public const VERSION = '1.16.8'; /** * The current release: major * 10000 + minor * 100 + patch */ - public const VERSION_ID = 11607; + public const VERSION_ID = 11608; /** * The current release status, either "stable" or "dev" */ diff --git a/src/Controller/InvoiceController.php b/src/Controller/InvoiceController.php index 8e1f351c..5a618f8f 100644 --- a/src/Controller/InvoiceController.php +++ b/src/Controller/InvoiceController.php @@ -134,22 +134,16 @@ final class InvoiceController extends AbstractController } /** - * @Route(path="/preview/{customer}", name="invoice_preview", methods={"GET"}) + * @Route(path="/preview/{customer}/{token}", name="invoice_preview", methods={"GET"}) * @Security("is_granted('access', customer)") * @Security("is_granted('create_invoice')") */ - public function previewAction(Customer $customer, Request $request, SystemConfiguration $configuration): Response + public function previewAction(Customer $customer, string $token, Request $request, SystemConfiguration $configuration): Response { if (!$this->templateRepository->hasTemplate()) { return $this->redirectToRoute('invoice'); } - $token = null; - if ($request->query->has('token')) { - $token = $request->query->get('token'); - $request->query->remove('token'); - } - if (!$this->isCsrfTokenValid('invoice.preview', $token)) { $this->flashError('action.csrf.error'); @@ -183,30 +177,22 @@ final class InvoiceController extends AbstractController } /** - * @Route(path="/save-invoice/{customer}/{template}", name="invoice_create", methods={"GET"}) + * @Route(path="/save-invoice/{customer}/{template}/{token}", name="invoice_create", methods={"GET"}) * @Security("is_granted('access', customer)") * @Security("is_granted('create_invoice')") */ - public function createInvoiceAction(Customer $customer, InvoiceTemplate $template, Request $request, SystemConfiguration $configuration, CsrfTokenManagerInterface $csrfTokenManager): Response + public function createInvoiceAction(Customer $customer, InvoiceTemplate $template, string $token, Request $request, SystemConfiguration $configuration, CsrfTokenManagerInterface $csrfTokenManager): Response { if (!$this->templateRepository->hasTemplate()) { return $this->redirectToRoute('invoice'); } - $token = null; - if ($request->query->has('token')) { - $token = $request->query->get('token'); - $request->query->remove('token'); - } - if (!$this->isCsrfTokenValid('invoice.create', $token)) { $this->flashError('action.csrf.error'); return $this->redirectToRoute('invoice'); } - $csrfTokenManager->refreshToken('invoice.create'); - $query = $this->getDefaultQuery(); $form = $this->getToolbarForm($query, $configuration->find('invoice.simple_form')); if ($this->handleSearch($form, $request)) { diff --git a/templates/invoice/index.html.twig b/templates/invoice/index.html.twig index f712cbd4..2e268235 100644 --- a/templates/invoice/index.html.twig +++ b/templates/invoice/index.html.twig @@ -109,8 +109,8 @@ {{ widgets.action_button('show', {'url': '#invoice_preview_details_' ~ model.customer.id, 'title': 'timesheet.all'|trans, 'class': 'btn btn-sm hidden-xs hidden-sm'}, 'link') }} - {{ widgets.action_button('print', {'url': '#', 'onclick': 'return singleInvoice(this)', 'title': 'button.preview'|trans, 'target': '_blank', 'class': 'btn btn-sm', 'attr': {'data-customer': model.customer.id, 'data-template': model.template.id, 'data-href': path('invoice_preview', {'customer': model.customer.id})}}) }} - {{ widgets.action_button('save', {'url': '#', 'onclick': 'return singleInvoice(this)', 'title': 'action.save'|trans, 'class': 'btn btn-sm', 'attr': {'data-customer': model.customer.id, 'data-template': model.template.id, 'data-href': path('invoice_create', {'customer': model.customer.id, 'template': model.template.id})}}, 'success') }} + {{ widgets.action_button('print', {'url': '#', 'onclick': 'return singleInvoice(this)', 'title': 'button.preview'|trans, 'target': '_blank', 'class': 'btn btn-sm', 'attr': {'data-customer': model.customer.id, 'data-template': model.template.id, 'data-href': path('invoice_preview', {'customer': model.customer.id, 'token': csrf_token('invoice.preview')})}}) }} + {{ widgets.action_button('save', {'url': '#', 'onclick': 'return singleInvoice(this)', 'title': 'action.save'|trans, 'class': 'btn btn-sm', 'attr': {'data-customer': model.customer.id, 'data-template': model.template.id, 'data-href': path('invoice_create', {'customer': model.customer.id, 'template': model.template.id, 'token': csrf_token('invoice.create')})}}, 'success') }} {{ model.calculator.timeWorked|duration(isDecimal) }} @@ -218,7 +218,7 @@ const overwrites = {'customers[]': link.dataset['customer'], 'template': link.dataset['template']}; const uri = formPlugin.convertFormDataToQueryString(document.getElementById('{{ formId }}'), overwrites); - link.href = link.dataset['href'] + '?token={{ csrf_token('invoice.preview') }}&' + uri; + link.href = link.dataset['href'] + '?' + uri; return true; } diff --git a/tests/Controller/InvoiceControllerTest.php b/tests/Controller/InvoiceControllerTest.php index 7f8403f3..31717751 100644 --- a/tests/Controller/InvoiceControllerTest.php +++ b/tests/Controller/InvoiceControllerTest.php @@ -194,7 +194,7 @@ class InvoiceControllerTest extends ControllerBaseTest /** @var CsrfToken $token */ $token = self::$container->get('security.csrf.token_manager')->getToken('invoice.create'); - $action = '/invoice/save-invoice/1/' . $template->getId() . '?token=' . $token->getValue() . '&' . http_build_query($urlParams); + $action = '/invoice/save-invoice/1/' . $template->getId() . '/' . $token->getValue() . '?' . http_build_query($urlParams); $this->request($client, $action); $this->assertIsRedirect($client); $this->assertRedirectUrl($client, '/invoice/show?id=', false); @@ -234,18 +234,29 @@ class InvoiceControllerTest extends ControllerBaseTest $dateRange = $begin->format('Y-m-d') . DateRangeType::DATE_SPACER . $end->format('Y-m-d'); + $form = $client->getCrawler()->filter('#invoice-print-form')->form(); + $node = $form->getFormNode(); + $node->setAttribute('action', $this->createUrl('/invoice/')); + $node->setAttribute('method', 'GET'); + $client->submit($form, [ + 'template' => $id, + 'daterange' => $dateRange, + 'customers' => [1], + ]); + + $this->assertTrue($client->getResponse()->isSuccessful()); + /** @var CsrfToken $token */ $token = self::$container->get('security.csrf.token_manager')->getToken('invoice.preview'); $params = [ - 'token' => $token->getValue(), 'daterange' => $dateRange, 'projects' => [1], 'template' => $id, 'customers[]' => 1 ]; - $action = '/invoice/preview/1?' . http_build_query($params); + $action = '/invoice/preview/1/' . $token->getValue() . '?' . http_build_query($params); $this->request($client, $action); $this->assertTrue($client->getResponse()->isSuccessful()); $node = $client->getCrawler()->filter('body');