From 81bfbd71e23805c5b13e306ece1640db07d5c224 Mon Sep 17 00:00:00 2001 From: Angel Fernando Quiroz Campos Date: Thu, 5 Nov 2020 18:53:01 -0500 Subject: [PATCH] XAPI: Allow set basic auth for LRS - refs BT#16742 --- plugin/xapi/lang/english.php | 11 ++--- plugin/xapi/launch/add.php | 23 ++++++++--- plugin/xapi/launch/edit.php | 21 +++++++--- plugin/xapi/launch/launch.php | 19 ++++++--- plugin/xapi/launch/tool.php | 6 ++- plugin/xapi/src/Entity/ToolLaunch.php | 40 ++++++++++++++---- plugin/xapi/src/XApiPlugin.php | 59 ++++++++++----------------- 7 files changed, 112 insertions(+), 67 deletions(-) diff --git a/plugin/xapi/lang/english.php b/plugin/xapi/lang/english.php index 19548ee684..0d825cf02a 100644 --- a/plugin/xapi/lang/english.php +++ b/plugin/xapi/lang/english.php @@ -7,11 +7,12 @@ $strings['plugin_comment'] = 'Allow to incorporate an Learning Record Store and $strings[XApiPlugin::SETTING_UUID_NAMESPACE] = 'UUID Namespace'; $strings[XApiPlugin::SETTING_UUID_NAMESPACE.'_help'] = 'Namespace for universally unique identifiers used as statement IDs.' .'
This is automatically by Chamilo LMS. Don\'t replace it.'; -$strings[XApiPlugin::SETTING_LRS_URL] = 'LRS: URL for API'; -$strings[XApiPlugin::SETTING_LRS_URL.'_help'] = 'Sets the LRS base URL.'; -$strings[XApiPlugin::SETTING_LRS_AUTH] = 'LRS: Authentication method'; -$strings[XApiPlugin::SETTING_LRS_AUTH.'_help'] = 'Sets HTTP authentication credentials.
'; -$strings[XApiPlugin::SETTING_LRS_AUTH.'_help'] .= 'Choose one auth method: Basic (basic:username:password) or OAuth1 (oauth:key:secret)'; +$strings['lrs_url'] = 'LRS endpoint'; +$strings['lrs_url_help'] = 'Base URL from the LRS'; +$strings['lrs_auth_username'] = 'LRS user'; +$strings['lrs_auth_username_help'] = 'Username for basic HTTP authentication'; +$strings['lrs_auth_password'] = 'LRS password'; +$strings['lrs_auth_password_help'] = 'Password for basic HTTP authentication'; $strings['NoActivities'] = 'No activities added yet'; $strings['ActivityTitle'] = 'Activity'; diff --git a/plugin/xapi/launch/add.php b/plugin/xapi/launch/add.php index 0290f048ea..75c633093b 100644 --- a/plugin/xapi/launch/add.php +++ b/plugin/xapi/launch/add.php @@ -37,8 +37,16 @@ $frmActivity->addText( $frmActivity->addText( 'lrs_auth', [ - $plugin->get_lang('lrs_auth'), - $plugin->get_lang('lrs_auth_help'), + $plugin->get_lang('lrs_auth_username'), + $plugin->get_lang('lrs_auth_username_help'), + ], + false +); +$frmActivity->addText( + 'lrs_auth', + [ + $plugin->get_lang('lrs_auth_password'), + $plugin->get_lang('lrs_auth_password_help'), ], false ); @@ -84,9 +92,14 @@ if ($frmActivity->validate()) { $toolLaunch->setDescription($values['description']); } - if (!empty($values['lrs_url']) && !empty($values['lrs_auth'])) { - $toolLaunch->setLrsUrl($values['lrs_url']); - $toolLaunch->setLrsAuth($values['lrs_auth']); + if (!empty($values['lrs_url']) + && !empty($values['lrs_auth_username']) + && !empty($values['lrs_auth_password']) + ) { + $toolLaunch + ->setLrsUrl($values['lrs_url']) + ->setLrsAuthUsername($values['lrs_auth_username']) + ->setLrsAuthUsername($values['lrs_auth_password']); } $em = Database::getManager(); diff --git a/plugin/xapi/launch/edit.php b/plugin/xapi/launch/edit.php index 1efe8c5c4a..d810f30f1a 100644 --- a/plugin/xapi/launch/edit.php +++ b/plugin/xapi/launch/edit.php @@ -56,8 +56,16 @@ $frmActivity->addText( $frmActivity->addText( 'lrs_auth', [ - $plugin->get_lang('lrs_auth'), - $plugin->get_lang('lrs_auth_help'), + $plugin->get_lang('lrs_auth_username'), + $plugin->get_lang('lrs_auth_username_help'), + ], + false +); +$frmActivity->addText( + 'lrs_auth', + [ + $plugin->get_lang('lrs_auth_password'), + $plugin->get_lang('lrs_auth_password_help'), ], false ); @@ -82,8 +90,10 @@ if ($frmActivity->validate()) { ); if (!empty($values['lrs_url']) && !empty($values['lrs_auth'])) { - $toolLaunch->setLrsUrl($values['lrs_url']); - $toolLaunch->setLrsAuth($values['lrs_auth']); + $toolLaunch + ->setLrsUrl($values['lrs_url']) + ->setLrsAuthUsername($values['lrs_auth_username']) + ->setLrsAuthPassword($values['lrs_auth_password']); } $courseTool = $plugin->getCourseToolFromLaunchTool($toolLaunch); @@ -110,7 +120,8 @@ $frmActivity->setDefaults( 'launch_url' => $toolLaunch->getLaunchUrl(), 'allow_multiple_attempts' => $toolLaunch->isAllowMultipleAttempts(), 'lrs_url' => $toolLaunch->getLrsUrl(), - 'lrs_auth' => $toolLaunch->getLrsAuth(), + 'lrs_auth_username' => $toolLaunch->getLrsAuthUsername(), + 'lrs_auth_password' => $toolLaunch->getLrsAuthPassword(), ] ); diff --git a/plugin/xapi/launch/launch.php b/plugin/xapi/launch/launch.php index 5427895b5c..c64f759bae 100644 --- a/plugin/xapi/launch/launch.php +++ b/plugin/xapi/launch/launch.php @@ -57,7 +57,13 @@ $state = new State( $nowDate = api_get_utc_datetime(null, false, true)->format('c'); try { - $stateDocument = $plugin->getXApiStateClient()->getDocument($state); + $stateDocument = $plugin + ->getXApiStateClient( + $toolLaunch->getLrsUrl(), + $toolLaunch->getLrsAuthUsername(), + $toolLaunch->getLrsAuthPassword() + ) + ->getDocument($state); $data = $stateDocument->getData()->getData(); @@ -111,19 +117,20 @@ try { exit; } -$authString = $plugin->get(XApiPlugin::SETTING_LRS_AUTH); -$parts = explode(':', $authString); +$lrsUrl = $toolLaunch->getLrsUrl() ?: $plugin->get(XApiPlugin::SETTING_LRS_URL); +$lrsAuthUsername = $toolLaunch->getLrsAuthUsername() ?: $plugin->get(XApiPlugin::SETTING_LRS_AUTH_USERNAME); +$lrsAuthPassword = $toolLaunch->getLrsAuthPassword() ?: $plugin->get(XApiPlugin::SETTING_LRS_AUTH_PASSWORD); $activityLaunchUrl = $toolLaunch->getLaunchUrl().'?' .http_build_query( [ - 'endpoint' => $plugin->get(XApiPlugin::SETTING_LRS_URL), - 'auth' => 'Basic '.base64_encode("{$parts[1]}:{$parts[2]}"), + 'endpoint' => trim($lrsUrl, "/ \t\n\r\0\x0B"), + 'auth' => 'Basic '.base64_encode(trim($lrsAuthUsername).':'.trim($lrsAuthPassword)), 'actor' => Serializer::createSerializer()->serialize($actor, 'json'), 'registration' => $attemptId, 'activity_id' => $toolLaunch->getActivityId(), ], - '', + null, '&', PHP_QUERY_RFC3986 ); diff --git a/plugin/xapi/launch/tool.php b/plugin/xapi/launch/tool.php index 53affb633a..34c65db7d3 100644 --- a/plugin/xapi/launch/tool.php +++ b/plugin/xapi/launch/tool.php @@ -54,7 +54,11 @@ $cidReq = api_get_cidreq(); try { $stateDocument = $plugin - ->getXApiStateClient($toolLaunch->getLrsUrl(), $toolLaunch->getLrsAuth()) + ->getXApiStateClient( + $toolLaunch->getLrsUrl(), + $toolLaunch->getLrsAuthUsername(), + $toolLaunch->getLrsAuthPassword() + ) ->getDocument($state); } catch (NotFoundException $notFoundException) { $stateDocument = null; diff --git a/plugin/xapi/src/Entity/ToolLaunch.php b/plugin/xapi/src/Entity/ToolLaunch.php index 992b54e944..4accc5ad3e 100644 --- a/plugin/xapi/src/Entity/ToolLaunch.php +++ b/plugin/xapi/src/Entity/ToolLaunch.php @@ -85,9 +85,15 @@ class ToolLaunch /** * @var string|null * - * @ORM\Column(name="lrs_auth", type="string", nullable=true) + * @ORM\Column(name="lrs_auth_username", type="string", nullable=true) */ - private $lrsAuth; + private $lrsAuthUsername; + /** + * @var string|null + * + * @ORM\Column(name="lrs_auth_password", type="string", nullable=true) + */ + private $lrsAuthPassword; /*** * @var \DateTime * @@ -326,19 +332,39 @@ class ToolLaunch /** * @return string|null */ - public function getLrsAuth(): ?string + public function getLrsAuthUsername(): ?string + { + return $this->lrsAuthUsername; + } + + /** + * @param string|null $lrsAuthUsername + * + * @return ToolLaunch + */ + public function setLrsAuthUsername(?string $lrsAuthUsername): ToolLaunch + { + $this->lrsAuthUsername = $lrsAuthUsername; + + return $this; + } + + /** + * @return string|null + */ + public function getLrsAuthPassword(): ?string { - return $this->lrsAuth; + return $this->lrsAuthPassword; } /** - * @param string|null $lrsAuth + * @param string|null $lrsAuthPassword * * @return ToolLaunch */ - public function setLrsAuth(?string $lrsAuth): ToolLaunch + public function setLrsAuthPassword(?string $lrsAuthPassword): ToolLaunch { - $this->lrsAuth = $lrsAuth; + $this->lrsAuthPassword = $lrsAuthPassword; return $this; } diff --git a/plugin/xapi/src/XApiPlugin.php b/plugin/xapi/src/XApiPlugin.php index 133fa78af1..4d3e69e3d3 100644 --- a/plugin/xapi/src/XApiPlugin.php +++ b/plugin/xapi/src/XApiPlugin.php @@ -18,7 +18,8 @@ use Xabbuh\XApi\Client\XApiClientBuilderInterface; class XApiPlugin extends Plugin implements HookPluginInterface { const SETTING_LRS_URL = 'lrs_url'; - const SETTING_LRS_AUTH = 'lrs_auth'; + const SETTING_LRS_AUTH_USERNAME = 'lrs_auth_username'; + const SETTING_LRS_AUTH_PASSWORD = 'lrs_auth_password'; const SETTING_UUID_NAMESPACE = 'uuid_namespace'; const SETTING_LRS_LP_ITEM_ACTIVE = 'lrs_lp_item_viewed_active'; const SETTING_LRS_LP_ACTIVE = 'lrs_lp_end_active'; @@ -59,8 +60,11 @@ class XApiPlugin extends Plugin implements HookPluginInterface ]; $settings = [ self::SETTING_UUID_NAMESPACE => 'text', + self::SETTING_LRS_URL => 'text', - self::SETTING_LRS_AUTH => 'text', + self::SETTING_LRS_AUTH_USERNAME => 'text', + self::SETTING_LRS_AUTH_PASSWORD => 'text', + self::SETTING_LRS_LP_ITEM_ACTIVE => 'boolean', self::SETTING_LRS_LP_ACTIVE => 'boolean', self::SETTING_LRS_QUIZ_ACTIVE => 'boolean', @@ -194,13 +198,16 @@ class XApiPlugin extends Plugin implements HookPluginInterface /** * @param string|null $lrsUrl - * @param string|null $lrsAuth + * @param string|null $lrsAuthUsername + * @param string|null $lrsAuthPassword * * @return \Xabbuh\XApi\Client\Api\StateApiClientInterface */ - public function getXApiStateClient($lrsUrl = null, $lrsAuth = null) + public function getXApiStateClient($lrsUrl = null, $lrsAuthUsername = null, $lrsAuthPassword = null) { - return $this->createXApiClient($lrsUrl, $lrsAuth)->getStateApiClient(); + return $this + ->createXApiClient($lrsUrl, $lrsAuthUsername, $lrsAuthPassword) + ->getStateApiClient(); } /** @@ -213,49 +220,25 @@ class XApiPlugin extends Plugin implements HookPluginInterface /** * @param string|null $lrsUrl - * @param string|null $lrsAuth + * @param string|null $lrsAuthUsername + * @param string|null $lrsAuthPassword * * @return \Xabbuh\XApi\Client\XApiClientInterface */ - public function createXApiClient($lrsUrl = null, $lrsAuth = null) + private function createXApiClient($lrsUrl = null, $lrsAuthUsername = null, $lrsAuthPassword = null) { - $baseUrl = $lrsUrl ?: trim($this->get(self::SETTING_LRS_URL), "/ \t\n\r\0\x0B"); + $baseUrl = $lrsUrl ?: $this->get(self::SETTING_LRS_URL); + $lrsAuthUsername = $lrsAuthUsername ?: $this->get(self::SETTING_LRS_AUTH_USERNAME); + $lrsAuthPassword = $lrsAuthPassword ?: $this->get(self::SETTING_LRS_AUTH_PASSWORD); $clientBuilder = new XApiClientBuilder(); $clientBuilder ->setHttpClient(Client::createWithConfig([RequestOptions::VERIFY => false])) ->setRequestFactory(new GuzzleMessageFactory()) - ->setBaseUrl($baseUrl); - - return $this - ->setAuthMethodToClient($clientBuilder, $lrsAuth) - ->build(); - } - - /** - * @param \Xabbuh\XApi\Client\XApiClientBuilderInterface $clientBuilder - * @param string|null $lrsAuth - * - * @return \Xabbuh\XApi\Client\XApiClientBuilderInterface - */ - private function setAuthMethodToClient(XApiClientBuilderInterface $clientBuilder, $lrsAuth = null) - { - $authString = $lrsAuth ?: $this->get(self::SETTING_LRS_AUTH); - - $parts = explode(':', $authString); - - if (!empty($parts)) { - $method = strtolower($parts[0]); - - switch ($method) { - case 'basic': - return $clientBuilder->setAuth($parts[1], $parts[2]); - case 'oauth': - return $clientBuilder->setOAuthCredentials($parts[1], $parts[2]); - } - } + ->setBaseUrl(trim($baseUrl, "/ \t\n\r\0\x0B")) + ->setAuth(trim($lrsAuthUsername), trim($lrsAuthPassword)); - return $clientBuilder; + return $clientBuilder->build(); } /**