Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 64
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
tao_actions_form_CspHeader
0.00% covered (danger)
0.00%
0 / 64
0.00% covered (danger)
0.00%
0 / 8
132
0.00% covered (danger)
0.00%
0 / 1
 initForm
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
 initElements
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
2
 getSettings
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getSourceOptions
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 handleFormPost
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 groupElements
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 initializeFormData
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 setValidation
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2019 (original work) Open Assessment Technologies SA;
19 *
20 */
21
22use oat\oatbox\service\ServiceManagerAwareTrait;
23use oat\tao\helpers\form\validators\CspHeaderValidator;
24use oat\tao\model\security\Business\Domain\SettingsCollection;
25
26/**
27 * Handling of the CSP Header form
28 *
29 * @author Martijn Swinkels <m.swinkels@taotesting.com>
30 */
31class tao_actions_form_CspHeader extends tao_helpers_form_FormContainer
32{
33    use ServiceManagerAwareTrait;
34
35    public const SETTINGS_DATA = 'settings';
36
37    private const SOURCE_RADIO_NAME       = 'iframeSourceOption';
38    private const SOURCE_LIST_NAME        = 'iframeSourceDomains';
39    private const FORCED_TLS_NAME         = 'isTlsForced';
40    private const FORCED_TLS_ELEMENT_NAME = self::FORCED_TLS_NAME . '_0';
41
42    /** @var tao_helpers_form_elements_xhtml_Radiobox */
43    private $sourceElement;
44
45    /** @var tao_helpers_form_elements_xhtml_Textarea */
46    private $sourceDomainsElement;
47
48    /** @var tao_helpers_form_elements_xhtml_Checkbox */
49    private $forcedTlsElement;
50
51    /** @var SettingsCollection */
52    private $settings;
53
54    /**
55     * @inheritdoc
56     */
57    public function initForm()
58    {
59        $this->settings = $this->data[self::SETTINGS_DATA];
60        $this->form = new tao_helpers_form_xhtml_Form('cspHeader');
61
62        $this->form->setDecorators([
63            'element' => new tao_helpers_form_xhtml_TagWrapper(['tag' => 'div']),
64            'group' => new tao_helpers_form_xhtml_TagWrapper(['tag' => 'div', 'cssClass' => 'form-group']),
65            'error' => new tao_helpers_form_xhtml_TagWrapper([
66                'tag' => 'div',
67                'cssClass' => 'form-error ui-state-error ui-corner-all hidden'
68            ]),
69            'actions-bottom' => new tao_helpers_form_xhtml_TagWrapper(['tag' => 'div', 'cssClass' => 'form-toolbar'])
70        ]);
71    }
72
73    /**
74     * @inheritdoc
75     */
76    public function initElements()
77    {
78        $this->sourceElement = tao_helpers_form_FormFactory::getElement(self::SOURCE_RADIO_NAME, 'Radiobox');
79        $this->sourceDomainsElement = tao_helpers_form_FormFactory::getElement(self::SOURCE_LIST_NAME, 'Textarea');
80        $this->sourceDomainsElement->setAttribute('rows', 10);
81        $this->sourceDomainsElement->setHelp(
82            "<div class='help-text'>Each domain should be added on a new line. \n
83            Valid domain formats: www.example.com, *.example.com, http://www.example.com</div>"
84        );
85        $this->forcedTlsElement = tao_helpers_form_FormFactory::getElement(self::FORCED_TLS_NAME, 'Checkbox');
86
87        $this->setValidation();
88        $this->sourceElement->setOptions($this->getSourceOptions());
89        $this->forcedTlsElement->setOptions([1 => __('Force HTTPS on this platform')]);
90
91        $this->initializeFormData();
92
93        $this->form->addElement($this->sourceElement);
94        $this->form->addElement($this->sourceDomainsElement);
95        $this->form->addElement($this->forcedTlsElement);
96
97        $this->groupElements();
98
99        $this->form->setActions(tao_helpers_form_FormFactory::getCommonActions());
100    }
101
102    public function getSettings(): SettingsCollection
103    {
104        $this->handleFormPost();
105
106        return $this->settings;
107    }
108
109    /**
110     * @return array
111     */
112    private function getSourceOptions(): array
113    {
114        return [
115            'none' => __('Forbid for all domains'),
116            '*'  => __('Allow for all domains'),
117            'self'  => __('Only allow for my own domain (%s)', ROOT_URL),
118            'list' => __('Allow for the following domains'),
119        ];
120    }
121
122    /**
123     * Set the form data based on the available data
124     */
125    private function handleFormPost(): void
126    {
127        $postData = $this->getPostData();
128
129        if (
130            isset($postData[self::SOURCE_RADIO_NAME])
131            && array_key_exists($postData[self::SOURCE_RADIO_NAME], $this->getSourceOptions())
132        ) {
133            $this->settings->findContentSecurityPolicy()->setValue($postData[self::SOURCE_RADIO_NAME]);
134        }
135
136        if (isset($postData[self::SOURCE_LIST_NAME])) {
137            $this->settings->findContentSecurityPolicyWhitelist()->setValue($postData[self::SOURCE_LIST_NAME]);
138        }
139
140        $this->settings->findTransportSecurity()->setValue((string)!empty($postData[self::FORCED_TLS_ELEMENT_NAME]));
141    }
142
143    private function groupElements(): void
144    {
145        $this->form->createGroup(
146            'sources',
147            '<h3>' . __('Sources that can embed this platform in an iFrame') . '</h3>',
148            [self::SOURCE_RADIO_NAME, self::SOURCE_LIST_NAME]
149        );
150        $this->form->createGroup(
151            'tls',
152            sprintf('<h3>%s</h3>', __('Transport Layer Security')),
153            [self::FORCED_TLS_NAME]
154        );
155    }
156
157    private function initializeFormData(): void
158    {
159        $this->sourceElement->setValue(
160            $this->settings->findContentSecurityPolicy()->getValue()
161        );
162        $this->sourceDomainsElement->setValue(
163            $this->settings->findContentSecurityPolicyWhitelist()->getValue()
164        );
165        $this->forcedTlsElement->setValue(
166            $this->settings->findTransportSecurity()->getValue()
167        );
168    }
169
170    /**
171     * Set the validation needed for the form elements.
172     */
173    private function setValidation(): void
174    {
175        $this->sourceDomainsElement->addValidator(new CspHeaderValidator(['sourceElement' => $this->sourceElement]));
176        $this->sourceElement->addValidator(tao_helpers_form_FormFactory::getValidator('NotEmpty'));
177    }
178}