From 64cdd496d7aa9ae9976ff1b05fd8d68d8e62fd98 Mon Sep 17 00:00:00 2001 From: antoinerobin Date: Mon, 21 Aug 2017 10:05:28 +0200 Subject: [PATCH 01/12] send service locator to session (cherry picked from commit ac85863fdecc6067c1d514651fdd862f5ec18cba) --- models/classes/class.LtiService.php | 1 + 1 file changed, 1 insertion(+) diff --git a/models/classes/class.LtiService.php b/models/classes/class.LtiService.php index 676d79ee..6ae7f1f4 100755 --- a/models/classes/class.LtiService.php +++ b/models/classes/class.LtiService.php @@ -45,6 +45,7 @@ public function startLtiSession(common_http_Request $request) { $adapter = new taoLti_models_classes_LtiAuthAdapter($request); $user = $adapter->authenticate(); $session = new taoLti_models_classes_TaoLtiSession($user); + $this->getServiceLocator()->propagate($session); common_session_SessionManager::startSession($session); } From d6be3dd4d27efed28416836a49a736a2ffad26b3 Mon Sep 17 00:00:00 2001 From: antoinerobin Date: Wed, 23 Aug 2017 10:40:17 +0200 Subject: [PATCH 02/12] create lti user object --- models/classes/user/LtiUser.php | 167 ++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100755 models/classes/user/LtiUser.php diff --git a/models/classes/user/LtiUser.php b/models/classes/user/LtiUser.php new file mode 100755 index 00000000..02e5d6b3 --- /dev/null +++ b/models/classes/user/LtiUser.php @@ -0,0 +1,167 @@ + + * @package taoLti + + */ +class LtiUser extends \common_user_User implements ServiceLocatorAwareInterface +{ + use ServiceLocatorAwareTrait; + + /** + * Data with which this session was launched + * @var \taoLti_models_classes_LtiLaunchData + */ + private $ltiLaunchData; + + /** + * Local represenation of user + * @var \core_kernel_classes_Resource + */ + private $userUri; + + /** + * Cache of the current user's lti roles + * @var array + */ + protected $roles; + + private $language; + + private $firstname; + + private $lastname; + + private $email; + + private $label; + + /** + * Currently used UI languages. + * + * @var array + */ + protected $uiLanguage; + + public function __construct($launchData, $userUri, $roles, $language = DEFAULT_LANG, $firstname = '', $lastname = '', $email = '', $label = '') { + $this->ltiLaunchData = $launchData; + $this->userUri = $userUri; + $this->roles = $roles; + $this->language = $language; + $this->firstname = $firstname; + $this->lastname = $lastname; + $this->email = $email; + } + + /** + * (non-PHPdoc) + * @see common_user_User::getIdentifier() + */ + public function getIdentifier() { + return $this->userUri; + } + + + public function getLaunchData() + { + return $this->ltiLaunchData; + } + + /** + * (non-PHPdoc) + * @see common_user_User::getPropertyValues() + */ + public function getPropertyValues($property) { + $returnValue = null; + switch ($property) { + case PROPERTY_USER_DEFLG : + $returnValue = array(DEFAULT_LANG); + break; + case PROPERTY_USER_UILG : + $returnValue = array($this->language); + break; + case PROPERTY_USER_ROLES : + $returnValue = $this->roles; + break; + case PROPERTY_USER_FIRSTNAME : + $returnValue = [$this->firstname]; + break; + case PROPERTY_USER_LASTNAME : + $returnValue = [$this->lastname]; + break; + default: + \common_Logger::d('Unkown property '.$property.' requested from '.__CLASS__); + $returnValue = array(); + } + return $returnValue; + } + + + /** + * (non-PHPdoc) + * @see common_user_User::refresh() + */ + public function refresh() { + // nothing to do + } + + /** + * @param $data string json representing a lti user + * @throws \taoLti_models_classes_LtiException + * @return LtiUser + */ + public static function unserialize($data) + { + $user = $data !== false ? json_decode($data,true) : array(); + + if(isset($user['launchData']) && isset($user['userUri']) && isset($user['roles']) && isset($user['language']) && isset($user['firstname']) && isset($user['lastname']) && isset($user['email']) && isset($user['label'])){ + return new self($user['launchData'], $user['userUri'], $user['roles'], $user['language'], $user['firstname'], $user['lastname'], $user['email'], $user['label']); + } + + return null; + } + + + public function jsonSerialize() + { + return [ + 'launchData' => $this->ltiLaunchData, + 'userUri' => $this->userUri, + 'roles' => $this->roles, + 'language' => $this->language, + 'firstname' => $this->firstname, + 'lastname' => $this->lastname, + 'email' => $this->email, + 'label' => $this->label, + ]; + } + +} From 0edc4f6bc70472f9702ac673531d1bb2fc479edb Mon Sep 17 00:00:00 2001 From: antoinerobin Date: Wed, 23 Aug 2017 10:40:44 +0200 Subject: [PATCH 03/12] use lti user service to get lti user --- models/classes/LtiRestApiService.php | 23 ++---- models/classes/class.LtiAuthAdapter.php | 10 ++- models/classes/class.LtiService.php | 2 +- models/classes/user/LtiUserService.php | 102 ++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 19 deletions(-) create mode 100755 models/classes/user/LtiUserService.php diff --git a/models/classes/LtiRestApiService.php b/models/classes/LtiRestApiService.php index ffd4c354..c1d39e15 100644 --- a/models/classes/LtiRestApiService.php +++ b/models/classes/LtiRestApiService.php @@ -20,6 +20,8 @@ namespace oat\taoLti\models\classes; +use oat\taoLti\models\classes\user\LtiUserService; + class LtiRestApiService extends \tao_models_classes_Service { protected function getRootClass() @@ -43,8 +45,6 @@ protected function getClassService() */ public function getUserId($id, $key) { - $class = new \core_kernel_classes_Class(CLASS_LTI_USER); - $dataStore = new \tao_models_classes_oauth_DataStore(); try { /** @var \core_kernel_classes_Resource $consumerResource */ @@ -53,25 +53,16 @@ public function getUserId($id, $key) throw new \common_exception_NotFound($e->getMessage()); } - $instances = $class->searchInstances(array( - PROPERTY_USER_LTIKEY => $id, - PROPERTY_USER_LTICONSUMER => $consumerResource - ), array( - 'like' => false - )); - - if (count($instances) > 1) { - throw new \common_Exception('Multiple user accounts found for user key: ' . $id); - } + /** @var LtiUserService $service */ + $service = $this->getServiceLocator()->get(LtiUserService::SERVICE_ID); + $ltiUser = $service->findUser($id, $consumerResource); - /** @var \core_kernel_classes_Resource $ltiUser */ - $ltiUser = count($instances) == 1 ? current($instances) : null; - if (!$ltiUser) { + if (is_null($ltiUser)) { return null; } return array ( - 'id' => $ltiUser->getUri() + 'id' => $ltiUser->getIdentifier() ); } } \ No newline at end of file diff --git a/models/classes/class.LtiAuthAdapter.php b/models/classes/class.LtiAuthAdapter.php index 8337ab17..5c26e328 100755 --- a/models/classes/class.LtiAuthAdapter.php +++ b/models/classes/class.LtiAuthAdapter.php @@ -20,6 +20,7 @@ */ use oat\taoLti\models\classes\LtiMessages\LtiErrorMessage; +use oat\taoLti\models\classes\user\LtiUserService; /** * Authentication adapter interface to be implemented by authentication methods @@ -29,8 +30,11 @@ * @package taoLti */ class taoLti_models_classes_LtiAuthAdapter - implements common_user_auth_Adapter + implements common_user_auth_Adapter, \Zend\ServiceManager\ServiceLocatorAwareInterface { + + use \Zend\ServiceManager\ServiceLocatorAwareTrait; + /** * * @var common_http_Request @@ -56,7 +60,9 @@ public function authenticate() { try { $service->validate($this->request); $ltiLaunchData = taoLti_models_classes_LtiLaunchData::fromRequest($this->request); - return new taoLti_models_classes_LtiUser($ltiLaunchData); + /** @var LtiUserService $userService */ + $userService = $this->getServiceLocator()->get(LtiUserService::SERVICE_ID); + return $userService->findOrSpawnUser($ltiLaunchData); } catch (common_http_InvalidSignatureException $e) { throw new taoLti_models_classes_LtiException('Invalid LTI signature', LtiErrorMessage::ERROR_UNAUTHORIZED); } diff --git a/models/classes/class.LtiService.php b/models/classes/class.LtiService.php index 6ae7f1f4..1423ba4d 100755 --- a/models/classes/class.LtiService.php +++ b/models/classes/class.LtiService.php @@ -43,9 +43,9 @@ protected function __construct() { */ public function startLtiSession(common_http_Request $request) { $adapter = new taoLti_models_classes_LtiAuthAdapter($request); + $this->getServiceLocator()->propagate($adapter); $user = $adapter->authenticate(); $session = new taoLti_models_classes_TaoLtiSession($user); - $this->getServiceLocator()->propagate($session); common_session_SessionManager::startSession($session); } diff --git a/models/classes/user/LtiUserService.php b/models/classes/user/LtiUserService.php new file mode 100755 index 00000000..88f2af0f --- /dev/null +++ b/models/classes/user/LtiUserService.php @@ -0,0 +1,102 @@ + + * @package taoLti + + */ +abstract class LtiUserService extends ConfigurableService +{ + const SERVICE_ID = 'taoLti/LtiUserService'; + + /** + * Returns the existing tao User that corresponds to + * the LTI request or spawns it + * + * @param \taoLti_models_classes_LtiLaunchData $launchData + * @throws \taoLti_models_classes_LtiException + * @return LtiUser + */ + public function findOrSpawnUser(\taoLti_models_classes_LtiLaunchData $launchData) { + $taoUser = $this->findUser($launchData->getUserID(), \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($launchData), $launchData); + if (is_null($taoUser)) { + $taoUser = $this->spawnUser($launchData); + } + return $taoUser; + } + + /** + * Searches if this user was already created in TAO + * + * @param string $userId + * @param \core_kernel_classes_Resource $ltiConsumer + * @throws \taoLti_models_classes_LtiException + * @return LtiUser + */ + abstract public function findUser($userId, $ltiConsumer); + + /** + * Creates a new LTI User with the absolute minimum of required informations + * + * @param \taoLti_models_classes_LtiLaunchData $ltiContext + * @return LtiUser + */ + abstract public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext); + + + protected function determineTaoRoles(\taoLti_models_classes_LtiLaunchData $ltiLaunchData) { + $roles = array(); + if ($ltiLaunchData->hasVariable(\taoLti_models_classes_LtiLaunchData::ROLES)) { + foreach ($ltiLaunchData->getUserRoles() as $role) { + $taoRole = \taoLti_models_classes_LtiUtils::mapLTIRole2TaoRole($role); + if (!is_null($taoRole)) { + $roles[] = $taoRole; + foreach (\core_kernel_users_Service::singleton()->getIncludedRoles(new \core_kernel_classes_Resource($taoRole)) as $includedRole) { + $roles[] = $includedRole->getUri(); + } + } + } + $roles = array_unique($roles); + } else { + return array(INSTANCE_ROLE_LTI_BASE); + } + return $roles; + } + + + protected function getRoles($taoRoles) { + $roles = array(); + foreach ($taoRoles as $role){ + $roles[] = $role->getUri(); + + } + return $roles; + } +} From 8f930ea8c4afe194e58073224df6a8d1c624ce79 Mon Sep 17 00:00:00 2001 From: antoinerobin Date: Wed, 23 Aug 2017 10:41:48 +0200 Subject: [PATCH 04/12] use lti user in session --- models/classes/class.TaoLtiSession.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/models/classes/class.TaoLtiSession.php b/models/classes/class.TaoLtiSession.php index ecd9ef7b..820e25b6 100755 --- a/models/classes/class.TaoLtiSession.php +++ b/models/classes/class.TaoLtiSession.php @@ -20,6 +20,8 @@ * */ +use oat\taoLti\models\classes\user\LtiUser; + /** * The TAO layer ontop of the LtiSession * @@ -36,7 +38,7 @@ class taoLti_models_classes_TaoLtiSession extends common_session_DefaultSession */ private $ltiLink = null; - public function __construct(taoLti_models_classes_LtiUser $user) + public function __construct(LtiUser $user) { parent::__construct($user); } From e9343c21e1eff7446632d5eb1e4b68e90303763c Mon Sep 17 00:00:00 2001 From: antoinerobin Date: Wed, 23 Aug 2017 10:42:08 +0200 Subject: [PATCH 05/12] ontology and kv implemtation of lti user service --- models/classes/user/KvLtiUserService.php | 121 ++++++++++++++ .../classes/user/OntologyLtiUserService.php | 151 ++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100755 models/classes/user/KvLtiUserService.php create mode 100755 models/classes/user/OntologyLtiUserService.php diff --git a/models/classes/user/KvLtiUserService.php b/models/classes/user/KvLtiUserService.php new file mode 100755 index 00000000..657ad853 --- /dev/null +++ b/models/classes/user/KvLtiUserService.php @@ -0,0 +1,121 @@ + + * @package taoLti + + */ +class KvLtiUserService extends LtiUserService +{ + + const OPTION_PERSISTENCE = 'persistence'; + + const LTI_USER = 'lti_ku_'; + + /** + * @var \common_persistence_KeyValuePersistence + */ + private $persistence; + + /** + * @return \common_persistence_KeyValuePersistence|\common_persistence_Persistence + */ + protected function getPersistence() + { + if (is_null($this->persistence)) { + $persistenceOption = $this->getOption(self::OPTION_PERSISTENCE); + $this->persistence = (is_object($persistenceOption)) + ? $persistenceOption + : \common_persistence_KeyValuePersistence::getPersistence($persistenceOption); + } + return $this->persistence; + } + + + /** + * @inheritdoc + */ + public function findUser($userId, $ltiConsumer) { + $data = $this->getPersistence()->get(self::LTI_USER . $userId . $ltiConsumer->getUri()); + if($data === false){ + return null; + } + + $ltiUser = LtiUser::unSerialize($data); + + return $ltiUser; + } + + /** + * Creates a new LTI User with the absolute minimum of required informations + * + * @param \taoLti_models_classes_LtiLaunchData $ltiContext + * @return LtiUser + */ + public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext) { + + $firstname = ''; + $lastname = ''; + $email = ''; + $label = ''; + + if ($ltiContext->hasLaunchLanguage()) { + $launchLanguage = $ltiContext->getLaunchLanguage(); + $uiLanguage = \taoLti_models_classes_LtiUtils::mapCode2InterfaceLanguage($launchLanguage); + } else { + $uiLanguage = DEFAULT_LANG; + } + + + if ($ltiContext->hasVariable(\taoLti_models_classes_LtiLaunchData::LIS_PERSON_NAME_FULL)) { + $label = $ltiContext->getUserFullName(); + } + + if ($ltiContext->hasVariable(\taoLti_models_classes_LtiLaunchData::LIS_PERSON_NAME_GIVEN)) { + $firstname = $ltiContext->getUserGivenName(); + } + if ($ltiContext->hasVariable(\taoLti_models_classes_LtiLaunchData::LIS_PERSON_NAME_FAMILY)) { + $lastname = $ltiContext->getUserFamilyName(); + } + if ($ltiContext->hasVariable(\taoLti_models_classes_LtiLaunchData::LIS_PERSON_CONTACT_EMAIL_PRIMARY)) { + $email = $ltiContext->getUserEmail();; + } + + $roles = $this->determineTaoRoles($ltiContext); + + $userId = $ltiContext->getUserID(); + + $ltiUser = new LtiUser($ltiContext, $userId, $roles, $uiLanguage, $firstname, $lastname, $email, $label); + $ltiConsumer = \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($ltiContext); + $this->getPersistence()->set(self::LTI_USER . $userId . $ltiConsumer->getUri(), json_encode($ltiUser)); + + return $ltiUser; + } +} diff --git a/models/classes/user/OntologyLtiUserService.php b/models/classes/user/OntologyLtiUserService.php new file mode 100755 index 00000000..96868d95 --- /dev/null +++ b/models/classes/user/OntologyLtiUserService.php @@ -0,0 +1,151 @@ + + * @package taoLti + + */ +class OntologyLtiUserService extends LtiUserService +{ + + const PROPERTY_USER_LTICONSUMER = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#UserConsumer'; + + const PROPERTY_USER_LTIKEY = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#UserKey'; + + const CLASS_LTI_USER = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#LTIConsumer'; + + /** + * Searches if this user was already created in TAO + * + * @param \taoLti_models_classes_LtiLaunchData $ltiContext + * @throws \taoLti_models_classes_LtiException + * @return LtiUser + */ + public function findUser($userId, $ltiConsumer, $launchdata = null) { + $class = new \core_kernel_classes_Class(self::CLASS_LTI_USER); + $instances = $class->searchInstances(array( + self::PROPERTY_USER_LTIKEY => $userId, + self::PROPERTY_USER_LTICONSUMER => $ltiConsumer + ), array( + 'like' => false + )); + if (count($instances) > 1) { + throw new \taoLti_models_classes_LtiException( + 'Multiple user accounts found for user key \''.$userId.'\'', + LtiErrorMessage::ERROR_SYSTEM_ERROR + ); + } + /** @var \core_kernel_classes_Resource $instance */ + if(count($instances) == 1){ + $instance = current($instances); + $properties = $instance->getPropertiesValues( + [ + PROPERTY_USER_UILG, + PROPERTY_USER_FIRSTNAME, + PROPERTY_USER_LASTNAME, + PROPERTY_USER_MAIL, + PROPERTY_USER_ROLES + ] + ); + + + $roles = $this->getRoles($properties[PROPERTY_USER_ROLES]); + return new LtiUser($launchdata, $instance->getUri(), $roles, (string)$properties[PROPERTY_USER_UILG][0], (string)$properties[PROPERTY_USER_FIRSTNAME][0], (string)$properties[PROPERTY_USER_LASTNAME][0], (string)$properties[PROPERTY_USER_MAIL][0]); + + } else { + return null; + } + + } + + /** + * Creates a new LTI User with the absolute minimum of required informations + * + * @param \taoLti_models_classes_LtiLaunchData $ltiContext + * @return LtiUser + */ + public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext) { + $class = new \core_kernel_classes_Class(self::CLASS_LTI_USER); + //$lang = tao_models_classes_LanguageService::singleton()->getLanguageByCode(DEFAULT_LANG); + + $props = array( + self::PROPERTY_USER_LTIKEY => $ltiContext->getUserID(), + self::PROPERTY_USER_LTICONSUMER => \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($ltiContext), + /* + PROPERTY_USER_UILG => $lang, + PROPERTY_USER_DEFLG => $lang, + */ + + ); + + $firstname = ''; + $lastname = ''; + $email = ''; + $label = ''; + if ($ltiContext->hasLaunchLanguage()) { + $launchLanguage = $ltiContext->getLaunchLanguage(); + $uiLanguage = \taoLti_models_classes_LtiUtils::mapCode2InterfaceLanguage($launchLanguage); + } else { + $uiLanguage = DEFAULT_LANG; + } + + $props[PROPERTY_USER_UILG] = $uiLanguage; + + if ($ltiContext->hasVariable(\taoLti_models_classes_LtiLaunchData::LIS_PERSON_NAME_FULL)) { + $label = $ltiContext->getUserFullName(); + $props[RDFS_LABEL] = $label; + } + + if ($ltiContext->hasVariable(\taoLti_models_classes_LtiLaunchData::LIS_PERSON_NAME_GIVEN)) { + $firstname = $ltiContext->getUserGivenName(); + $props[PROPERTY_USER_FIRSTNAME] = $firstname; + } + if ($ltiContext->hasVariable(\taoLti_models_classes_LtiLaunchData::LIS_PERSON_NAME_FAMILY)) { + $lastname = $ltiContext->getUserFamilyName(); + $props[PROPERTY_USER_LASTNAME] = $lastname; + } + if ($ltiContext->hasVariable(\taoLti_models_classes_LtiLaunchData::LIS_PERSON_CONTACT_EMAIL_PRIMARY)) { + $email = $ltiContext->getUserEmail();; + $props[PROPERTY_USER_MAIL] = $email; + } + + $roles = $this->determineTaoRoles($ltiContext); + $props[PROPERTY_USER_ROLES] = $roles; + + $user = $class->createInstanceWithProperties($props); + \common_Logger::i('added User '.$user->getLabel()); + + + $ltiUser = new LtiUser($ltiContext, $user->getUri(), $roles, $uiLanguage, $firstname, $lastname, $email, $label) ; + + return $ltiUser; + } + +} From 332262396f5fb2dcc919fd1a1baab1e60aec3874 Mon Sep 17 00:00:00 2001 From: antoinerobin Date: Wed, 23 Aug 2017 10:42:25 +0200 Subject: [PATCH 06/12] default config --- config/default/LtiUserService.conf.php | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 config/default/LtiUserService.conf.php diff --git a/config/default/LtiUserService.conf.php b/config/default/LtiUserService.conf.php new file mode 100644 index 00000000..92462ef6 --- /dev/null +++ b/config/default/LtiUserService.conf.php @@ -0,0 +1,4 @@ + Date: Wed, 23 Aug 2017 10:45:23 +0200 Subject: [PATCH 07/12] update version number and set new service --- manifest.php | 2 +- scripts/update/class.Updater.php | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/manifest.php b/manifest.php index dd70f221..a298ab56 100755 --- a/manifest.php +++ b/manifest.php @@ -35,7 +35,7 @@ 'label' => 'LTI library', 'description' => 'TAO LTI library and helpers', 'license' => 'GPL-2.0', - 'version' => '3.2.4', + 'version' => '3.3.0', 'author' => 'Open Assessment Technologies SA', 'requires' => array( 'tao' => '>=10.8.0' diff --git a/scripts/update/class.Updater.php b/scripts/update/class.Updater.php index 3fbab2b0..92995ac0 100755 --- a/scripts/update/class.Updater.php +++ b/scripts/update/class.Updater.php @@ -1,5 +1,5 @@ @@ -75,5 +78,13 @@ public function update($initialVersion) } $this->skip('2.1.0', '3.2.4'); + + if ($this->isVersion('3.2.4')) { + $service = new OntologyLtiUserService(); + $service->setServiceManager($this->getServiceManager()); + $this->getServiceManager()->register(LtiUserService::SERVICE_ID, $service); + + $this->setVersion('3.3.0'); + } } } From 08bc4a4c21c507a9de742e702c91380b8155e6aa Mon Sep 17 00:00:00 2001 From: antoinerobin Date: Wed, 23 Aug 2017 11:20:48 +0200 Subject: [PATCH 08/12] documentation --- config/default/LtiUserService.conf.php | 3 +- models/classes/LtiRestApiService.php | 6 +- models/classes/user/KvLtiUserService.php | 51 ++++++----- models/classes/user/LtiUser.php | 36 ++++---- models/classes/user/LtiUserService.php | 56 +++++++------ .../classes/user/OntologyLtiUserService.php | 84 ++++++++++++------- 6 files changed, 140 insertions(+), 96 deletions(-) diff --git a/config/default/LtiUserService.conf.php b/config/default/LtiUserService.conf.php index 92462ef6..8ce765ef 100644 --- a/config/default/LtiUserService.conf.php +++ b/config/default/LtiUserService.conf.php @@ -1,4 +1,3 @@ getServiceLocator()->get(LtiUserService::SERVICE_ID); - $ltiUser = $service->findUser($id, $consumerResource); + $userIdentifier = $service->getUserIdentifier($id, $consumerResource); - if (is_null($ltiUser)) { + if (is_null($userIdentifier)) { return null; } return array ( - 'id' => $ltiUser->getIdentifier() + 'id' => $userIdentifier ); } } \ No newline at end of file diff --git a/models/classes/user/KvLtiUserService.php b/models/classes/user/KvLtiUserService.php index 657ad853..4917e932 100755 --- a/models/classes/user/KvLtiUserService.php +++ b/models/classes/user/KvLtiUserService.php @@ -1,40 +1,38 @@ + * @author Antoine Robin, * @package taoLti - */ class KvLtiUserService extends LtiUserService { + const OPTION_PERSISTENCE = 'persistence'; const LTI_USER = 'lti_ku_'; @@ -62,9 +60,11 @@ protected function getPersistence() /** * @inheritdoc */ - public function findUser($userId, $ltiConsumer) { - $data = $this->getPersistence()->get(self::LTI_USER . $userId . $ltiConsumer->getUri()); - if($data === false){ + public function findUser(\taoLti_models_classes_LtiLaunchData $ltiContext) + { + $ltiConsumer = \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($ltiContext); + $data = $this->getPersistence()->get(self::LTI_USER . $ltiContext->getUserID() . $ltiConsumer->getUri()); + if ($data === false) { return null; } @@ -74,12 +74,23 @@ public function findUser($userId, $ltiConsumer) { } /** - * Creates a new LTI User with the absolute minimum of required informations - * - * @param \taoLti_models_classes_LtiLaunchData $ltiContext - * @return LtiUser + * @inheritdoc */ - public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext) { + public function getUserIdentifier($userId, $consumer) + { + $data = $this->getPersistence()->get(self::LTI_USER . $userId . $consumer); + if ($data === false) { + return null; + } + return $userId; + } + + + /** + * @inheritdoc + */ + public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext) + { $firstname = ''; $lastname = ''; diff --git a/models/classes/user/LtiUser.php b/models/classes/user/LtiUser.php index 02e5d6b3..1f60430e 100755 --- a/models/classes/user/LtiUser.php +++ b/models/classes/user/LtiUser.php @@ -1,25 +1,26 @@ * @package taoLti - */ class LtiUser extends \common_user_User implements ServiceLocatorAwareInterface { @@ -71,7 +71,8 @@ class LtiUser extends \common_user_User implements ServiceLocatorAwareInterface */ protected $uiLanguage; - public function __construct($launchData, $userUri, $roles, $language = DEFAULT_LANG, $firstname = '', $lastname = '', $email = '', $label = '') { + public function __construct($launchData, $userUri, $roles, $language = DEFAULT_LANG, $firstname = '', $lastname = '', $email = '', $label = '') + { $this->ltiLaunchData = $launchData; $this->userUri = $userUri; $this->roles = $roles; @@ -85,7 +86,8 @@ public function __construct($launchData, $userUri, $roles, $language = DEFAULT_L * (non-PHPdoc) * @see common_user_User::getIdentifier() */ - public function getIdentifier() { + public function getIdentifier() + { return $this->userUri; } @@ -99,7 +101,8 @@ public function getLaunchData() * (non-PHPdoc) * @see common_user_User::getPropertyValues() */ - public function getPropertyValues($property) { + public function getPropertyValues($property) + { $returnValue = null; switch ($property) { case PROPERTY_USER_DEFLG : @@ -112,13 +115,13 @@ public function getPropertyValues($property) { $returnValue = $this->roles; break; case PROPERTY_USER_FIRSTNAME : - $returnValue = [$this->firstname]; + $returnValue = [$this->firstname]; break; case PROPERTY_USER_LASTNAME : - $returnValue = [$this->lastname]; + $returnValue = [$this->lastname]; break; default: - \common_Logger::d('Unkown property '.$property.' requested from '.__CLASS__); + \common_Logger::d('Unkown property ' . $property . ' requested from ' . __CLASS__); $returnValue = array(); } return $returnValue; @@ -129,7 +132,8 @@ public function getPropertyValues($property) { * (non-PHPdoc) * @see common_user_User::refresh() */ - public function refresh() { + public function refresh() + { // nothing to do } @@ -140,9 +144,9 @@ public function refresh() { */ public static function unserialize($data) { - $user = $data !== false ? json_decode($data,true) : array(); + $user = $data !== false ? json_decode($data, true) : array(); - if(isset($user['launchData']) && isset($user['userUri']) && isset($user['roles']) && isset($user['language']) && isset($user['firstname']) && isset($user['lastname']) && isset($user['email']) && isset($user['label'])){ + if (isset($user['launchData']) && isset($user['userUri']) && isset($user['roles']) && isset($user['language']) && isset($user['firstname']) && isset($user['lastname']) && isset($user['email']) && isset($user['label'])) { return new self($user['launchData'], $user['userUri'], $user['roles'], $user['language'], $user['firstname'], $user['lastname'], $user['email'], $user['label']); } diff --git a/models/classes/user/LtiUserService.php b/models/classes/user/LtiUserService.php index 88f2af0f..ce99da55 100755 --- a/models/classes/user/LtiUserService.php +++ b/models/classes/user/LtiUserService.php @@ -1,22 +1,22 @@ + * @author Antoine Antoine, * @package taoLti - */ abstract class LtiUserService extends ConfigurableService { @@ -44,8 +43,9 @@ abstract class LtiUserService extends ConfigurableService * @throws \taoLti_models_classes_LtiException * @return LtiUser */ - public function findOrSpawnUser(\taoLti_models_classes_LtiLaunchData $launchData) { - $taoUser = $this->findUser($launchData->getUserID(), \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($launchData), $launchData); + public function findOrSpawnUser(\taoLti_models_classes_LtiLaunchData $launchData) + { + $taoUser = $this->findUser($launchData); if (is_null($taoUser)) { $taoUser = $this->spawnUser($launchData); } @@ -55,12 +55,20 @@ public function findOrSpawnUser(\taoLti_models_classes_LtiLaunchData $launchData /** * Searches if this user was already created in TAO * - * @param string $userId - * @param \core_kernel_classes_Resource $ltiConsumer + * @param \taoLti_models_classes_LtiLaunchData $ltiContext * @throws \taoLti_models_classes_LtiException * @return LtiUser */ - abstract public function findUser($userId, $ltiConsumer); + abstract public function findUser(\taoLti_models_classes_LtiLaunchData $ltiContext); + + + /** + * Find the tao user identifier related to a lti user id and a consumer + * @param string $userId + * @param \core_kernel_classes_Resource $consumer + * @return mixed + */ + abstract public function getUserIdentifier($userId, $consumer); /** * Creates a new LTI User with the absolute minimum of required informations @@ -71,7 +79,13 @@ abstract public function findUser($userId, $ltiConsumer); abstract public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext); - protected function determineTaoRoles(\taoLti_models_classes_LtiLaunchData $ltiLaunchData) { + /** + * Getting tao roles associated to lti roles + * @param \taoLti_models_classes_LtiLaunchData $ltiLaunchData + * @return array + */ + protected function determineTaoRoles(\taoLti_models_classes_LtiLaunchData $ltiLaunchData) + { $roles = array(); if ($ltiLaunchData->hasVariable(\taoLti_models_classes_LtiLaunchData::ROLES)) { foreach ($ltiLaunchData->getUserRoles() as $role) { @@ -89,14 +103,4 @@ protected function determineTaoRoles(\taoLti_models_classes_LtiLaunchData $ltiLa } return $roles; } - - - protected function getRoles($taoRoles) { - $roles = array(); - foreach ($taoRoles as $role){ - $roles[] = $role->getUri(); - - } - return $roles; - } } diff --git a/models/classes/user/OntologyLtiUserService.php b/models/classes/user/OntologyLtiUserService.php index 96868d95..28481a10 100755 --- a/models/classes/user/OntologyLtiUserService.php +++ b/models/classes/user/OntologyLtiUserService.php @@ -1,22 +1,22 @@ + * @author Antoine Robin, * @package taoLti - */ class OntologyLtiUserService extends LtiUserService { @@ -41,6 +40,8 @@ class OntologyLtiUserService extends LtiUserService const CLASS_LTI_USER = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#LTIConsumer'; + const PROPERTY_USER_LAUNCHDATA = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#LaunchData'; + /** * Searches if this user was already created in TAO * @@ -48,22 +49,23 @@ class OntologyLtiUserService extends LtiUserService * @throws \taoLti_models_classes_LtiException * @return LtiUser */ - public function findUser($userId, $ltiConsumer, $launchdata = null) { + public function findUser(\taoLti_models_classes_LtiLaunchData $ltiContext) + { $class = new \core_kernel_classes_Class(self::CLASS_LTI_USER); $instances = $class->searchInstances(array( - self::PROPERTY_USER_LTIKEY => $userId, - self::PROPERTY_USER_LTICONSUMER => $ltiConsumer + self::PROPERTY_USER_LTIKEY => $ltiContext->getUserID(), + self::PROPERTY_USER_LTICONSUMER => \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($ltiContext) ), array( - 'like' => false + 'like' => false )); if (count($instances) > 1) { throw new \taoLti_models_classes_LtiException( - 'Multiple user accounts found for user key \''.$userId.'\'', + 'Multiple user accounts found for user key \'' . $ltiContext->getUserID() . '\'', LtiErrorMessage::ERROR_SYSTEM_ERROR ); } /** @var \core_kernel_classes_Resource $instance */ - if(count($instances) == 1){ + if (count($instances) == 1) { $instance = current($instances); $properties = $instance->getPropertiesValues( [ @@ -71,13 +73,13 @@ public function findUser($userId, $ltiConsumer, $launchdata = null) { PROPERTY_USER_FIRSTNAME, PROPERTY_USER_LASTNAME, PROPERTY_USER_MAIL, - PROPERTY_USER_ROLES + PROPERTY_USER_ROLES, + self::PROPERTY_USER_LAUNCHDATA ] ); - $roles = $this->getRoles($properties[PROPERTY_USER_ROLES]); - return new LtiUser($launchdata, $instance->getUri(), $roles, (string)$properties[PROPERTY_USER_UILG][0], (string)$properties[PROPERTY_USER_FIRSTNAME][0], (string)$properties[PROPERTY_USER_LASTNAME][0], (string)$properties[PROPERTY_USER_MAIL][0]); + return new LtiUser($ltiContext, $instance->getUri(), $properties[PROPERTY_USER_ROLES], (string)current($properties[PROPERTY_USER_UILG]), (string)current($properties[PROPERTY_USER_FIRSTNAME]), (string)current($properties[PROPERTY_USER_LASTNAME]), (string)current($properties[PROPERTY_USER_MAIL])); } else { return null; @@ -85,24 +87,48 @@ public function findUser($userId, $ltiConsumer, $launchdata = null) { } + /** + * @inheritdoc + */ + public function getUserIdentifier($userId, $ltiConsumer) + { + $class = new \core_kernel_classes_Class(self::CLASS_LTI_USER); + $instances = $class->searchInstances(array( + self::PROPERTY_USER_LTIKEY => $userId, + self::PROPERTY_USER_LTICONSUMER => $ltiConsumer + ), array( + 'like' => false + )); + if (count($instances) > 1) { + throw new \taoLti_models_classes_LtiException( + 'Multiple user accounts found for user key \'' . $userId . '\'', + LtiErrorMessage::ERROR_SYSTEM_ERROR + ); + } + /** @var \core_kernel_classes_Resource $instance */ + if (count($instances) == 1) { + $instance = current($instances); + return $instance->getUri(); + } else { + return null; + } + + } + /** * Creates a new LTI User with the absolute minimum of required informations * * @param \taoLti_models_classes_LtiLaunchData $ltiContext * @return LtiUser */ - public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext) { + public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext) + { $class = new \core_kernel_classes_Class(self::CLASS_LTI_USER); //$lang = tao_models_classes_LanguageService::singleton()->getLanguageByCode(DEFAULT_LANG); $props = array( - self::PROPERTY_USER_LTIKEY => $ltiContext->getUserID(), - self::PROPERTY_USER_LTICONSUMER => \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($ltiContext), - /* - PROPERTY_USER_UILG => $lang, - PROPERTY_USER_DEFLG => $lang, - */ - + self::PROPERTY_USER_LTIKEY => $ltiContext->getUserID(), + self::PROPERTY_USER_LTICONSUMER => \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($ltiContext), ); $firstname = ''; @@ -140,10 +166,10 @@ public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext) { $props[PROPERTY_USER_ROLES] = $roles; $user = $class->createInstanceWithProperties($props); - \common_Logger::i('added User '.$user->getLabel()); + \common_Logger::i('added User ' . $user->getLabel()); - $ltiUser = new LtiUser($ltiContext, $user->getUri(), $roles, $uiLanguage, $firstname, $lastname, $email, $label) ; + $ltiUser = new LtiUser($ltiContext, $user->getUri(), $roles, $uiLanguage, $firstname, $lastname, $email, $label); return $ltiUser; } From 0becd2f0ce45a39e0261f8917146da2157293844 Mon Sep 17 00:00:00 2001 From: antoine Date: Mon, 9 Oct 2017 15:13:06 +0200 Subject: [PATCH 09/12] add a cache for the ltiConsumer resource so we don't call db each time --- models/classes/class.LtiLaunchData.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/models/classes/class.LtiLaunchData.php b/models/classes/class.LtiLaunchData.php index abfb1ff3..ae4ffb29 100755 --- a/models/classes/class.LtiLaunchData.php +++ b/models/classes/class.LtiLaunchData.php @@ -55,6 +55,11 @@ class taoLti_models_classes_LtiLaunchData * @var array */ private $customParams; + + /** + * @var core_kernel_classes_Resource + */ + private $ltiConsumer; /** @@ -206,6 +211,20 @@ public function getToolConsumerName() { ? $this->getVariable(self::TOOL_CONSUMER_INSTANCE_DESCRIPTION) : null; } + + /** + * @return core_kernel_classes_Resource + * @throws tao_models_classes_oauth_Exception + */ + public function getLtiConsumer() + { + if(is_null($this->ltiConsumer)){ + $dataStore = new tao_models_classes_oauth_DataStore(); + $this->ltiConsumer = $dataStore->findOauthConsumerResource($this->getOauthKey()); + } + + return $this->ltiConsumer; + } /** * Return the returnUrl to the tool consumer From 4127564c47a47642787ff6465c2d7f5a8253d4a5 Mon Sep 17 00:00:00 2001 From: antoine Date: Mon, 9 Oct 2017 15:14:06 +0200 Subject: [PATCH 10/12] use the newly created cache --- models/classes/class.LtiService.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/models/classes/class.LtiService.php b/models/classes/class.LtiService.php index 1423ba4d..8edf0e55 100755 --- a/models/classes/class.LtiService.php +++ b/models/classes/class.LtiService.php @@ -84,13 +84,14 @@ public function getCredential($key) { * * @access public * @author Joel Bout, - * @return core_kernel_classes_Resource resource of LtiConsumer + * @param taoLti_models_classes_LtiLaunchData $launchData + * @return core_kernel_classes_Resource resource of LtiConsumer * @throws tao_models_classes_oauth_Exception thrown if no Consumer found for key + * @deprecated use taoLti_models_classes_LtiLaunchData::getLtiConsumer instead */ public function getLtiConsumerResource($launchData) { - $dataStore = new tao_models_classes_oauth_DataStore(); - return $dataStore->findOauthConsumerResource($launchData->getOauthKey()); + return $launchData->getLtiConsumer(); } /** @@ -120,7 +121,7 @@ public function findUser(taoLti_models_classes_LtiLaunchData $ltiContext) { $class = new core_kernel_classes_Class(CLASS_LTI_USER); $instances = $class->searchInstances(array( PROPERTY_USER_LTIKEY => $ltiContext->getUserID(), - PROPERTY_USER_LTICONSUMER => $this->getLtiConsumerResource($ltiContext) + PROPERTY_USER_LTICONSUMER => $ltiContext->getLtiConsumer() ), array( 'like' => false )); @@ -145,7 +146,7 @@ public function spawnUser(taoLti_models_classes_LtiLaunchData $ltiContext) { $props = array( PROPERTY_USER_LTIKEY => $ltiContext->getUserID(), - PROPERTY_USER_LTICONSUMER => $this->getLtiConsumerResource($ltiContext), + PROPERTY_USER_LTICONSUMER => $ltiContext->getLtiConsumer(), /* PROPERTY_USER_UILG => $lang, PROPERTY_USER_DEFLG => $lang, From 630e962588bb0205fe6cf36b76f316c5777d6666 Mon Sep 17 00:00:00 2001 From: antoine Date: Mon, 9 Oct 2017 15:15:02 +0200 Subject: [PATCH 11/12] use the cache instead of the service to get lticonsumer --- models/classes/class.TaoLtiSession.php | 2 +- models/classes/user/KvLtiUserService.php | 4 ++-- models/classes/user/OntologyLtiUserService.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/models/classes/class.TaoLtiSession.php b/models/classes/class.TaoLtiSession.php index 820e25b6..439fa395 100755 --- a/models/classes/class.TaoLtiSession.php +++ b/models/classes/class.TaoLtiSession.php @@ -83,7 +83,7 @@ public function getLtiLinkResource() { if (is_null($this->ltiLink)) { $class = new core_kernel_classes_Class(CLASS_LTI_INCOMINGLINK); - $consumer = taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($this->getLaunchData()); + $consumer = $this->getLaunchData()->getLtiConsumer(); // search for existing resource $instances = $class->searchInstances(array( PROPERTY_LTI_LINK_ID => $this->getLaunchData()->getResourceLinkID(), diff --git a/models/classes/user/KvLtiUserService.php b/models/classes/user/KvLtiUserService.php index 4917e932..d5a6b84d 100755 --- a/models/classes/user/KvLtiUserService.php +++ b/models/classes/user/KvLtiUserService.php @@ -62,7 +62,7 @@ protected function getPersistence() */ public function findUser(\taoLti_models_classes_LtiLaunchData $ltiContext) { - $ltiConsumer = \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($ltiContext); + $ltiConsumer = $ltiContext->getLtiConsumer(); $data = $this->getPersistence()->get(self::LTI_USER . $ltiContext->getUserID() . $ltiConsumer->getUri()); if ($data === false) { return null; @@ -124,7 +124,7 @@ public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext) $userId = $ltiContext->getUserID(); $ltiUser = new LtiUser($ltiContext, $userId, $roles, $uiLanguage, $firstname, $lastname, $email, $label); - $ltiConsumer = \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($ltiContext); + $ltiConsumer = $ltiContext->getLtiConsumer(); $this->getPersistence()->set(self::LTI_USER . $userId . $ltiConsumer->getUri(), json_encode($ltiUser)); return $ltiUser; diff --git a/models/classes/user/OntologyLtiUserService.php b/models/classes/user/OntologyLtiUserService.php index 28481a10..ee44c0a3 100755 --- a/models/classes/user/OntologyLtiUserService.php +++ b/models/classes/user/OntologyLtiUserService.php @@ -54,7 +54,7 @@ public function findUser(\taoLti_models_classes_LtiLaunchData $ltiContext) $class = new \core_kernel_classes_Class(self::CLASS_LTI_USER); $instances = $class->searchInstances(array( self::PROPERTY_USER_LTIKEY => $ltiContext->getUserID(), - self::PROPERTY_USER_LTICONSUMER => \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($ltiContext) + self::PROPERTY_USER_LTICONSUMER => $ltiContext->getLtiConsumer() ), array( 'like' => false )); @@ -128,7 +128,7 @@ public function spawnUser(\taoLti_models_classes_LtiLaunchData $ltiContext) $props = array( self::PROPERTY_USER_LTIKEY => $ltiContext->getUserID(), - self::PROPERTY_USER_LTICONSUMER => \taoLti_models_classes_LtiService::singleton()->getLtiConsumerResource($ltiContext), + self::PROPERTY_USER_LTICONSUMER => $ltiContext->getLtiConsumer(), ); $firstname = ''; From f11eb9252ad09ceb999a463e3f1c1c657a271fd6 Mon Sep 17 00:00:00 2001 From: bugalot Date: Fri, 13 Oct 2017 14:52:29 +0200 Subject: [PATCH 12/12] Camelcase issue --- models/classes/user/KvLtiUserService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/classes/user/KvLtiUserService.php b/models/classes/user/KvLtiUserService.php index d5a6b84d..5f7c961c 100755 --- a/models/classes/user/KvLtiUserService.php +++ b/models/classes/user/KvLtiUserService.php @@ -68,7 +68,7 @@ public function findUser(\taoLti_models_classes_LtiLaunchData $ltiContext) return null; } - $ltiUser = LtiUser::unSerialize($data); + $ltiUser = LtiUser::unserialize($data); return $ltiUser; }