Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 74
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
tao_actions_form_RestUserForm
0.00% covered (danger)
0.00%
0 / 74
0.00% covered (danger)
0.00%
0 / 8
1406
0.00% covered (danger)
0.00%
0 / 1
 getData
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
72
 validate
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
210
 getPropertyValidators
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 validatePassword
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 prepareValuesToSave
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
30
 isLoginAvailable
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTopClass
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getUserClass
0.00% covered (danger)
0.00%
0 / 1
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) 2017 (original work) Open Assessment Technologies SA;
19 *
20 */
21
22use oat\generis\model\GenerisRdf;
23use oat\generis\model\OntologyRdfs;
24use oat\generis\model\user\PasswordConstraintsService;
25use oat\oatbox\validator\ValidatorInterface;
26use tao_models_classes_UserService as UserService;
27use Zend\ServiceManager\ServiceLocatorAwareTrait;
28use Zend\ServiceManager\ServiceLocatorAwareInterface;
29
30/**
31 * Class tao_actions_form_RestUserForm
32 *
33 * Implementation of tao_actions_form_RestForm to manage generis user forms for edit and create
34 */
35class tao_actions_form_RestUserForm extends tao_actions_form_RestForm implements ServiceLocatorAwareInterface
36{
37    use ServiceLocatorAwareTrait;
38
39    /** @var bool If password is change, set it to true to save new one */
40    protected $changePassword = false;
41
42    /**
43     * Get the form data.
44     * Set readOnly to login in case of edition.
45     * Add password and password confirmation with different label depending creation or edition
46     *
47     * @return array
48     */
49    public function getData()
50    {
51        $properties = $this->formProperties;
52
53        foreach ($properties as $index => $property) {
54            if ($property['uri'] === GenerisRdf::PROPERTY_USER_LOGIN && $this->doesExist()) {
55                $properties[$index]['widget'] = tao_helpers_form_elements_Readonly::WIDGET_ID;
56                break;
57            }
58        }
59
60        if ($this->doesExist()) {
61            foreach ($properties as $key => $property) {
62                if ($property['uri'] === GenerisRdf::PROPERTY_USER_PASSWORD && isset($property['value'])) {
63                    $properties[$key]['value'] = '';
64                    break;
65                }
66            }
67        }
68
69        return [
70            self::PROPERTIES => $properties,
71            self::RANGES => $this->ranges,
72        ];
73    }
74
75    /**
76     * Validate the form against the property validators.
77     * In case of range, check if value belong to associated ranges list
78     *
79     * @return common_report_Report
80     */
81    public function validate()
82    {
83        $report = parent::validate();
84
85        $password = null;
86        foreach ($this->formProperties as $key => $property) {
87            if (
88                $property['uri'] == GenerisRdf::PROPERTY_USER_PASSWORD
89                && !empty($this->formProperties[$key]['formValue'])
90            ) {
91                $password = $this->formProperties[$key]['formValue'];
92                break;
93            }
94        }
95
96        if ($this->isNew() || ($this->doesExist() && !is_null($password))) {
97            try {
98                $this->validatePassword($password);
99                $this->changePassword = true;
100            } catch (common_exception_ValidationFailed $e) {
101                $subReport = common_report_Report::createFailure($e->getMessage());
102                $subReport->setData(GenerisRdf::PROPERTY_USER_PASSWORD);
103                $report->add($subReport);
104            }
105        }
106
107        // Validate new login availability
108        if ($this->isNew()) {
109            foreach ($this->formProperties as $property) {
110                if ($property['uri'] === GenerisRdf::PROPERTY_USER_LOGIN) {
111                    if (empty($property['formValue'])) {
112                        $subReport = common_report_Report::createFailure(__('Login is empty.'));
113                    } elseif (! $this->isLoginAvailable($property['formValue'])) {
114                        $subReport = common_report_Report::createFailure(__('Login is already in use.'));
115                    }
116
117                    if (isset($subReport)) {
118                        $subReport->setData($property['uri']);
119                        $report->add($subReport);
120                    }
121                }
122            }
123        }
124
125        return $report;
126    }
127
128    /**
129     * Get validators of a property.
130     * Add not empty validator to user to languages and roles properties
131     *
132     * @param core_kernel_classes_Property $property
133     * @return array
134     */
135    protected function getPropertyValidators(core_kernel_classes_Property $property)
136    {
137        $validators = parent::getPropertyValidators($property);
138
139        $notEmptyProperties = [
140            GenerisRdf::PROPERTY_USER_UILG,
141            GenerisRdf::PROPERTY_USER_ROLES,
142            OntologyRdfs::RDFS_LABEL,
143        ];
144
145        if ($this->isNew()) {
146            $notEmptyProperties[] = GenerisRdf::PROPERTY_USER_PASSWORD;
147            $notEmptyProperties[] = 'http://www.tao.lu/Ontologies/generis.rdf#login';
148        }
149
150        if (in_array($property->getUri(), $notEmptyProperties)) {
151            $validators[] = 'notEmpty';
152        }
153
154        return $validators;
155    }
156
157    /**
158     * Validate password by evaluate it against PasswordConstraintService and NotEmpty validators
159     *
160     * @param $password
161     * @throws common_exception_ValidationFailed If invalid
162     */
163    protected function validatePassword($password)
164    {
165        if (!(new tao_helpers_form_validators_NotEmpty())->evaluate($password)) {
166            throw new common_exception_ValidationFailed(GenerisRdf::PROPERTY_USER_PASSWORD, __('Password is empty.'));
167        }
168
169        /** @var ValidatorInterface $validator */
170        foreach (PasswordConstraintsService::singleton()->getValidators() as $validator) {
171            if (!$validator->evaluate($password)) {
172                throw new common_exception_ValidationFailed(
173                    GenerisRdf::PROPERTY_USER_PASSWORD,
174                    $validator->getMessage()
175                );
176            }
177        }
178    }
179
180    /**
181     * Prepare form properties values to be saved.
182     * Remove form fields for password and create a new one with encrypted value.
183     *
184     * @return array
185     */
186    protected function prepareValuesToSave()
187    {
188        $values = parent::prepareValuesToSave();
189        if ($this->changePassword) {
190            $password = null;
191            foreach ($this->formProperties as $key => $property) {
192                if (
193                    $property['uri'] == GenerisRdf::PROPERTY_USER_PASSWORD
194                    && isset($this->formProperties[$key]['formValue'])
195                ) {
196                    $password = $this->formProperties[$key]['formValue'];
197                    break;
198                }
199            }
200
201            $values[GenerisRdf::PROPERTY_USER_PASSWORD] = core_kernel_users_Service::getPasswordHash()->encrypt(
202                $password
203            );
204        }
205
206        return $values;
207    }
208
209    /**
210     * Check if login is already used. Return false if not, yes if a User resource has he same login
211     *
212     * @param $login
213     * @return bool
214     */
215    protected function isLoginAvailable($login)
216    {
217        return UserService::singleton()->loginAvailable($login);
218    }
219
220    /**
221     * Get the class associated to current form
222     *
223     * @return core_kernel_classes_Class
224     */
225    protected function getTopClass()
226    {
227        return $this->getUserClass();
228    }
229
230    /**
231     * Get the generis user class
232     *
233     * @return core_kernel_classes_Class
234     */
235    protected function getUserClass()
236    {
237        return $this->getClass(GenerisRdf::CLASS_GENERIS_USER);
238    }
239}