Merge remote-tracking branch 'origin/1.11.x' into 1.11.x

pull/4367/head
Angel Fernando Quiroz Campos 3 years ago
commit 296215a02d
  1. 1
      plugin/ims_lti/.htaccess
  2. 2
      plugin/ims_lti/ImsLtiPlugin.php
  3. 172
      plugin/ims_lti/README.md
  4. 39
      plugin/ims_lti/auth.php
  5. 14
      plugin/ims_lti/configure.php
  6. 4
      plugin/ims_lti/edit.php
  7. 15
      plugin/ims_lti/form.php
  8. 2
      plugin/ims_lti/item_return2.php
  9. 2
      plugin/ims_lti/login.php
  10. 2
      plugin/ims_lti/multiply.php
  11. 2
      plugin/ims_lti/multiply_session.php
  12. 2
      plugin/ims_lti/session.php
  13. 8
      plugin/ims_lti/src/Service/Resource/LtiLineItemResource.php
  14. 4
      plugin/ims_lti/src/Service/Resource/LtiLineItemsResource.php

@ -0,0 +1 @@
AcceptPathInfo On

@ -26,7 +26,7 @@ class ImsLtiPlugin extends Plugin
protected function __construct()
{
$version = '1.8.0';
$version = '1.9.0';
$author = 'Angel Fernando Quiroz Campos';
$message = Display::return_message($this->get_lang('GenerateKeyPairInfo'));

@ -4,140 +4,179 @@ IMS/LTI plugin
Version 1.9.0
> This plugin is meant to be later integrated into Chamilo (in a major version
release).
IMS/LTI defines the possibility to integrate tools or content into Chamilo.
This plugin allows the integration of a new tool into courses, obtaining
data back from those tools and recording them as gradebook "external" activities.
> release).
This plugin allows certified support for LTI 1.0, 1.1, 1.1.1, Deep Linking 1.x, Outcome Services 1.x.
You can get information about the LTI Certification on [this page][certification link].
The LTI 1.3 is being developed.
IMS/LTI defines the possibility to integrate tools or content into Chamilo.
This plugin allows the integration of a new tool into courses, obtaining
data back from those tools and recording them as gradebook "external" activities.
As a platform admin, you can register external tools available for all courses.
You need set the tools settings in the IMS/LTI administration page.
Then the registered tools should be added in each course individually.
As a teacher, you can register external tools available only for the current
course. You need follow the link in the IMS/LTI block located in the Course
Settings tool. Then select a previously tool registered or register a new
Settings tool. Then select a tool registered previously or register a new
external tool.
# Installation
* Prepare your web server to allow to send cookies in all contexts, set the `SameSite` attribute to `None`
* i.e. Apache configuration
```apacheconf
Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure;SameSite=None
```
1. Install the plugin from the Plugins page
2. Enable the plugin from the IMS/LTI Plugin Settings page
3. Assign to the Administrator region (in the regions management page)
# Changelog
## v1.9
> Requires DB changes to upgrade, see [v1.9](#to-v190).
* Add option to add LTI tool to sessions
## v1.8
> Requires DB changes to upgrade, see [v1.8](#to-v180).
* Add option to add replacements for launch params
## v1.7
> Requires DB changes to upgrade, see [v1.8](#to-v170).
* Fix auth params
* Add option to show LTI tool in iframe or new window.
## v1.6
> Requires DB changes to upgrade, see [v1.8](#to-v160).
* Add support to LTI 1.3 and Advantage Services
## v1.5
> Requires DB changes to upgrade, see [v1.8](#to-v151).
* Plugin has passed the tests from the LTI Certification suite.
* Add support for substitution of variable.
See `ImsLti::getSubstitutableParams()`.
* Outcome services has a unique URL and sourced ID.
## v1.4
> Requires DB changes to upgrade, see [v1.8](#to-v140).
* Allow create external tools when there is no key/secret available for launch
## v1.3
> Requires DB changes to upgrade, see [v1.8](#to-v130).
* Privacy settings added. Allow to indicate id the launcher's data
should be sent in request.
## v1.2
> Requires DB changes to upgrade, see [v1.8](#to-v120).
* Register course in which the tool was added.
* Register parent tool from which the new tool comes from.
## v1.1
> Requires DB changes to upgrade, see [v1.8](#to-v110).
* Support for Deep-Linking added.
* Support for outcomes services. And register score on course gradebook.
# Installation
*Prior to installing/uninstalling this plugin, you will need to make sure the src/Chamilo/PluginBundle/Entity folder is
temporarily writeable by the web server.*
1. Install the plugin from the Plugins page
2. Enable the plugin from the IMS/LTI Plugin Settings page
3. Assign to the Administrator region (in the regions management page)
# Upgrading
Run this changes on database:
## To v1.9.0
```sql
ALTER TABLE plugin_ims_lti_tool ADD session_id INT DEFAULT NULL;
ALTER TABLE plugin_ims_lti_tool ADD CONSTRAINT FK_C5E47F7C613FECDF FOREIGN KEY (session_id) REFERENCES session (id);
ALTER TABLE plugin_ims_lti_tool
ADD session_id INT DEFAULT NULL;
ALTER TABLE plugin_ims_lti_tool
ADD CONSTRAINT FK_C5E47F7C613FECDF FOREIGN KEY (session_id) REFERENCES session (id);
CREATE INDEX IDX_C5E47F7C613FECDF ON plugin_ims_lti_tool (session_id);
```
## To v1.8.0
```sql
ALTER TABLE plugin_ims_lti_tool ADD replacement_params LONGTEXT NOT NULL COMMENT '(DC2Type:json)';
ALTER TABLE plugin_ims_lti_tool
ADD replacement_params LONGTEXT NOT NULL COMMENT '(DC2Type:json)';
```
## To v1.7.0
```sql
ALTER TABLE plugin_ims_lti_tool ADD launch_presentation LONGTEXT NOT NULL COMMENT '(DC2Type:json)';
ALTER TABLE plugin_ims_lti_tool
ADD launch_presentation LONGTEXT NOT NULL COMMENT '(DC2Type:json)';
```
## To v1.6.0
```sql
CREATE TABLE plugin_ims_lti_platform (
id INT AUTO_INCREMENT NOT NULL,
kid VARCHAR(255) NOT NULL,
public_key LONGTEXT NOT NULL,
private_key LONGTEXT NOT NULL,
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
CREATE TABLE plugin_ims_lti_token (
id INT AUTO_INCREMENT NOT NULL,
tool_id INT DEFAULT NULL,
scope LONGTEXT NOT NULL COMMENT '(DC2Type:json)',
hash VARCHAR(255) NOT NULL,
created_at INT NOT NULL,
expires_at INT NOT NULL,
CREATE TABLE plugin_ims_lti_platform
(
id INT AUTO_INCREMENT NOT NULL,
kid VARCHAR(255) NOT NULL,
public_key LONGTEXT NOT NULL,
private_key LONGTEXT NOT NULL,
PRIMARY KEY (id)
) DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci
ENGINE = InnoDB;
CREATE TABLE plugin_ims_lti_token
(
id INT AUTO_INCREMENT NOT NULL,
tool_id INT DEFAULT NULL,
scope LONGTEXT NOT NULL COMMENT '(DC2Type:json)',
hash VARCHAR(255) NOT NULL,
created_at INT NOT NULL,
expires_at INT NOT NULL,
INDEX IDX_F7B5692F8F7B22CC (tool_id),
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
PRIMARY KEY (id)
) DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci
ENGINE = InnoDB;
ALTER TABLE plugin_ims_lti_token
ADD CONSTRAINT FK_F7B5692F8F7B22CC FOREIGN KEY (tool_id) REFERENCES plugin_ims_lti_tool (id) ON DELETE CASCADE;
ALTER TABLE plugin_ims_lti_tool
ADD client_id VARCHAR(255) DEFAULT NULL,
ADD public_key LONGTEXT DEFAULT NULL,
ADD login_url VARCHAR(255) DEFAULT NULL,
ADD redirect_url VARCHAR(255) DEFAULT NULL,
ADD advantage_services LONGTEXT DEFAULT NULL COMMENT '(DC2Type:json)',
ADD version VARCHAR(255) DEFAULT 'lti1p1' NOT NULL;
CREATE TABLE plugin_ims_lti_lineitem (
id INT AUTO_INCREMENT NOT NULL,
tool_id INT NOT NULL,
evaluation INT NOT NULL,
ADD client_id VARCHAR(255) DEFAULT NULL,
ADD public_key LONGTEXT DEFAULT NULL,
ADD login_url VARCHAR(255) DEFAULT NULL,
ADD redirect_url VARCHAR(255) DEFAULT NULL,
ADD advantage_services LONGTEXT DEFAULT NULL COMMENT '(DC2Type:json)',
ADD version VARCHAR(255) DEFAULT 'lti1p1' NOT NULL;
CREATE TABLE plugin_ims_lti_lineitem
(
id INT AUTO_INCREMENT NOT NULL,
tool_id INT NOT NULL,
evaluation INT NOT NULL,
resource_id VARCHAR(255) DEFAULT NULL,
tag VARCHAR(255) DEFAULT NULL,
start_date DATETIME DEFAULT NULL,
end_date DATETIME DEFAULT NULL,
tag VARCHAR(255) DEFAULT NULL,
start_date DATETIME DEFAULT NULL,
end_date DATETIME DEFAULT NULL,
INDEX IDX_BA81BBF08F7B22CC (tool_id),
UNIQUE INDEX UNIQ_BA81BBF01323A575 (evaluation),
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
PRIMARY KEY (id)
) DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci
ENGINE = InnoDB;
ALTER TABLE plugin_ims_lti_lineitem
ADD CONSTRAINT FK_BA81BBF08F7B22CC FOREIGN KEY (tool_id) REFERENCES plugin_ims_lti_tool (id) ON DELETE CASCADE;
ALTER TABLE plugin_ims_lti_lineitem
@ -145,6 +184,7 @@ ALTER TABLE plugin_ims_lti_lineitem
```
## To v1.5.1
```sql
ALTER TABLE plugin_ims_lti_tool
DROP FOREIGN KEY FK_C5E47F7C727ACA70,
@ -152,6 +192,7 @@ ALTER TABLE plugin_ims_lti_tool
```
## To v1.4
```sql
ALTER TABLE plugin_ims_lti_tool
CHANGE consumer_key consumer_key VARCHAR(255) DEFAULT NULL,
@ -159,34 +200,41 @@ ALTER TABLE plugin_ims_lti_tool
```
## To v1.3
```sql
ALTER TABLE plugin_ims_lti_tool ADD privacy LONGTEXT DEFAULT NULL;
ALTER TABLE plugin_ims_lti_tool
ADD privacy LONGTEXT DEFAULT NULL;
```
## To v1.2
```sql
ALTER TABLE plugin_ims_lti_tool ADD c_id INT DEFAULT NULL;
ALTER TABLE plugin_ims_lti_tool ADD CONSTRAINT FK_C5E47F7C91D79BD3
FOREIGN KEY (c_id) REFERENCES course (id);
ALTER TABLE plugin_ims_lti_tool
ADD c_id INT DEFAULT NULL;
ALTER TABLE plugin_ims_lti_tool
ADD CONSTRAINT FK_C5E47F7C91D79BD3 FOREIGN KEY (c_id) REFERENCES course (id);
CREATE INDEX IDX_C5E47F7C91D79BD3 ON plugin_ims_lti_tool (c_id);
ALTER TABLE plugin_ims_lti_tool ADD parent_id INT DEFAULT NULL, DROP is_global;
ALTER TABLE plugin_ims_lti_tool ADD CONSTRAINT FK_C5E47F7C727ACA70
FOREIGN KEY (parent_id) REFERENCES plugin_ims_lti_tool (id);
ALTER TABLE plugin_ims_lti_tool
ADD parent_id INT DEFAULT NULL,
DROP is_global;
ALTER TABLE plugin_ims_lti_tool
ADD CONSTRAINT FK_C5E47F7C727ACA70 FOREIGN KEY (parent_id) REFERENCES plugin_ims_lti_tool (id);
CREATE INDEX IDX_C5E47F7C727ACA70 ON plugin_ims_lti_tool (parent_id);
```
## To v1.1
```sql
ALTER TABLE plugin_ims_lti_tool
ADD active_deep_linking TINYINT(1) DEFAULT '0' NOT NULL,
CHANGE id id INT AUTO_INCREMENT NOT NULL,
CHANGE launch_url launch_url VARCHAR(255) NOT NULL;
ALTER TABLE plugin_ims_lti_tool ADD gradebook_eval_id INT DEFAULT NULL;
ALTER TABLE plugin_ims_lti_tool ADD CONSTRAINT FK_C5E47F7C82F80D8B
FOREIGN KEY (gradebook_eval_id) REFERENCES gradebook_evaluation (id)
ON DELETE SET NULL;
ALTER TABLE plugin_ims_lti_tool
ADD gradebook_eval_id INT DEFAULT NULL;
ALTER TABLE plugin_ims_lti_tool
ADD CONSTRAINT FK_C5E47F7C82F80D8B FOREIGN KEY (gradebook_eval_id) REFERENCES gradebook_evaluation (id) ON DELETE SET NULL;
CREATE INDEX IDX_C5E47F7C82F80D8B ON plugin_ims_lti_tool (gradebook_eval_id);
```

@ -7,7 +7,7 @@ use Firebase\JWT\JWT;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_course_script(false);
api_protect_course_script();
api_block_anonymous_users(false);
$scope = empty($_REQUEST['scope']) ? '' : trim($_REQUEST['scope']);
@ -26,6 +26,8 @@ $em = Database::getManager();
$webPath = api_get_path(WEB_PATH);
$webPluginPath = api_get_path(WEB_PLUGIN_PATH);
$tool = null;
try {
if (
empty($scope) ||
@ -64,12 +66,12 @@ try {
throw LtiAuthException::invalidRequest();
}
/** @var ImsLtiTool $tool */
$tool = $em
->find('ChamiloPluginBundle:ImsLti\ImsLtiTool', $ltiToolLogin);
if (empty($tool)) {
throw LtiAuthException::invalidRequest();
try {
/** @var ImsLtiTool $tool */
$tool = $em
->find('ChamiloPluginBundle:ImsLti\ImsLtiTool', $ltiToolLogin);
} catch (\Exception $e) {
api_not_allowed(true);
}
if ($tool->getClientId() != $clientId) {
@ -207,15 +209,21 @@ try {
if (LtiAssignmentGradesService::AGS_NONE !== $advServices['ags']) {
$agsClaim = [
'scope' => [
LtiAssignmentGradesService::SCOPE_LINE_ITEM,
LtiAssignmentGradesService::SCOPE_LINE_ITEM_READ,
LtiAssignmentGradesService::SCOPE_RESULT_READ,
LtiAssignmentGradesService::SCOPE_SCORE_WRITE,
],
'lineitems' => LtiAssignmentGradesService::getLineItemsUrl(
$course->getId(),
$tool->getId()
),
];
if (LtiAssignmentGradesService::AGS_FULL === $advServices['ags']) {
$agsClaim['scope'][] = LtiAssignmentGradesService::SCOPE_LINE_ITEM;
}
$agsClaim['lineitems'] = LtiAssignmentGradesService::getLineItemsUrl(
$course->getId(),
$tool->getId()
);
if ($tool->getLineItems()->count() === 1) {
$agsClaim['lineitem'] = LtiAssignmentGradesService::getLineItemUrl(
$course->getId(),
@ -255,7 +263,8 @@ try {
$course,
$session,
$platformDomain,
ImsLti::V_1P3
ImsLti::V_1P3,
$tool
);
}
@ -288,6 +297,10 @@ try {
];
}
if (!$tool) {
exit;
}
$formActionUrl = $tool->isActiveDeepLinking() ? $tool->getRedirectUrl() : $tool->getLaunchUrl();
?>
<!DOCTYPE html>

@ -17,8 +17,7 @@ $toolsRepo = $em->getRepository('ChamiloPluginBundle:ImsLti\ImsLtiTool');
$baseTool = isset($_REQUEST['type']) ? $toolsRepo->find(intval($_REQUEST['type'])) : null;
$action = !empty($_REQUEST['action']) ? $_REQUEST['action'] : 'add';
/** @var Course $course */
$course = $em->find('ChamiloCoreBundle:Course', api_get_course_int_id());
$course = api_get_course_entity(api_get_course_int_id());
$addedTools = $toolsRepo->findBy(['course' => $course]);
$globalTools = $toolsRepo->findBy(['parent' => null, 'course' => null]);
@ -84,9 +83,7 @@ switch ($action) {
->setRedirectUrl($formValues['redirect_url'])
->setAdvantageServices(
[
'ags' => isset($formValues['1p3_ags'])
? $formValues['1p3_ags']
: LtiAssignmentGradesService::AGS_NONE,
'ags' => $formValues['1p3_ags'] ?? LtiAssignmentGradesService::AGS_NONE,
'nrps' => $formValues['1p3_nrps'],
]
)
@ -213,9 +210,7 @@ switch ($action) {
->setRedirectUrl($formValues['redirect_url'])
->setAdvantageServices(
[
'ags' => isset($formValues['1p3_ags'])
? $formValues['1p3_ags']
: LtiAssignmentGradesService::AGS_NONE,
'ags' => $formValues['1p3_ags'] ?? LtiAssignmentGradesService::AGS_NONE,
'nrps' => $formValues['1p3_nrps'],
]
)
@ -247,6 +242,9 @@ switch ($action) {
$form->setDefaultValues();
break;
default:
api_not_allowed(true);
break;
}
$template = new Template($plugin->get_lang('AddExternalTool'));

@ -69,9 +69,7 @@ if ($form->validate()) {
->setRedirectUrl($formValues['redirect_url'])
->setAdvantageServices(
[
'ags' => isset($formValues['1p3_ags'])
? $formValues['1p3_ags']
: LtiAssignmentGradesService::AGS_NONE,
'ags' => $formValues['1p3_ags'] ?? LtiAssignmentGradesService::AGS_NONE,
'nrps' => $formValues['1p3_nrps'],
]
)

@ -1,14 +1,11 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
use Chamilo\UserBundle\Entity\User;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_course_script(false);
api_protect_course_script();
api_block_anonymous_users(false);
$em = Database::getManager();
@ -22,14 +19,10 @@ if (!$tool) {
api_not_allowed(true);
}
/** @var ImsLtiPlugin $imsLtiPlugin */
$imsLtiPlugin = ImsLtiPlugin::create();
/** @var Session $session */
$session = $em->find('ChamiloCoreBundle:Session', api_get_session_id());
/** @var Course $course */
$course = $em->find('ChamiloCoreBundle:Course', api_get_course_int_id());
/** @var User $user */
$user = $em->find('ChamiloUserBundle:User', api_get_user_id());
$session = api_get_session_entity();
$course = api_get_course_entity();
$user = api_get_user_entity(api_get_user_id());
$pluginPath = api_get_path(WEB_PLUGIN_PATH).'ims_lti/';
$toolUserId = ImsLtiPlugin::getLaunchUserIdClaim($tool, $user);

@ -6,7 +6,7 @@ use Firebase\JWT\JWT;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_course_script(false);
api_protect_course_script();
api_block_anonymous_users(false);
$jwt = empty($_REQUEST['JWT']) ? '' : $_REQUEST['JWT'];

@ -6,7 +6,7 @@ use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_course_script(true);
api_block_anonymous_users(true);
api_block_anonymous_users();
$em = Database::getManager();

@ -8,7 +8,7 @@ $cidReset = true;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script(false);
api_protect_admin_script();
$plugin = ImsLtiPlugin::create();
$webPluginPath = api_get_path(WEB_PLUGIN_PATH).'ims_lti/';

@ -8,7 +8,7 @@ $cidReset = true;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script(false);
api_protect_admin_script();
$plugin = ImsLtiPlugin::create();
$webPluginPath = api_get_path(WEB_PLUGIN_PATH).'ims_lti/';

@ -8,7 +8,7 @@ $cidReset = true;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script(false);
api_protect_admin_script();
$plugin = ImsLtiPlugin::create();
$webPluginPath = api_get_path(WEB_PLUGIN_PATH).'ims_lti/';

@ -56,12 +56,20 @@ class LtiLineItemResource extends LtiAdvantageServiceResource
$this->processGet();
break;
case Request::METHOD_PUT:
if (LtiAssignmentGradesService::AGS_FULL !== $this->tool->getAdvantageServices()['ags']) {
throw new MethodNotAllowedHttpException([Request::METHOD_GET]);
}
$this->validateToken(
[LtiAssignmentGradesService::SCOPE_LINE_ITEM]
);
$this->processPut();
break;
case Request::METHOD_DELETE:
if (LtiAssignmentGradesService::AGS_FULL !== $this->tool->getAdvantageServices()['ags']) {
throw new MethodNotAllowedHttpException([Request::METHOD_GET]);
}
$this->validateToken(
[LtiAssignmentGradesService::SCOPE_LINE_ITEM]
);

@ -67,6 +67,10 @@ class LtiLineItemsResource extends LtiAdvantageServiceResource
{
switch ($this->request->getMethod()) {
case Request::METHOD_POST:
if (LtiAssignmentGradesService::AGS_FULL !== $this->tool->getAdvantageServices()['ags']) {
throw new MethodNotAllowedHttpException([Request::METHOD_GET]);
}
$this->validateToken(
[
LtiAssignmentGradesService::SCOPE_LINE_ITEM,

Loading…
Cancel
Save