MDL-62815 mod_lti: adjust new capabilities

MDL-62815 mod_lti: improve lang strings + use clonepermissionsfrom

MDL-62815 mod_lti: prevent changing from manual instance without cap
This commit is contained in:
Davo Smith 2019-01-23 16:21:45 +00:00
parent e3b82acdc1
commit 477e87170b
9 changed files with 136 additions and 180 deletions

View File

@ -91,24 +91,26 @@ $capabilities = array(
)
),
// The ability to a globally preconfigured instance to the course.
'mod/lti:addgloballypreconfigedtoolinstance' => array(
// The ability to a preconfigured instance to the course.
'mod/lti:addpreconfiguredinstance' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
'clonepermissionsfrom' => 'mod/lti:addinstance',
),
// The ability to add a default instance (i.e. not from a preconfigured tool) to the course.
'mod/lti:adddefaultinstance' => array(
// The ability to add a manual instance (i.e. not from a preconfigured tool) to the course.
'mod/lti:addmanualinstance' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
'clonepermissionsfrom' => 'mod/lti:addinstance',
),
// The ability to request the administrator to configure a particular

View File

@ -210,7 +210,7 @@ In addition, all web service requests from the tool provider will use SSL.
If using this option, confirm that this Moodle site and the tool provider support SSL.';
$string['generaltool'] = 'General tool';
$string['global_tool_types'] = 'Global preconfigured tools';
$string['global_tool_types'] = 'Preconfigured tools';
$string['grading'] = 'Grade routing';
$string['icon_url'] = 'Icon URL';
$string['icon_url_help'] = 'The icon URL allows the icon that shows up in the course listing for this activity to be modified. Instead of using the default
@ -254,10 +254,10 @@ real estate to the tool, and others provide a more integrated feel with the Mood
$string['launchoptions'] = 'Launch options';
$string['leaveblank'] = 'Leave blank if you do not need them';
$string['lti'] = 'LTI';
$string['lti:adddefaultinstance'] = 'Add a non-globally-configured tool';
$string['lti:addgloballypreconfigedtoolinstance'] = 'Add a globally preconfigured tool';
$string['lti:addinstance'] = 'Add a new external tool';
$string['lti:addcoursetool'] = 'Add course-specific tool configurations';
$string['lti:addmanualinstance'] = 'Add a manually-configured tool';
$string['lti:addinstance'] = 'Add a new external tool';
$string['lti:addpreconfiguredinstance'] = 'Add a preconfigured tool';
$string['lti:grade'] = 'View grades returned by the external tool';
$string['lti:manage'] = 'Be an Instructor when the tool is launched';
$string['lti:admin'] = 'Be an administrator when the tool is launched';

View File

