Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
20.51% |
8 / 39 |
|
16.67% |
2 / 12 |
CRAP | |
0.00% |
0 / 1 |
LtiUserService | |
20.51% |
8 / 39 |
|
16.67% |
2 / 12 |
162.14 | |
0.00% |
0 / 1 |
findOrSpawnUser | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
findUser | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
updateUser | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getUserIdentifier | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
spawnUser | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
getUserDataFromId | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getUserName | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
getLastName | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getFirstName | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
createLtiUser | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getLtiUserFactory | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
2.06 | |||
getEventManager | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
userUpdatedEvent | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
userCreatedEvent | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getLtiUserEventDispatcher | |
0.00% |
0 / 1 |
|
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-2020 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT); |
19 | */ |
20 | |
21 | declare(strict_types=1); |
22 | |
23 | namespace oat\taoLti\models\classes\user; |
24 | |
25 | use common_Exception; |
26 | use Exception; |
27 | use oat\generis\model\GenerisRdf; |
28 | use oat\oatbox\event\EventManager; |
29 | use oat\oatbox\service\ConfigurableService; |
30 | use oat\taoLti\models\classes\LtiLaunchData; |
31 | use oat\oatbox\mutex\LockTrait; |
32 | use oat\taoLti\models\classes\user\events\dispatcher\LtiUserEventDispatcher; |
33 | use oat\taoLti\models\classes\user\events\LtiUserCreatedEvent; |
34 | use oat\taoLti\models\classes\user\events\LtiUserUpdatedEvent; |
35 | |
36 | /** |
37 | * Lti user service, allow us to find or spawn a lti user based on launch data |
38 | * |
39 | * @access public |
40 | * @author Antoine Antoine, <joel@taotesting.com> |
41 | * @package taoLti |
42 | */ |
43 | abstract class LtiUserService extends ConfigurableService |
44 | { |
45 | use LockTrait; |
46 | |
47 | public const SERVICE_ID = 'taoLti/LtiUserService'; |
48 | |
49 | public const OPTION_FACTORY_LTI_USER = 'factoryLtiUser'; |
50 | |
51 | public const PROPERTY_USER_LTICONSUMER = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#UserConsumer'; |
52 | |
53 | public const PROPERTY_USER_LTIKEY = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#UserKey'; |
54 | |
55 | /** |
56 | * Returns the existing tao User that corresponds to |
57 | * the LTI request or spawns it |
58 | * |
59 | * @param LtiLaunchData $launchData |
60 | * @return LtiUser |
61 | * @throws common_Exception |
62 | * @throws \common_exception_Error |
63 | * @throws \core_kernel_users_CacheException |
64 | * @throws \core_kernel_users_Exception |
65 | * @throws \oat\taoLti\models\classes\LtiVariableMissingException |
66 | */ |
67 | public function findOrSpawnUser(LtiLaunchData $launchData) |
68 | { |
69 | $lock = $this->createLock(__METHOD__ . $launchData->getUserID() . $launchData->getLtiConsumer()->getUri(), 30); |
70 | $lock->acquire(true); |
71 | |
72 | try { |
73 | $taoUser = $this->findUser($launchData); |
74 | if ($taoUser === null) { |
75 | $taoUser = $this->spawnUser($launchData); |
76 | |
77 | $this->getLtiUserEventDispatcher()->dispatch($taoUser); |
78 | } |
79 | } finally { |
80 | $lock->release(); |
81 | } |
82 | |
83 | return $taoUser; |
84 | } |
85 | |
86 | /** |
87 | * Searches if this user was already created in TAO |
88 | * |
89 | * @param LtiLaunchData $ltiContext |
90 | * @return LtiUser |
91 | * @throws common_Exception |
92 | * @throws \common_exception_Error |
93 | * @throws \core_kernel_users_CacheException |
94 | * @throws \core_kernel_users_Exception |
95 | * @throws \oat\taoLti\models\classes\LtiVariableMissingException |
96 | * @throws Exception |
97 | */ |
98 | public function findUser(LtiLaunchData $ltiContext) |
99 | { |
100 | $ltiConsumer = $ltiContext->getLtiConsumer(); |
101 | $taoUserId = $this->getUserIdentifier($ltiContext->getUserID(), $ltiConsumer->getUri()); |
102 | if (is_null($taoUserId)) { |
103 | return null; |
104 | } |
105 | |
106 | $ltiUser = $this->createLtiUser($ltiContext, $taoUserId); |
107 | |
108 | \common_Logger::t("LTI User '" . $ltiUser->getIdentifier() . "' found."); |
109 | |
110 | $this->updateUser($ltiUser, $ltiContext); |
111 | |
112 | return $ltiUser; |
113 | } |
114 | |
115 | /** |
116 | * @param LtiUser $user |
117 | * @param LtiLaunchData $ltiContext |
118 | * @return mixed |
119 | */ |
120 | abstract protected function updateUser(LtiUserInterface $user, LtiLaunchData $ltiContext); |
121 | |
122 | /** |
123 | * Find the tao user identifier related to a lti user id and a consumer |
124 | * @param string $ltiUserId |
125 | * @param \core_kernel_classes_Resource $consumer |
126 | * @return mixed |
127 | */ |
128 | abstract public function getUserIdentifier($ltiUserId, $consumer); |
129 | |
130 | /** |
131 | * Creates a new LTI User with the absolute minimum of required informations |
132 | * |
133 | * @param LtiLaunchData $ltiContext |
134 | * @return LtiUserInterface |
135 | * @throws common_Exception |
136 | * @throws \common_exception_Error |
137 | * @throws \core_kernel_users_CacheException |
138 | * @throws \core_kernel_users_Exception |
139 | * @throws \oat\taoLti\models\classes\LtiVariableMissingException |
140 | * @throws Exception |
141 | */ |
142 | public function spawnUser(LtiLaunchData $ltiContext) |
143 | { |
144 | //@TODO create LtiUser after create and save in db. |
145 | $userId = $ltiContext->getUserID(); |
146 | |
147 | $ltiUser = $this->createLtiUser($ltiContext, $userId); |
148 | |
149 | $this->updateUser($ltiUser, $ltiContext); |
150 | |
151 | return $ltiUser; |
152 | } |
153 | |
154 | /** |
155 | * Get the user information from the tao user identifier |
156 | * @param string $taoUserId |
157 | * @return array structure that represent the user |
158 | * [ |
159 | * 'http://www.tao.lu/Ontologies/generis.rdf#userRoles' => ['firstRole', 'secondRole'], |
160 | * 'http://www.tao.lu/Ontologies/generis.rdf#userUILg' => 'en-US', |
161 | * 'http://www.tao.lu/Ontologies/generis.rdf#userFirstName' => 'firstname, |
162 | * 'http://www.tao.lu/Ontologies/generis.rdf#userLastName' => 'lastname', |
163 | * 'http://www.tao.lu/Ontologies/generis.rdf#userMail' => 'test@test.com', |
164 | * 'http://www.w3.org/2000/01/rdf-schema#label' => 'label' |
165 | * ] |
166 | */ |
167 | abstract public function getUserDataFromId($taoUserId); |
168 | |
169 | /** |
170 | * @param array $userData |
171 | * @return string |
172 | */ |
173 | public function getUserName(array $userData) |
174 | { |
175 | $firstName = $this->getFirstName($userData); |
176 | $lastName = $this->getLastName($userData); |
177 | |
178 | $userName = trim($firstName . ' ' . $lastName); |
179 | |
180 | return $userName; |
181 | } |
182 | |
183 | /** |
184 | * @param array $userData |
185 | * @return mixed|string |
186 | */ |
187 | public function getLastName(array $userData) |
188 | { |
189 | return isset($userData[GenerisRdf::PROPERTY_USER_LASTNAME]) |
190 | ? $userData[GenerisRdf::PROPERTY_USER_LASTNAME] |
191 | : ''; |
192 | } |
193 | |
194 | /** |
195 | * @param array $userData |
196 | * @return string |
197 | */ |
198 | public function getFirstName(array $userData) |
199 | { |
200 | return isset($userData[GenerisRdf::PROPERTY_USER_FIRSTNAME]) |
201 | ? $userData[GenerisRdf::PROPERTY_USER_FIRSTNAME] |
202 | : ''; |
203 | } |
204 | |
205 | /** |
206 | * @param LtiLaunchData $ltiContext |
207 | * @param string $userId |
208 | * @return LtiUserInterface |
209 | * @throws common_Exception |
210 | */ |
211 | protected function createLtiUser(LtiLaunchData $ltiContext, $userId) |
212 | { |
213 | return $this->getLtiUserFactory()->create($ltiContext, $userId); |
214 | } |
215 | |
216 | /** |
217 | * @return LtiUserFactoryInterface |
218 | * @throws common_Exception |
219 | */ |
220 | protected function getLtiUserFactory() |
221 | { |
222 | $ltiUserFactory = $this->getServiceLocator()->get($this->getOption(static::OPTION_FACTORY_LTI_USER)); |
223 | if (!$ltiUserFactory instanceof LtiUserFactoryInterface) { |
224 | throw new common_Exception('Lti Factory it is not a LtiUserFactoryInterface'); |
225 | } |
226 | |
227 | return $ltiUserFactory; |
228 | } |
229 | |
230 | /** |
231 | * @return EventManager |
232 | */ |
233 | protected function getEventManager() |
234 | { |
235 | return $this->getServiceLocator()->get(EventManager::SERVICE_ID); |
236 | } |
237 | |
238 | protected function userUpdatedEvent($userId) |
239 | { |
240 | $this->getEventManager()->trigger(new LtiUserUpdatedEvent($userId)); |
241 | } |
242 | |
243 | protected function userCreatedEvent($userId) |
244 | { |
245 | $this->getEventManager()->trigger(new LtiUserCreatedEvent($userId)); |
246 | } |
247 | |
248 | private function getLtiUserEventDispatcher(): LtiUserEventDispatcher |
249 | { |
250 | return $this->getServiceLocator()->get(LtiUserEventDispatcher::class); |
251 | } |
252 | } |