Skip to content

Commit f62dcfa

Browse files
committed
MAGETWO-97671: Invalid action behavior
1 parent b771a6b commit f62dcfa

File tree

9 files changed

+251
-34
lines changed

9 files changed

+251
-34
lines changed

app/code/Magento/Email/Block/Adminhtml/Template/Preview.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
*/
1212
namespace Magento\Email\Block\Adminhtml\Template;
1313

14+
/**
15+
* Email template preview block.
16+
*/
1417
class Preview extends \Magento\Backend\Block\Widget
1518
{
1619
/**
@@ -49,6 +52,7 @@ public function __construct(
4952
* Prepare html output
5053
*
5154
* @return string
55+
* @SuppressWarnings(PHPMD.RequestAwareBlockMethod)
5256
*/
5357
protected function _toHtml()
5458
{
@@ -64,8 +68,6 @@ protected function _toHtml()
6468
$template->setTemplateStyles($this->getRequest()->getParam('styles'));
6569
}
6670

67-
$template->setTemplateText($this->_maliciousCode->filter($template->getTemplateText()));
68-
6971
\Magento\Framework\Profiler::start($this->profilerName);
7072

7173
$template->emulateDesign($storeId);
@@ -74,6 +76,7 @@ protected function _toHtml()
7476
[$template, 'getProcessedTemplate']
7577
);
7678
$template->revertDesign();
79+
$templateProcessed = $this->_maliciousCode->filter($templateProcessed);
7780