@ -103,8 +103,6 @@ function lti_add_instance($lti, $mform) {
$lti->typeid = $lti->urlmatchedtypeid;
}
lti_require_type_access($lti);
if (!isset($lti->instructorchoiceacceptgrades) || $lti->instructorchoiceacceptgrades != LTI_SETTING_ALWAYS) {
// The instance does not accept grades back from the provider, so set to "No grade" value 0.
$lti->grade = 0;
@ -167,8 +165,6 @@ function lti_update_instance($lti, $mform) {
$lti->typeid = $lti->urlmatchedtypeid;
}
lti_require_type_access($lti);
$completiontimeexpected = !empty($lti->completionexpected) ? $lti->completionexpected : null;
\core_completion\api::update_completion_date_event($lti->coursemodule, 'lti', $lti->id, $completiontimeexpected);
@ -223,7 +219,7 @@ function lti_get_shortcuts($defaultitem) {
require_once($CFG->dirroot.'/mod/lti/locallib.php');
$types = lti_get_configured_types($COURSE->id, $defaultitem->link->param('sr'));
if (has_capability('mod/lti:adddefaultinstance', context_course::instance($COURSE->id))) {
if (has_capability('mod/lti:addmanualinstance', context_course::instance($COURSE->id))) {
$types[] = $defaultitem;
}

View File

@ -2130,10 +2130,10 @@ function lti_get_lti_types_by_course($courseid, $coursevisible = null) {
list($coursevisiblesql, $coursevisparams) = $DB->get_in_or_equal($coursevisible, SQL_PARAMS_NAMED, 'coursevisible');
$courseconds = [];
if (has_capability('mod/lti:adddefaultinstance', context_course::instance($courseid))) {
if (has_capability('mod/lti:addmanualinstance', context_course::instance($courseid))) {
$courseconds[] = "course = :courseid";
}
if (has_capability('mod/lti:addgloballypreconfigedtoolinstance', context_course::instance($courseid))) {
if (has_capability('mod/lti:addpreconfiguredinstance', context_course::instance($courseid))) {
$courseconds[] = "course = :siteid";
}
if (!$courseconds) {
@ -2160,7 +2160,7 @@ function lti_get_types_for_add_instance() {
$admintypes = lti_get_lti_types_by_course($COURSE->id);
$types = array();
if (has_capability('mod/lti:adddefaultinstance', context_course::instance($COURSE->id))) {
if (has_capability('mod/lti:addmanualinstance', context_course::instance($COURSE->id))) {
$types[0] = (object)array('name' => get_string('automatic', 'lti'), 'course' => 0, 'toolproxyid' => null);
}
@ -4261,29 +4261,3 @@ function lti_new_access_token($typeid, $scopes) {
return $newtoken;
}
/**
* Checks if user can add tool. Throws a capability exception otherwise.
* @param object $lti
* @return void
* @throws required_capability_exception
*/
function lti_require_type_access($lti) {
global $DB, $SITE;
if (empty($lti->typeid)) {
// This is not a global tool.
require_capability('mod/lti:adddefaultinstance', context_course::instance($lti->course));
return;
}
$toolcourseid = $DB->get_field('lti_types', 'course', ['id' => $lti->typeid], MUST_EXIST);
if ($toolcourseid != $SITE->id) {
// Not a global tool.
require_capability('mod/lti:adddefaultinstance', context_course::instance($lti->course));
return;
}
// This is a global tool.
require_capability('mod/lti:addgloballypreconfigedtoolinstance', context_course::instance($lti->course));
}

View File

@ -60,6 +60,23 @@ class mod_lti_mod_form extends moodleform_mod {
component_callback("ltisource_$type", 'add_instance_hook');
}
// Type ID parameter being passed when adding an preconfigured tool from activity chooser.
$typeid = optional_param('typeid', false, PARAM_INT);
// Show configuration details only if not preset (when new) or user has the capabilities to do so (when editing).
if ($this->_instance) {
$showtypes = has_capability('mod/lti:addpreconfiguredinstance', $this->context);
$showoptions = has_capability('mod/lti:addmanualinstance', $this->context);
if (!$showoptions && $this->current->typeid == 0) {
// If you cannot add a manual instance and this is already a manual instance, then
// remove the 'types' selector.
$showtypes = false;
}
} else {
$showtypes = !$typeid;
$showoptions = !$typeid && has_capability('mod/lti:addmanualinstance', $this->context);
}
$this->typeid = 0;
$mform =& $this->_form;
@ -95,122 +112,131 @@ class mod_lti_mod_form extends moodleform_mod {
$mform->addHelpButton('showdescriptionlaunch', 'display_description', 'lti');
// Tool settings.
$tooltypes = $mform->addElement('select', 'typeid', get_string('external_tool_type', 'lti'));
// Type ID parameter being passed when adding an preconfigured tool from activity chooser.
$typeid = optional_param('typeid', false, PARAM_INT);
if ($typeid) {
$mform->getElement('typeid')->setValue($typeid);
}
$mform->addHelpButton('typeid', 'external_tool_type', 'lti');
$toolproxy = array();
// Array of tool type IDs that don't support ContentItemSelectionRequest.
$noncontentitemtypes = [];
foreach (lti_get_types_for_add_instance() as $id => $type) {
if (!empty($type->toolproxyid)) {
$toolproxy[] = $type->id;
$attributes = array( 'globalTool' => 1, 'toolproxy' => 1);
$enabledcapabilities = explode("\n", $type->enabledcapability);
if (!in_array('Result.autocreate', $enabledcapabilities) || in_array('BasicOutcome.url', $enabledcapabilities)) {
$attributes['nogrades'] = 1;
}
if (!in_array('Person.name.full', $enabledcapabilities) && !in_array('Person.name.family', $enabledcapabilities) &&
!in_array('Person.name.given', $enabledcapabilities)) {
$attributes['noname'] = 1;
}
if (!in_array('Person.email.primary', $enabledcapabilities)) {
$attributes['noemail'] = 1;
}
} else if ($type->course == $COURSE->id) {
$attributes = array( 'editable' => 1, 'courseTool' => 1, 'domain' => $type->tooldomain );
} else if ($id != 0) {
$attributes = array( 'globalTool' => 1, 'domain' => $type->tooldomain);
} else {
$attributes = array();
if ($showtypes) {
$tooltypes = $mform->addElement('select', 'typeid', get_string('external_tool_type', 'lti'));
if ($typeid) {
$mform->getElement('typeid')->setValue($typeid);
}
$mform->addHelpButton('typeid', 'external_tool_type', 'lti');
if ($id) {
$config = lti_get_type_config($id);
if (!empty($config['contentitem'])) {
$attributes['data-contentitem'] = 1;
$attributes['data-id'] = $id;
foreach (lti_get_types_for_add_instance() as $id => $type) {
if (!empty($type->toolproxyid)) {
$toolproxy[] = $type->id;
$attributes = array('globalTool' => 1, 'toolproxy' => 1);
$enabledcapabilities = explode("\n", $type->enabledcapability);
if (!in_array('Result.autocreate', $enabledcapabilities) ||
in_array('BasicOutcome.url', $enabledcapabilities)) {
$attributes['nogrades'] = 1;
}
if (!in_array('Person.name.full', $enabledcapabilities) &&
!in_array('Person.name.family', $enabledcapabilities) &&
!in_array('Person.name.given', $enabledcapabilities)) {
$attributes['noname'] = 1;
}
if (!in_array('Person.email.primary', $enabledcapabilities)) {
$attributes['noemail'] = 1;
}
} else if ($type->course == $COURSE->id) {
$attributes = array('editable' => 1, 'courseTool' => 1, 'domain' => $type->tooldomain);
} else if ($id != 0) {
$attributes = array('globalTool' => 1, 'domain' => $type->tooldomain);
} else {
$noncontentitemtypes[] = $id;
$attributes = array();
}
if ($id) {
$config = lti_get_type_config($id);
if (!empty($config['contentitem'])) {
$attributes['data-contentitem'] = 1;
$attributes['data-id'] = $id;
} else {
$noncontentitemtypes[] = $id;
}
}
$tooltypes->addOption($type->name, $id, $attributes);
}
$tooltypes->addOption($type->name, $id, $attributes);
} else {
$mform->addElement('hidden', 'typeid', $typeid);
$mform->setType('typeid', PARAM_INT);
}
// Add button that launches the content-item selection dialogue.
// Set contentitem URL.
$contentitemurl = new moodle_url('/mod/lti/contentitem.php');
$contentbuttonattributes = [
'data-contentitemurl' => $contentitemurl->out(false)
];
$contentbuttonlabel = get_string('selectcontent', 'lti');
$contentbutton = $mform->addElement('button', 'selectcontent', $contentbuttonlabel, $contentbuttonattributes);
// Disable select content button if the selected tool doesn't support content item or it's set to Automatic.
$allnoncontentitemtypes = $noncontentitemtypes;
$allnoncontentitemtypes[] = '0'; // Add option value for "Automatic, based on tool URL".
$mform->disabledIf('selectcontent', 'typeid', 'in', $allnoncontentitemtypes);
if ($showoptions) {
// Set contentitem URL.
$contentitemurl = new moodle_url('/mod/lti/contentitem.php');
$contentbuttonattributes = [
'data-contentitemurl' => $contentitemurl->out(false)
];
$contentbuttonlabel = get_string('selectcontent', 'lti');
$contentbutton = $mform->addElement('button', 'selectcontent', $contentbuttonlabel, $contentbuttonattributes);
// Disable select content button if the selected tool doesn't support content item or it's set to Automatic.
$allnoncontentitemtypes = $noncontentitemtypes;
$allnoncontentitemtypes[] = '0'; // Add option value for "Automatic, based on tool URL".
$mform->disabledIf('selectcontent', 'typeid', 'in', $allnoncontentitemtypes);
$mform->addElement('text', 'toolurl', get_string('launch_url', 'lti'), array('size' => '64'));
$mform->setType('toolurl', PARAM_URL);
$mform->addHelpButton('toolurl', 'launch_url', 'lti');
$mform->hideIf('toolurl', 'typeid', 'in', $noncontentitemtypes);
$mform->addElement('text', 'toolurl', get_string('launch_url', 'lti'), array('size' => '64'));
$mform->setType('toolurl', PARAM_URL);
$mform->addHelpButton('toolurl', 'launch_url', 'lti');
$mform->hideIf('toolurl', 'typeid', 'in', $noncontentitemtypes);
$mform->addElement('text', 'securetoolurl', get_string('secure_launch_url', 'lti'), array('size' => '64'));
$mform->setType('securetoolurl', PARAM_URL);
$mform->setAdvanced('securetoolurl');
$mform->addHelpButton('securetoolurl', 'secure_launch_url', 'lti');
$mform->hideIf('securetoolurl', 'typeid', 'in', $noncontentitemtypes);
$mform->addElement('text', 'securetoolurl', get_string('secure_launch_url', 'lti'), array('size' => '64'));
$mform->setType('securetoolurl', PARAM_URL);
$mform->setAdvanced('securetoolurl');
$mform->addHelpButton('securetoolurl', 'secure_launch_url', 'lti');
$mform->hideIf('securetoolurl', 'typeid', 'in', $noncontentitemtypes);
}
$mform->addElement('hidden', 'urlmatchedtypeid', '', array( 'id' => 'id_urlmatchedtypeid' ));
$mform->setType('urlmatchedtypeid', PARAM_INT);
$launchoptions = array();
$launchoptions[LTI_LAUNCH_CONTAINER_DEFAULT] = get_string('default', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_EMBED] = get_string('embed', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS] = get_string('embed_no_blocks', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_REPLACE_MOODLE_WINDOW] = get_string('existing_window', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_WINDOW] = get_string('new_window', 'lti');
if ($showoptions) {
$launchoptions = array();
$launchoptions[LTI_LAUNCH_CONTAINER_DEFAULT] = get_string('default', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_EMBED] = get_string('embed', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS] = get_string('embed_no_blocks', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_REPLACE_MOODLE_WINDOW] = get_string('existing_window', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_WINDOW] = get_string('new_window', 'lti');
$mform->addElement('select', 'launchcontainer', get_string('launchinpopup', 'lti'), $launchoptions);
$mform->setDefault('launchcontainer', LTI_LAUNCH_CONTAINER_DEFAULT);
$mform->addHelpButton('launchcontainer', 'launchinpopup', 'lti');
$mform->setAdvanced('launchcontainer');
$mform->addElement('select', 'launchcontainer', get_string('launchinpopup', 'lti'), $launchoptions);
$mform->setDefault('launchcontainer', LTI_LAUNCH_CONTAINER_DEFAULT);
$mform->addHelpButton('launchcontainer', 'launchinpopup', 'lti');
$mform->setAdvanced('launchcontainer');
$mform->addElement('text', 'resourcekey', get_string('resourcekey', 'lti'));
$mform->setType('resourcekey', PARAM_TEXT);
$mform->setAdvanced('resourcekey');
$mform->addHelpButton('resourcekey', 'resourcekey', 'lti');
$mform->setForceLtr('resourcekey');
$mform->hideIf('resourcekey', 'typeid', 'in', $noncontentitemtypes);
$mform->addElement('text', 'resourcekey', get_string('resourcekey', 'lti'));
$mform->setType('resourcekey', PARAM_TEXT);
$mform->setAdvanced('resourcekey');
$mform->addHelpButton('resourcekey', 'resourcekey', 'lti');
$mform->setForceLtr('resourcekey');
$mform->hideIf('resourcekey', 'typeid', 'in', $noncontentitemtypes);
$mform->addElement('passwordunmask', 'password', get_string('password', 'lti'));
$mform->setType('password', PARAM_TEXT);
$mform->setAdvanced('password');
$mform->addHelpButton('password', 'password', 'lti');
$mform->hideIf('password', 'typeid', 'in', $noncontentitemtypes);
$mform->addElement('passwordunmask', 'password', get_string('password', 'lti'));
$mform->setType('password', PARAM_TEXT);
$mform->setAdvanced('password');
$mform->addHelpButton('password', 'password', 'lti');
$mform->hideIf('password', 'typeid', 'in', $noncontentitemtypes);
$mform->addElement('textarea', 'instructorcustomparameters', get_string('custom', 'lti'), array('rows' => 4, 'cols' => 60));
$mform->setType('instructorcustomparameters', PARAM_TEXT);
$mform->setAdvanced('instructorcustomparameters');
$mform->addHelpButton('instructorcustomparameters', 'custom', 'lti');
$mform->setForceLtr('instructorcustomparameters');
$mform->addElement('textarea', 'instructorcustomparameters', get_string('custom', 'lti'), array('rows' => 4, 'cols' => 60));
$mform->setType('instructorcustomparameters', PARAM_TEXT);
$mform->setAdvanced('instructorcustomparameters');
$mform->addHelpButton('instructorcustomparameters', 'custom', 'lti');
$mform->setForceLtr('instructorcustomparameters');
$mform->addElement('text', 'icon', get_string('icon_url', 'lti'), array('size' => '64'));
$mform->setType('icon', PARAM_URL);
$mform->setAdvanced('icon');
$mform->addHelpButton('icon', 'icon_url', 'lti');
$mform->hideIf('icon', 'typeid', 'in', $noncontentitemtypes);
$mform->addElement('text', 'icon', get_string('icon_url', 'lti'), array('size' => '64'));
$mform->setType('icon', PARAM_URL);
$mform->setAdvanced('icon');
$mform->addHelpButton('icon', 'icon_url', 'lti');
$mform->hideIf('icon', 'typeid', 'in', $noncontentitemtypes);
$mform->addElement('text', 'secureicon', get_string('secure_icon_url', 'lti'), array('size' => '64'));
$mform->setType('secureicon', PARAM_URL);
$mform->setAdvanced('secureicon');
$mform->addHelpButton('secureicon', 'secure_icon_url', 'lti');
$mform->hideIf('secureicon', 'typeid', 'in', $noncontentitemtypes);
$mform->addElement('text', 'secureicon', get_string('secure_icon_url', 'lti'), array('size' => '64'));
$mform->setType('secureicon', PARAM_URL);
$mform->setAdvanced('secureicon');
$mform->addHelpButton('secureicon', 'secure_icon_url', 'lti');
$mform->hideIf('secureicon', 'typeid', 'in', $noncontentitemtypes);
}
// Add privacy preferences fieldset where users choose whether to send their data.
$mform->addElement('header', 'privacy', get_string('privacy', 'lti'));
@ -289,32 +315,6 @@ class mod_lti_mod_form extends moodleform_mod {
}
$PAGE->requires->js_init_call('M.mod_lti.editor.init', array(json_encode($jsinfo)), true, $module);
// Show configuration details only if not preset (when new) or user has the capabilities to do so (when editing).
$ctxcourse = context_course::instance($COURSE->id);
if (optional_param('update', 0, PARAM_INT)) {
$listtypes = has_capability('mod/lti:addgloballypreconfigedtoolinstance', $ctxcourse);
$listoptions = has_capability('mod/lti:adddefaultinstance', $ctxcourse);
} else {
$listtypes = !$typeid;
$listoptions = !$typeid && has_capability('mod/lti:adddefaultinstance', $ctxcourse);
}
if (!$listtypes) {
$mform->removeElement('typeid');
$mform->addElement('hidden', 'typeid', $typeid);
$mform->setType('typeid', PARAM_INT);
}
if (!$listoptions) {
$mform->removeElement('selectcontent');
$mform->removeElement('toolurl');
$mform->removeElement('securetoolurl');
$mform->removeElement('launchcontainer');
$mform->removeElement('resourcekey');
$mform->removeElement('password');
$mform->removeElement('instructorcustomparameters');
$mform->removeElement('icon');
$mform->removeElement('secureicon');
}
}
}

View File

@ -50,8 +50,6 @@ class ltiservice_gradebookservices_cleanup_task_testcase extends advanced_testca
public function test_cleanup_task() {
global $DB;
$this->setAdminuser();
// Create a course.
$course = $this->getDataGenerator()->create_course();

View File

@ -41,8 +41,6 @@ class mod_lti_generator_testcase extends advanced_testcase {
$this->resetAfterTest(true);
$this->setAdminuser();
$this->assertEquals(0, $DB->count_records('lti'));
$course = $this->getDataGenerator()->create_course();

View File

@ -204,7 +204,7 @@ class mod_lti_locallib_testcase extends advanced_testcase {
public function test_lti_buid_request_resource_link_id() {
$this->resetAfterTest();
$this->setAdminUser();
self::setUser($this->getDataGenerator()->create_user());
$course = $this->getDataGenerator()->create_course();
$instance = $this->getDataGenerator()->create_module('lti', array(
'intro' => "<p>This</p>\nhas\r\n<p>some</p>\nnew\n\rlines",
@ -243,7 +243,7 @@ class mod_lti_locallib_testcase extends advanced_testcase {
public function test_lti_build_request_description() {
$this->resetAfterTest();
$this->setAdminUser();
self::setUser($this->getDataGenerator()->create_user());
$course = $this->getDataGenerator()->create_course();
$instance = $this->getDataGenerator()->create_module('lti', array(
'intro' => "<p>This</p>\nhas\r\n<p>some</p>\nnew\n\rlines",

View File

@ -86,8 +86,6 @@ class mod_lti_privacy_provider_testcase extends \core_privacy\tests\provider_tes
public function test_get_contexts_for_userid() {
$this->resetAfterTest();
$this->setAdminuser();
$course = $this->getDataGenerator()->create_course();
// The LTI activity the user will have submitted something for.
@ -120,8 +118,6 @@ class mod_lti_privacy_provider_testcase extends \core_privacy\tests\provider_tes
public function test_get_users_in_context() {
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$component = 'mod_lti';
@ -163,8 +159,6 @@ class mod_lti_privacy_provider_testcase extends \core_privacy\tests\provider_tes
public function test_export_for_context_submissions() {
$this->resetAfterTest();
$this->setAdminuser();
$course = $this->getDataGenerator()->create_course();
$lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id));
@ -272,8 +266,6 @@ class mod_lti_privacy_provider_testcase extends \core_privacy\tests\provider_tes
$this->resetAfterTest();
$this->setAdminuser();
$course = $this->getDataGenerator()->create_course();
$lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id));
@ -306,8 +298,6 @@ class mod_lti_privacy_provider_testcase extends \core_privacy\tests\provider_tes
$this->resetAfterTest();
$this->setAdminuser();
$course = $this->getDataGenerator()->create_course();
$lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id));
@ -348,8 +338,6 @@ class mod_lti_privacy_provider_testcase extends \core_privacy\tests\provider_tes
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$lti = $this->getDataGenerator()->create_module('lti', array('course' => $course->id));