Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
PasswordRecoveryService
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 9
240
0.00% covered (danger)
0.00%
0 / 1
 sendMail
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
6
 getUser
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 getUserMail
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 setPassword
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 deleteToken
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getMessagingService
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getMailContent
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 getPasswordRecoveryLink
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 generateRecoveryToken
0.00% covered (danger)
0.00%
0 / 5
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) 2015 (original work) Open Assessment Technologies SA;
19 *
20 */
21
22namespace oat\tao\model\passwordRecovery;
23
24use oat\generis\model\GenerisRdf;
25use oat\tao\helpers\Template;
26use oat\tao\model\messaging\MessagingService;
27use oat\tao\model\messaging\Message;
28
29/**
30 * Password recovery service
31 *
32 * @access public
33 * @author Aleh Hutnikau <hutnikau@1pt.com>
34 * @package tao
35 */
36class PasswordRecoveryService extends \tao_models_classes_Service
37{
38    public const PROPERTY_PASSWORD_RECOVERY_TOKEN = 'http://www.tao.lu/Ontologies/generis.rdf#passwordRecoveryToken';
39
40    /**
41     * @var MessagingService
42     */
43    private $messagingSerivce;
44
45    /**
46     * Send email message with password recovery instructions.
47     *
48     * @author Aleh Hutnikau <hutnikau@1pt.com>
49     * @param core_kernel_classes_Resource $user The user has requested password recovery.
50     * @return boolean Whether message was sent.
51     */
52    public function sendMail(\core_kernel_classes_Resource $user)
53    {
54        $messagingService = $this->getMessagingService();
55        if (!$messagingService->isAvailable()) {
56            throw new PasswordRecoveryException('Messaging service is not available.');
57        }
58        $generisUser = new \core_kernel_users_GenerisUser($user);
59        $userNameProperty = new \core_kernel_classes_Property(GenerisRdf::PROPERTY_USER_FIRSTNAME);
60
61        $messageData = [
62            'user_name' => (string) $user->getOnePropertyValue($userNameProperty),
63            'link' => $this->getPasswordRecoveryLink($user)
64        ];
65
66        $message = new Message();
67        $message->setTo($generisUser);
68        $message->setBody($this->getMailContent($messageData));
69        $message->setTitle(__("Your TAO Password"));
70
71        $result = $messagingService->send($message);
72
73        return $result;
74    }
75
76    /**
77     * Get user by property value
78     * @param string $property uri
79     * @param type $value property value
80     * @return core_kernel_classes_Resource | null
81     */
82    public function getUser($property, $value)
83    {
84        $class = new \core_kernel_classes_Class(GenerisRdf::CLASS_GENERIS_USER);
85
86        $users = \tao_models_classes_UserService::singleton()->searchInstances(
87            [$property => $value],
88            $class,
89            ['like' => false, 'recursive' => true]
90        );
91        $user = empty($users) ? null : current($users);
92
93        return $user;
94    }
95
96    /**
97     * Get user mail value
98     * @param core_kernel_classes_Resource $user
99     * @return string | null
100     */
101    public function getUserMail(\core_kernel_classes_Resource $user)
102    {
103        $userMailProperty = new \core_kernel_classes_Property(GenerisRdf::PROPERTY_USER_MAIL);
104        $result = (string) $user->getOnePropertyValue($userMailProperty);
105        if (!$result || !filter_var($result, FILTER_VALIDATE_EMAIL)) {
106            $result = null;
107        }
108        return $result;
109    }
110
111    /**
112     * Change user pasword
113     * @param core_kernel_classes_Resource $user
114     * @param string $newPassword New password value
115     */
116    public function setPassword(\core_kernel_classes_Resource $user, $newPassword)
117    {
118        \tao_models_classes_UserService::singleton()->setPassword($user, $newPassword);
119        $this->deleteToken($user);
120    }
121
122    /**
123     * Delete password recovery token.
124     *
125     * @param \core_kernel_classes_Resource $user
126     * @return boolean
127     */
128    public function deleteToken(\core_kernel_classes_Resource $user)
129    {
130        $tokenProperty = new \core_kernel_classes_Property(self::PROPERTY_PASSWORD_RECOVERY_TOKEN);
131        return $user->removePropertyValues($tokenProperty);
132    }
133
134    /**
135     * Get messaging service
136     *
137     * @return MessagingService
138     */
139    public function getMessagingService()
140    {
141        if (is_null($this->messagingSerivce)) {
142            $this->messagingSerivce = MessagingService::singleton();
143        }
144        return $this->messagingSerivce;
145    }
146
147    /**
148     * Function generates password recovery email message content
149     * May be used in the following way:
150     * <pre>
151     * $this->getMailContent(array(
152     *     'user_name'=>'John Doe',
153     *     'link'=>$this->getPasswordRecoveryLink($user)
154     * ));
155     * </pre>
156     *
157     * @author Aleh Hutnikau <hutnikau@1pt.com>
158     * @param array $messageData
159     * @return string Message content
160     */
161    private function getMailContent($messageData)
162    {
163        $renderer = new \Renderer();
164        $renderer->setTemplate(Template::getTemplate('passwordRecovery/password-recovery-message.tpl', 'tao'));
165        foreach ($messageData as $key => $value) {
166            $renderer->setData($key, $value);
167        }
168        return $renderer->render();
169    }
170
171    /**
172     * Get password recovery link.
173     *
174     * @author Aleh Hutnikau <hutnikau@1pt.com>
175     * @param core_kernel_classes_Resource $user The user has requested password recovery.
176     * @return string Password recovery link.
177     */
178    private function getPasswordRecoveryLink(\core_kernel_classes_Resource $user)
179    {
180        $token = $this->generateRecoveryToken($user);
181        return _url('resetPassword', 'PasswordRecovery', 'tao', ['token' => $token]);
182    }
183
184    /**
185     * Generate password recovery token.
186     * If user already has passwordRecoveryToken property then it will be replaced.
187     *
188     * @author Aleh Hutnikau <hutnikau@1pt.com>
189     * @param core_kernel_classes_Resource $user The user has requested password recovery.
190     * @return string Password recovery token.
191     */
192    private function generateRecoveryToken(\core_kernel_classes_Resource $user)
193    {
194        $this->deleteToken($user);
195
196        $token = md5(uniqid(mt_rand(), true));
197        $tokenProperty = new \core_kernel_classes_Property(self::PROPERTY_PASSWORD_RECOVERY_TOKEN);
198        $user->setPropertyValue($tokenProperty, $token);
199
200        return $token;
201    }
202}