7881
if ($template->isPlain()) {
7982
$templateProcessed = "<pre>" . htmlspecialchars($templateProcessed) . "</pre>";
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Email\Controller\Adminhtml\Email\Template;
7+
8+
/**
9+
* Rendering popup email template.
10+
*/
11+
class Popup extends \Magento\Backend\App\Action
12+
{
13+
/**
14+
* @var \Magento\Framework\View\Result\PageFactory
15+
*/
16+
private $resultPageFactory;
17+
18+
/**
19+
* @param \Magento\Backend\App\Action\Context $context
20+
* @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
21+
*/
22+
public function __construct(
23+
\Magento\Backend\App\Action\Context $context,
24+
\Magento\Framework\View\Result\PageFactory $resultPageFactory
25+
) {
26+
parent::__construct($context);
27+
$this->resultPageFactory = $resultPageFactory;
28+
}
29+
30+
/**
31+
* Load the page.
32+
*
33+
* Load the page defined in view/adminhtml/layout/adminhtml_email_template_popup.xml
34+
*
35+
* @return \Magento\Framework\View\Result\Page
36+
*/
37+
public function execute()
38+
{
39+
return $this->resultPageFactory->create();
40+
}
41+
42+
/**
43+
* @inheritdoc
44+
*/
45+
protected function _isAllowed()
46+
{
47+
return $this->_authorization->isAllowed('Magento_Email::template');
48+
}
49+
}

app/code/Magento/Email/Controller/Adminhtml/Email/Template/Preview.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
*/
77
namespace Magento\Email\Controller\Adminhtml\Email\Template;
88

9+
/**
10+
* Rendering email template preview.
11+
*/
912
class Preview extends \Magento\Email\Controller\Adminhtml\Email\Template
1013
{
1114
/**
12-
* Preview transactional email action
15+
* Preview transactional email action.
1316
*
1417
* @return void
1518
*/
@@ -19,7 +22,7 @@ public function execute()
1922
$this->_view->loadLayout();
2023
$this->_view->getPage()->getConfig()->getTitle()->prepend(__('Email Preview'));
2124
$this->_view->renderLayout();
22-
$this->getResponse()->setHeader('Content-Security-Policy', "script-src 'none'");
25+
$this->getResponse()->setHeader('Content-Security-Policy', "script-src 'self'");
2326
} catch (\Exception $e) {
2427
$this->messageManager->addError(__('An error occurred. The email template can not be opened for preview.'));
2528
$this->_redirect('adminhtml/*/');

app/code/Magento/Email/Test/Unit/Block/Adminhtml/Template/PreviewTest.php

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6-
7-
// @codingStandardsIgnoreFile
8-
96
namespace Magento\Email\Test\Unit\Block\Adminhtml\Template;
107

8+
/**
9+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
10+
*/
1111
class PreviewTest extends \PHPUnit_Framework_TestCase
1212
{
1313
/**
@@ -36,7 +36,7 @@ protected function setUp()
3636
public function testToHtml($requestParamMap)
3737
{
3838
$storeId = 1;
39-
$template = $this->getMockBuilder('Magento\Email\Model\Template')
39+
$template = $this->getMockBuilder(\Magento\Email\Model\Template::class)
4040
->setMethods([
4141
'setDesignConfig',
4242
'getDesignConfig',
@@ -57,19 +57,19 @@ public function testToHtml($requestParamMap)
5757
->willReturn(new \Magento\Framework\DataObject(
5858
$designConfigData
5959
));
60-
$emailFactory = $this->getMock('Magento\Email\Model\TemplateFactory', ['create'], [], '', false);
60+
$emailFactory = $this->getMock(\Magento\Email\Model\TemplateFactory::class, ['create'], [], '', false);
6161
$emailFactory->expects($this->any())
6262
->method('create')
6363
->willReturn($template);
6464

65-
$request = $this->getMock('Magento\Framework\App\RequestInterface');
65+
$request = $this->getMock(\Magento\Framework\App\RequestInterface::class);
6666
$request->expects($this->any())->method('getParam')->willReturnMap($requestParamMap);
67-
$eventManage = $this->getMock('Magento\Framework\Event\ManagerInterface');
68-
$scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface');
69-
$design = $this->getMock('Magento\Framework\View\DesignInterface');
70-
$store = $this->getMock('Magento\Store\Model\Store', ['getId', '__wakeup'], [], '', false);
67+
$eventManage = $this->getMock(\Magento\Framework\Event\ManagerInterface::class);
68+
$scopeConfig = $this->getMock(\Magento\Framework\App\Config\ScopeConfigInterface::class);
69+
$design = $this->getMock(\Magento\Framework\View\DesignInterface::class);
70+
$store = $this->getMock(\Magento\Store\Model\Store::class, ['getId', '__wakeup'], [], '', false);
7171
$store->expects($this->any())->method('getId')->willReturn($storeId);
72-
$storeManager = $this->getMockBuilder('\Magento\Store\Model\StoreManagerInterface')
72+
$storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
7373
->disableOriginalConstructor()
7474
->getMock();
7575
$storeManager->expects($this->atLeastOnce())
@@ -85,9 +85,12 @@ public function testToHtml($requestParamMap)
8585
->disableOriginalConstructor()
8686
->getMock();
8787

88-
$context = $this->getMock('Magento\Backend\Block\Template\Context',
88+
$context = $this->getMock(
89+
\Magento\Backend\Block\Template\Context::class,
8990
['getRequest', 'getEventManager', 'getScopeConfig', 'getDesignPackage', 'getStoreManager', 'getAppState'],
90-
[], '', false
91+
[],
92+
'',
93+
false
9194
);
9295
$context->expects($this->any())->method('getRequest')->willReturn($request);
9396
$context->expects($this->any())->method('getEventManager')->willReturn($eventManage);
@@ -97,7 +100,7 @@ public function testToHtml($requestParamMap)
97100
$context->expects($this->once())->method('getAppState')->willReturn($appState);
98101

99102
$maliciousCode = $this->getMock(
100-
'Magento\Framework\Filter\Input\MaliciousCode',
103+
\Magento\Framework\Filter\Input\MaliciousCode::class,
101104
['filter'],
102105
[],
103106
'',
@@ -110,7 +113,7 @@ public function testToHtml($requestParamMap)
110113

111114
/** @var \Magento\Email\Block\Adminhtml\Template\Preview $preview */
112115
$preview = $this->objectManagerHelper->getObject(
113-
'Magento\Email\Block\Adminhtml\Template\Preview',
116+
\Magento\Email\Block\Adminhtml\Template\Preview::class,
114117
[
115118
'context' => $context,
116119
'maliciousCode' => $maliciousCode,
@@ -129,16 +132,6 @@ public function toHtmlDataProvider()
129132
{
130133
return [
131134
['data 1' => [
132-
['type', null, ''],
133-
['text', null, sprintf('<javascript>%s</javascript>', self::MALICIOUS_TEXT)],
134-
['styles', null, ''],
135-
]],
136-
['data 2' => [
137-
['type', null, ''],
138-
['text', null, sprintf('<iframe>%s</iframe>', self::MALICIOUS_TEXT)],
139-
['styles', null, ''],
140-
]],
141-
['data 3' => [
142135
['type', null, ''],
143136
['text', null, self::MALICIOUS_TEXT],
144137
['styles', null, ''],
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Email\Test\Unit\Controller\Adminhtml\Email\Template;
7+
8+
use Magento\Email\Controller\Adminhtml\Email\Template\Preview;
9+
use Magento\Framework\App\Action\Context;
10+
use Magento\Framework\App\RequestInterface;
11+
use Magento\Framework\App\View;
12+
use Magento\Framework\Registry;
13+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
14+
use Magento\Framework\View\Config;
15+
use Magento\Framework\View\Page\Title;
16+
use Magento\Framework\View\Result\Page;
17+
18+
/**
19+
* Preview Test.
20+
*/
21+
class PreviewTest extends \PHPUnit_Framework_TestCase
22+
{
23+
/**
24+
* @var Preview
25+
*/
26+
protected $object;
27+
28+
/**
29+
* @var Context
30+
*/
31+
protected $context;
32+
33+
/**
34+
* @var Registry|\PHPUnit_Framework_MockObject_MockObject
35+
*/
36+
protected $coreRegistryMock;
37+
38+
/**
39+
* @var View|\PHPUnit_Framework_MockObject_MockObject
40+
*/
41+
protected $viewMock;
42+
43+
/**
44+
* @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject
45+
*/
46+
protected $requestMock;
47+
48+
/**
49+
* @var Page|\PHPUnit_Framework_MockObject_MockObject
50+
*/
51+
protected $pageMock;
52+
53+
/**
54+
* @var Config|\PHPUnit_Framework_MockObject_MockObject
55+
*/
56+
protected $pageConfigMock;
57+
58+
/**
59+
* @var Title|\PHPUnit_Framework_MockObject_MockObject
60+
*/
61+
protected $pageTitleMock;
62+
63+
/**
64+
* @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
65+
*/
66+
protected $responseMock;
67+
68+
protected function setUp()
69+
{
70+
$objectManager = new ObjectManager($this);
71+
72+
$this->coreRegistryMock = $this->getMockBuilder(\Magento\Framework\Registry::class)
73+
->disableOriginalConstructor()
74+
->getMock();
75+
$this->viewMock = $this->getMockBuilder(\Magento\Framework\App\View::class)
76+
->disableOriginalConstructor()
77+
->getMock();
78+
$this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class)
79+
->getMock();
80+
$this->pageMock = $this->getMockBuilder(\Magento\Framework\View\Result\Page::class)
81+
->disableOriginalConstructor()
82+
->setMethods(['getConfig'])
83+
->getMock();
84+
$this->pageConfigMock = $this->getMockBuilder(\Magento\Framework\View\Page\Config::class)
85+
->setMethods(['getTitle'])
86+
->disableOriginalConstructor()
87+
->getMock();
88+
$this->pageTitleMock = $this->getMockBuilder(\Magento\Framework\View\Page\Title::class)
89+
->setMethods(['prepend'])
90+
->disableOriginalConstructor()
91+
->getMock();
92+
93+
$this->responseMock = $this->getMockBuilder(\Magento\Framework\App\ResponseInterface::class)
94+
->setMethods(['setHeader'])
95+
->getMockForAbstractClass();
96+
97+
$this->context = $objectManager->getObject(
98+
\Magento\Backend\App\Action\Context::class,
99+
[
100+
'request' => $this->requestMock,
101+
'view' => $this->viewMock,
102+
'response' => $this->responseMock
103+
]
104+
);
105+
$this->object = $objectManager->getObject(
106+
\Magento\Email\Controller\Adminhtml\Email\Template\Preview::class,
107+
[
108+
'context' => $this->context,
109+
'coreRegistry' => $this->coreRegistryMock,
110+
]
111+
);
112+
}
113+
114+
public function testExecute()
115+
{
116+
$this->viewMock->expects($this->once())
117+
->method('getPage')
118+
->willReturn($this->pageMock);
119+
$this->pageMock->expects($this->once())
120+
->method('getConfig')
121+
->willReturn($this->pageConfigMock);
122+
$this->pageConfigMock->expects($this->once())
123+
->method('getTitle')
124+
->willReturn($this->pageTitleMock);
125+
$this->pageTitleMock->expects($this->once())
126+
->method('prepend')
127+
->willReturnSelf();
128+
$this->responseMock->expects($this->once())
129+
->method('setHeader')
130+
->with('Content-Security-Policy', "script-src 'self'");
131+
132+
$this->assertNull($this->object->execute());
133+
}
134+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd">
9+
<container name="root">
10+
<block class="Magento\Framework\View\Element\Template" name="page.block" template="Magento_Email::template/preview.phtml">
11+
<block class="Magento\Email\Block\Adminhtml\Template\Preview" name="content" as="content"/>
12+
</block>
13+
</container>
14+
</layout>

app/code/Magento/Email/view/adminhtml/layout/adminhtml_email_template_preview.xml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
-->
88
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
99
<body>
10-
<referenceContainer name="page.content">
11-
<block name="preview.page.content" class="Magento\Framework\View\Element\Template" template="Magento_Email::template/preview.phtml">
12-
<block class="Magento\Email\Block\Adminhtml\Template\Preview" name="content" as="content"/>
13-
</block>
10+
<attribute name="id" value="html-body"/>
11+
<attribute name="class" value="preview-window"/>
12+
<referenceContainer name="backend.page" remove="true"/>
13+
<referenceContainer name="menu.wrapper" remove="true"/>
14+
<referenceContainer name="root">
15+
<block name="preview.page.content" class="Magento\Backend\Block\Page" template="Magento_Email::preview/iframeswitcher.phtml"/>
1416
</referenceContainer>
1517
</body>
1618
</page>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
/** @var \Magento\Backend\Block\Page $block */
8+
?>
9+
<div id="preview" class="cms-revision-preview">
10+
<iframe
11+
name="preview_iframe"
12+
id="preview_iframe"
13+
frameborder="0"
14+
title="<?php echo $block->escapeHtml(__('Preview')) ?>"
15+
width="100%"
16+
sandbox="allow-scripts allow-forms allow-pointer-lock"
17+
src="<?php echo $block->escapeUrl($block->getUrl('*/*/popup', ['_current' => true])) ?>"
18+
/>
19+
</div>

0 commit comments

Comments
 (0)