MDL-58090 oauth2: Move code from subclasses to config

Allow the behaviour of each oauth service to be customised by config instead of
subclasses.

Part of MDL-58220
This commit is contained in:
Damyon Wiese 2017-02-24 16:40:37 +08:00
parent 60237253a2
commit 8445556b4c
21 changed files with 961 additions and 117 deletions

View File

@ -0,0 +1,81 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the form add/update oauth2 endpoint.
*
* @package tool_oauth2
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_oauth2\form;
defined('MOODLE_INTERNAL') || die();
use stdClass;
use core\form\persistent;
/**
* Issuer form.
*
* @package tool_oauth2
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class endpoint extends persistent {
protected static $persistentclass = 'core\\oauth2\\endpoint';
protected static $fieldstoremove = array('submitbutton', 'action');
/**
* Define the form - called by parent constructor
*/
public function definition() {
global $PAGE;
$mform = $this->_form;
$endpoint = $this->get_persistent();
$mform->addElement('header', 'generalhdr', get_string('general'));
// Name.
$mform->addElement('text', 'name', get_string('endpointname', 'tool_oauth2'), 'maxlength="255"');
$mform->addRule('name', null, 'required', null, 'client');
$mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
$mform->addHelpButton('name', 'endpointname', 'tool_oauth2');
// Url.
$mform->addElement('text', 'url', get_string('endpointurl', 'tool_oauth2'), 'maxlength="1024"');
$mform->addRule('url', null, 'required', null, 'client');
$mform->addRule('url', get_string('maximumchars', '', 1024), 'maxlength', 1024, 'client');
$mform->addHelpButton('url', 'endpointurl', 'tool_oauth2');
$mform->addElement('hidden', 'action', 'edit');
$mform->setType('action', PARAM_RAW);
$mform->addElement('hidden', 'issuerid', $endpoint->get('issuerid'));
$mform->setType('issuerid', PARAM_INT);
$mform->setConstant('issuerid', $this->_customdata['issuerid']);
$mform->addElement('hidden', 'id', $endpoint->get('id'));
$mform->setType('id', PARAM_INT);
$this->add_action_buttons(true, get_string('savechanges', 'tool_oauth2'));
}
}

View File

@ -48,7 +48,7 @@ class issuer extends persistent {
global $PAGE;
$mform = $this->_form;
$provider = $this->get_persistent();
$endpoint = $this->get_persistent();
$mform->addElement('header', 'generalhdr', get_string('general'));
@ -77,7 +77,7 @@ class issuer extends persistent {
$mform->addHelpButton('baseurl', 'issuerbaseurl', 'tool_oauth2');
// Offline access type
$options = $provider->get_behaviour_list();
$options = $endpoint->get_behaviour_list();
$mform->addElement('select', 'behaviour', get_string('issuerbehaviour', 'tool_oauth2'), $options);
$mform->addHelpButton('behaviour', 'issuerbehaviour', 'tool_oauth2');
@ -97,7 +97,7 @@ class issuer extends persistent {
$mform->addElement('hidden', 'action', 'edit');
$mform->setType('action', PARAM_RAW);
$mform->addElement('hidden', 'id', $provider->get('id'));
$mform->addElement('hidden', 'id', $endpoint->get('id'));
$mform->setType('id', PARAM_INT);
$this->add_action_buttons(true, get_string('savechanges', 'tool_oauth2'));

View File

@ -0,0 +1,80 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the form add/update oauth2 user_field_mapping.
*
* @package tool_oauth2
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_oauth2\form;
defined('MOODLE_INTERNAL') || die();
use stdClass;
use core\form\persistent;
/**
* Issuer form.
*
* @package tool_oauth2
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class user_field_mapping extends persistent {
protected static $persistentclass = 'core\\oauth2\\user_field_mapping';
protected static $fieldstoremove = array('submitbutton', 'action');
/**
* Define the form - called by parent constructor
*/
public function definition() {
global $PAGE;
$mform = $this->_form;
$userfieldmapping = $this->get_persistent();
$mform->addElement('header', 'generalhdr', get_string('general'));
// External.
$mform->addElement('text', 'externalfield', get_string('userfieldexternalfield', 'tool_oauth2'), 'maxlength="255"');
$mform->addRule('externalfield', null, 'required', null, 'client');
$mform->addRule('externalfield', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
$mform->addHelpButton('externalfield', 'userfieldexternalfield', 'tool_oauth2');
// Internal.
$choices = $userfieldmapping->get_internalfield_list();
$mform->addElement('select', 'internalfield', get_string('userfieldinternalfield', 'tool_oauth2'), $choices);
$mform->addHelpButton('internalfield', 'userfieldinternalfield', 'tool_oauth2');
$mform->addElement('hidden', 'action', 'edit');
$mform->setType('action', PARAM_RAW);
$mform->addElement('hidden', 'issuerid', $userfieldmapping->get('issuerid'));
$mform->setConstant('issuerid', $this->_customdata['issuerid']);
$mform->setType('issuerid', PARAM_INT);
$mform->addElement('hidden', 'id', $userfieldmapping->get('id'));
$mform->setType('id', PARAM_INT);
$this->add_action_buttons(true, get_string('savechanges', 'tool_oauth2'));
}
}

View File

@ -79,7 +79,7 @@ class renderer extends plugin_renderer_base {
$name = $issuer->get('name');
$image = $issuer->get('image');
if ($image) {
$name = '<img width=24 height=24 alt="" src="' . $image . '"> ' . $name;
$name = '<img width=24 height=24 alt="" src="' . s($image) . '"> ' . s($name);
}
$namecell = new html_table_cell($name);
$namecell->header = true;
@ -104,7 +104,11 @@ class renderer extends plugin_renderer_base {
if (!empty($issuer->get('scopessupported'))) {
$discovered = $OUTPUT->pix_icon('yes', get_string('discovered', 'tool_oauth2'), 'tool_oauth2');
} else {
$discovered = $OUTPUT->pix_icon('no', get_string('notdiscovered', 'tool_oauth2'), 'tool_oauth2');
if ($issuer->get('behaviour') == $issuer::BEHAVIOUR_OPENID_CONNECT) {
$discovered = $OUTPUT->pix_icon('no', get_string('notdiscovered', 'tool_oauth2'), 'tool_oauth2');
} else {
$discovered = '-';
}
}
$discoverystatuscell = new html_table_cell($discovered);
@ -125,22 +129,37 @@ class renderer extends plugin_renderer_base {
$systemauthstatuscell = new html_table_cell($systemauth);
// Action links.
$links = '';
// Action links.
$editurl = new moodle_url('/admin/tool/oauth2/issuers.php', ['id' => $issuer->get('id'), 'action' => 'edit']);
$editlink = html_writer::link($editurl, $OUTPUT->pix_icon('t/edit', get_string('edit')));
$links .= ' ' . $editlink;
// Endpoints.
$editendpointsurl = new moodle_url('/admin/tool/oauth2/endpoints.php', ['issuerid' => $issuer->get('id')]);
$str = get_string('editendpoints', 'tool_oauth2');
$editendpointlink = html_writer::link($editendpointsurl, $OUTPUT->pix_icon('t/viewdetails', $str));
$links .= ' ' . $editendpointlink;
// User field mapping.
$edituserfieldmappingsurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', ['issuerid' => $issuer->get('id')]);
$str = get_string('edituserfieldmappings', 'tool_oauth2');
$edituserfieldmappinglink = html_writer::link($edituserfieldmappingsurl, $OUTPUT->pix_icon('t/user', $str));
$links .= ' ' . $edituserfieldmappinglink;
// Delete.
$deleteurl = new moodle_url('/admin/tool/oauth2/issuers.php', ['id' => $issuer->get('id'), 'action' => 'delete']);
$deletelink = html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete')));
$links .= ' ' . $deletelink;
if (!$last) {
// Move down.
$params = ['id' => $issuer->get('id'), 'action' => 'movedown', 'sesskey' => sesskey()];
$movedownurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params);
$movedownlink = html_writer::link($movedownurl, $OUTPUT->pix_icon('t/down', get_string('movedown')));
$links .= ' ' . $movedownlink;
}
if (!$first) {
// Move up.
$params = ['id' => $issuer->get('id'), 'action' => 'moveup', 'sesskey' => sesskey()];
$moveupurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params);
$moveuplink = html_writer::link($moveupurl, $OUTPUT->pix_icon('t/up', get_string('moveup')));
@ -164,4 +183,119 @@ class renderer extends plugin_renderer_base {
$table->data = $data;
return html_writer::table($table);
}
/**
* This function will render one beautiful table with all the endpoints.
*
* @param \core\oauth2\endpoint[] $endpoints - list of all endpoints.
* @return string HTML to output.
*/
public function endpoints_table($endpoints, $issuerid) {
global $CFG, $OUTPUT;
$table = new html_table();
$table->head = [
get_string('name'),
get_string('url'),
get_string('edit'),
];
$table->attributes['class'] = 'admintable generaltable';
$data = [];
$index = 0;
foreach ($endpoints as $endpoint) {
// Name.
$name = $endpoint->get('name');
$namecell = new html_table_cell(s($name));
$namecell->header = true;
// Url
$url = $endpoint->get('url');
$urlcell = new html_table_cell(s($url));
$links = '';
// Action links.
$editparams = ['issuerid' => $issuerid, 'endpointid' => $endpoint->get('id'), 'action' => 'edit'];
$editurl = new moodle_url('/admin/tool/oauth2/endpoints.php', $editparams);
$editlink = html_writer::link($editurl, $OUTPUT->pix_icon('t/edit', get_string('edit')));
$links .= ' ' . $editlink;
// Delete.
$deleteparams = ['issuerid' => $issuerid, 'endpointid' => $endpoint->get('id'), 'action' => 'delete'];
$deleteurl = new moodle_url('/admin/tool/oauth2/endpoints.php', $deleteparams);
$deletelink = html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete')));
$links .= ' ' . $deletelink;
$editcell = new html_table_cell($links);
$row = new html_table_row([
$namecell,
$urlcell,
$editcell,
]);
$data[] = $row;
$index++;
}
$table->data = $data;
return html_writer::table($table);
}
/**
* This function will render one beautiful table with all the user_field_mappings.
*
* @param \core\oauth2\user_field_mapping[] $userfieldmappings - list of all user_field_mappings.
* @return string HTML to output.
*/
public function user_field_mappings_table($userfieldmappings, $issuerid) {
global $CFG, $OUTPUT;
$table = new html_table();
$table->head = [
get_string('userfieldexternalfield', 'tool_oauth2'),
get_string('userfieldinternalfield', 'tool_oauth2'),
get_string('edit'),
];
$table->attributes['class'] = 'admintable generaltable';
$data = [];
$index = 0;
foreach ($userfieldmappings as $userfieldmapping) {
// External field
$externalfield = $userfieldmapping->get('externalfield');
$externalfieldcell = new html_table_cell(s($externalfield));
// Internal field
$internalfield = $userfieldmapping->get('internalfield');
$internalfieldcell = new html_table_cell(s($internalfield));
$links = '';
// Action links.
$editparams = ['issuerid' => $issuerid, 'userfieldmappingid' => $userfieldmapping->get('id'), 'action' => 'edit'];
$editurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', $editparams);
$editlink = html_writer::link($editurl, $OUTPUT->pix_icon('t/edit', get_string('edit')));
$links .= ' ' . $editlink;
// Delete.
$deleteparams = ['issuerid' => $issuerid, 'userfieldmappingid' => $userfieldmapping->get('id'), 'action' => 'delete'];
$deleteurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', $deleteparams);
$deletelink = html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete')));
$links .= ' ' . $deletelink;
$editcell = new html_table_cell($links);
$row = new html_table_row([
$externalfieldcell,
$internalfieldcell,
$editcell,
]);
$data[] = $row;
$index++;
}
$table->data = $data;
return html_writer::table($table);
}
}

View File

@ -0,0 +1,128 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* OAuth 2 Endpoing Configuration page.
*
* @package tool_oauth2
* @copyright 2017 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
$PAGE->set_url('/admin/tool/oauth2/endpoints.php', ['issuerid' => required_param('issuerid', PARAM_INT)]);
$PAGE->set_context(context_system::instance());
$PAGE->set_pagelayout('admin');
$strheading = get_string('pluginname', 'tool_oauth2');
$PAGE->set_title($strheading);
$PAGE->set_heading($strheading);
require_login();
require_capability('moodle/site:config', context_system::instance());
$renderer = $PAGE->get_renderer('tool_oauth2');
$action = optional_param('action', '', PARAM_ALPHAEXT);
$issuerid = required_param('issuerid', PARAM_INT);
$endpointid = optional_param('endpointid', '', PARAM_INT);
$endpoint = null;
$mform = null;
$issuer = \core\oauth2\api::get_issuer($issuerid);
if (!$issuer) {
print_error('invaliddata');
}
$PAGE->navbar->override_active_url(new moodle_url('/admin/tool/oauth2/issuers.php'), true);
if (!empty($endpointid)) {
$endpoint = \core\oauth2\api::get_endpoint($endpointid);
}
if ($action == 'edit') {
if ($endpoint) {
$strparams = [ 'issuer' => s($issuer->get('name')), 'endpoint' => s($endpoint->get('name')) ];
$PAGE->navbar->add(get_string('editendpoint', 'tool_oauth2', $strparams));
} else {
$PAGE->navbar->add(get_string('createnewendpoint', 'tool_oauth2', s($issuer->get('name'))));
}
$mform = new \tool_oauth2\form\endpoint(null, ['persistent' => $endpoint, 'issuerid' => $issuerid]);
}
if ($mform && $mform->is_cancelled()) {
redirect(new moodle_url('/admin/tool/oauth2/endpoints.php', ['issuerid' => $issuerid]));
} else if ($action == 'edit') {
if ($data = $mform->get_data()) {
try {
if (!empty($data->id)) {
core\oauth2\api::update_endpoint($data);
} else {
core\oauth2\api::create_endpoint($data);
}
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
} catch (Exception $e) {
redirect($PAGE->url, $e->getMessage(), null, \core\output\notification::NOTIFY_ERROR);
}
} else {
echo $OUTPUT->header();
if ($endpoint) {
$strparams = [ 'issuer' => s($issuer->get('name')), 'endpoint' => s($endpoint->get('name')) ];
echo $OUTPUT->heading(get_string('editendpoint', 'tool_oauth2', $strparams));
} else {
echo $OUTPUT->heading(get_string('createnewendpoint', 'tool_oauth2', s($issuer->get('name'))));
}
$mform->display();
echo $OUTPUT->footer();
}
} else if ($action == 'delete') {
if (!optional_param('confirm', false, PARAM_BOOL)) {
$continueparams = [
'action' => 'delete',
'issuerid' => $issuerid,
'endpointid' => $endpointid,
'sesskey' => sesskey(),
'confirm' => true
];
$continueurl = new moodle_url('/admin/tool/oauth2/endpoints.php', $continueparams);
$cancelurl = new moodle_url('/admin/tool/oauth2/endpoints.php');
echo $OUTPUT->header();
$strparams = [ 'issuer' => s($issuer->get('name')), 'endpoint' => s($endpoint->get('name')) ];
echo $OUTPUT->confirm(get_string('deleteendpointconfirm', 'tool_oauth2', $strparams), $continueurl, $cancelurl);
echo $OUTPUT->footer();
} else {
require_sesskey();
core\oauth2\api::delete_endpoint($endpointid);
redirect($PAGE->url, get_string('endpointdeleted', 'tool_oauth2'), null, \core\output\notification::NOTIFY_SUCCESS);
}
} else {
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('endpointsforissuer', 'tool_oauth2', s($issuer->get('name'))));
$endpoints = core\oauth2\api::get_endpoints($issuer);
echo $renderer->endpoints_table($endpoints, $issuerid);
$addurl = new moodle_url('/admin/tool/oauth2/endpoints.php', ['action' => 'edit', 'issuerid' => $issuerid]);
echo $renderer->single_button($addurl, get_string('createnewendpoint', 'tool_oauth2', s($issuer->get('name'))));
echo $OUTPUT->footer();
}

View File

@ -40,12 +40,12 @@ require_capability('moodle/site:config', context_system::instance());
$renderer = $PAGE->get_renderer('tool_oauth2');
$action = optional_param('action', '', PARAM_ALPHAEXT);
$idpid = optional_param('id', '', PARAM_RAW);
$issuerid = optional_param('id', '', PARAM_RAW);
$issuer = null;
$mform = null;
if ($idpid) {
$issuer = \core\oauth2\api::get_issuer($idpid);
if ($issuerid) {
$issuer = \core\oauth2\api::get_issuer($issuerid);
if (!$issuer) {
print_error('invaliddata');
}
@ -53,7 +53,7 @@ if ($idpid) {
if ($action == 'edit') {
if ($issuer) {
$PAGE->navbar->add(get_string('editissuer', 'tool_oauth2', $issuer->get('name')));
$PAGE->navbar->add(get_string('editissuer', 'tool_oauth2', s($issuer->get('name'))));
} else {
$PAGE->navbar->add(get_string('createnewissuer', 'tool_oauth2'));
}
@ -80,7 +80,7 @@ if ($mform && $mform->is_cancelled()) {
} else {
echo $OUTPUT->header();
if ($issuer) {
echo $OUTPUT->heading(get_string('editissuer', 'tool_oauth2', $issuer->get('name')));
echo $OUTPUT->heading(get_string('editissuer', 'tool_oauth2', s($issuer->get('name'))));
} else {
echo $OUTPUT->heading(get_string('createnewissuer', 'tool_oauth2'));
}
@ -91,30 +91,30 @@ if ($mform && $mform->is_cancelled()) {
} else if ($action == 'delete') {
if (!optional_param('confirm', false, PARAM_BOOL)) {
$continueparams = ['action' => 'delete', 'id' => $idpid, 'sesskey' => sesskey(), 'confirm' => true];
$continueparams = ['action' => 'delete', 'id' => $issuerid, 'sesskey' => sesskey(), 'confirm' => true];
$continueurl = new moodle_url('/admin/tool/oauth2/issuers.php', $continueparams);
$cancelurl = new moodle_url('/admin/tool/oauth2/issuers.php');
echo $OUTPUT->header();
echo $OUTPUT->confirm(get_string('deleteconfirm', 'tool_oauth2', $issuer->get('name')), $continueurl, $cancelurl);
echo $OUTPUT->confirm(get_string('deleteconfirm', 'tool_oauth2', s($issuer->get('name'))), $continueurl, $cancelurl);
echo $OUTPUT->footer();
} else {
require_sesskey();
core\oauth2\api::delete_issuer($idpid);
core\oauth2\api::delete_issuer($issuerid);
redirect($PAGE->url, get_string('issuerdeleted', 'tool_oauth2'), null, \core\output\notification::NOTIFY_SUCCESS);
}
} else if ($action == 'auth') {
if (!optional_param('confirm', false, PARAM_BOOL)) {
$continueparams = ['action' => 'auth', 'id' => $idpid, 'sesskey' => sesskey(), 'confirm' => true];
$continueparams = ['action' => 'auth', 'id' => $issuerid, 'sesskey' => sesskey(), 'confirm' => true];
$continueurl = new moodle_url('/admin/tool/oauth2/issuers.php', $continueparams);
$cancelurl = new moodle_url('/admin/tool/oauth2/issuers.php');
echo $OUTPUT->header();
echo $OUTPUT->confirm(get_string('authconfirm', 'tool_oauth2', $issuer->get('name')), $continueurl, $cancelurl);
echo $OUTPUT->confirm(get_string('authconfirm', 'tool_oauth2', s($issuer->get('name'))), $continueurl, $cancelurl);
echo $OUTPUT->footer();
} else {
require_sesskey();
$params = ['sesskey' => sesskey(), 'id' => $idpid, 'action' => 'auth', 'confirm' => true, 'response' => true];
$params = ['sesskey' => sesskey(), 'id' => $issuerid, 'action' => 'auth', 'confirm' => true, 'response' => true];
if (core\oauth2\api::connect_system_account($issuer, new moodle_url('/admin/tool/oauth2/issuers.php', $params))) {
redirect($PAGE->url, get_string('authconnected', 'tool_oauth2'), null, \core\output\notification::NOTIFY_SUCCESS);
} else {
@ -123,12 +123,12 @@ if ($mform && $mform->is_cancelled()) {
}
} else if ($action == 'moveup') {
require_sesskey();
core\oauth2\api::move_up_issuer($idpid);
core\oauth2\api::move_up_issuer($issuerid);
redirect($PAGE->url);
} else if ($action == 'movedown') {
require_sesskey();
core\oauth2\api::move_down_issuer($idpid);
core\oauth2\api::move_down_issuer($issuerid);
redirect($PAGE->url);
} else {

View File

@ -22,8 +22,17 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['pluginname'] = 'Open ID Connect configuration';
$string['pluginname'] = 'OAuth 2 Services';
$string['editissuer'] = 'Edit identity issuer: {$a}';
$string['editendpoint'] = 'Edit endpoint: {$a->endpoint} for issuer {$a->issuer}';
$string['endpointsforissuer'] = 'Endpoints for issuer: {$a}';
$string['edituserfieldmapping'] = 'Edit user field mapping for issuer {$a}';
$string['userfieldmappingsforissuer'] = 'User field mappings for issuer: {$a}';
$string['issuers'] = 'Issuers';
$string['endpointname'] = 'Name';
$string['endpointname_help'] = 'Key used to search for this endpoint. Must end with "_endpoint".';
$string['endpointurl'] = 'Url';
$string['endpointurl_help'] = 'URL for this endpoint. Must use https:// protocol.';
$string['issuername'] = 'Name';
$string['issuername_help'] = 'Name of the identity issuer. May be displayed on login page.';
$string['issuerimage'] = 'Logo URL';
@ -47,6 +56,8 @@ $string['configuredstatus'] = 'Configured';
$string['discoverystatus'] = 'Discovery';
$string['systemauthstatus'] = 'System account connected';
$string['configured'] = 'Configured';
$string['editendpoints'] = 'Configure endpoints';
$string['edituserfieldmappings'] = 'Configure user field mappings';
$string['notconfigured'] = 'Not configured';
$string['discovered'] = 'Service discovery successful';
$string['notdiscovered'] = 'Service discovery not successful';
@ -55,9 +66,19 @@ $string['notloginissuer'] = 'Do not allow login';
$string['systemaccountconnected'] = 'System account connected';
$string['systemaccountnotconnected'] = 'System account not connected';
$string['createnewissuer'] = 'Create new identity issuer';
$string['createnewendpoint'] = 'Create new endpoint for issuer "{$a}"';
$string['createnewuserfieldmapping'] = 'Create new user field mapping for issuer "{$a}"';
$string['deleteconfirm'] = 'Are you sure you want to delete the identity issuer "{$a}"? Any plugins relying on this issuer will stop working.';
$string['deleteendpointconfirm'] = 'Are you sure you want to delete the endpoint "{$a->endpoint}" for issuer "{$a->issuer}"? Any plugins relying on this endpoint will stop working.';
$string['deleteuserfieldmappingconfirm'] = 'Are you sure you want to delete the user field mapping for issuer "{$a}"?';
$string['issuerdeleted'] = 'Identity issuer deleted';
$string['endpointdeleted'] = 'Endpoint deleted';
$string['userfieldmappingdeleted'] = 'User field mapping deleted';
$string['connectsystemaccount'] = 'Connect to a system account';
$string['authconfirm'] = 'This action will grant permanent API access to Moodle for the authenticated account. This is intended to be used as a system account for managing files owned by Moodle.';
$string['authconnected'] = 'The system account is now connected for offline access';
$string['authnotconnected'] = 'The system account was not connected for offline access';
$string['userfieldexternalfield'] = 'External field name';
$string['userfieldexternalfield_help'] = 'Name of the field provided by the external OAuth system.';
$string['userfieldinternalfield'] = 'Internal field name';
$string['userfieldinternalfield_help'] = 'Name of the Moodle user field that should be mapped from the external field.';

View File

@ -0,0 +1,126 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* OAuth 2 Endpoing Configuration page.
*
* @package tool_oauth2
* @copyright 2017 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
$PAGE->set_url('/admin/tool/oauth2/userfieldmappings.php', ['issuerid' => required_param('issuerid', PARAM_INT)]);
$PAGE->set_context(context_system::instance());
$PAGE->set_pagelayout('admin');
$strheading = get_string('pluginname', 'tool_oauth2');
$PAGE->set_title($strheading);
$PAGE->set_heading($strheading);
require_login();
require_capability('moodle/site:config', context_system::instance());
$renderer = $PAGE->get_renderer('tool_oauth2');
$action = optional_param('action', '', PARAM_ALPHAEXT);
$issuerid = required_param('issuerid', PARAM_INT);
$userfieldmappingid = optional_param('userfieldmappingid', '', PARAM_INT);
$userfieldmapping = null;
$mform = null;
$issuer = \core\oauth2\api::get_issuer($issuerid);
if (!$issuer) {
print_error('invaliddata');
}
$PAGE->navbar->override_active_url(new moodle_url('/admin/tool/oauth2/issuers.php'), true);
if (!empty($userfieldmappingid)) {
$userfieldmapping = \core\oauth2\api::get_user_field_mapping($userfieldmappingid);
}
if ($action == 'edit') {
if ($userfieldmapping) {
$PAGE->navbar->add(get_string('edituserfieldmapping', 'tool_oauth2', s($issuer->get('name'))));
} else {
$PAGE->navbar->add(get_string('createnewuserfieldmapping', 'tool_oauth2', s($issuer->get('name'))));
}
$mform = new \tool_oauth2\form\user_field_mapping(null, ['persistent' => $userfieldmapping, 'issuerid' => $issuerid]);
}
if ($mform && $mform->is_cancelled()) {
redirect(new moodle_url('/admin/tool/oauth2/userfieldmappings.php', ['issuerid' => $issuerid]));
} else if ($action == 'edit') {
if ($data = $mform->get_data()) {
try {
if (!empty($data->id)) {
core\oauth2\api::update_user_field_mapping($data);
} else {
core\oauth2\api::create_user_field_mapping($data);
}
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
} catch (Exception $e) {
redirect($PAGE->url, $e->getMessage(), null, \core\output\notification::NOTIFY_ERROR);
}
} else {
echo $OUTPUT->header();
if ($issuer) {
echo $OUTPUT->heading(get_string('edituserfieldmapping', 'tool_oauth2', s($issuer->get('name'))));
} else {
echo $OUTPUT->heading(get_string('createnewuserfieldmapping', 'tool_oauth2', s($issuer->get('name'))));
}
$mform->display();
echo $OUTPUT->footer();
}
} else if ($action == 'delete') {
if (!optional_param('confirm', false, PARAM_BOOL)) {
$continueparams = [
'action' => 'delete',
'issuerid' => $issuerid,
'userfieldmappingid' => $userfieldmappingid,
'sesskey' => sesskey(),
'confirm' => true
];
$continueurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', $continueparams);
$cancelurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php');
echo $OUTPUT->header();
$str = get_string('deleteuserfieldmappingconfirm', 'tool_oauth2', s($issuer->get('name')));
echo $OUTPUT->confirm($str, $continueurl, $cancelurl);
echo $OUTPUT->footer();
} else {
require_sesskey();
core\oauth2\api::delete_user_field_mapping($userfieldmappingid);
redirect($PAGE->url, get_string('userfieldmappingdeleted', 'tool_oauth2'), null, \core\output\notification::NOTIFY_SUCCESS);
}
} else {
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('userfieldmappingsforissuer', 'tool_oauth2', s($issuer->get('name'))));
$userfieldmappings = core\oauth2\api::get_user_field_mappings($issuer);
echo $renderer->user_field_mappings_table($userfieldmappings, $issuerid);
$addurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', ['action' => 'edit', 'issuerid' => $issuerid]);
echo $renderer->single_button($addurl, get_string('createnewuserfieldmapping', 'tool_oauth2', s($issuer->get('name'))));
echo $OUTPUT->footer();
}

View File

@ -318,6 +318,11 @@ class auth extends \auth_plugin_base {
$SESSION->loginerrormsg = $errormsg;
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
}
if (empty($userinfo['username'])) {
$errormsg = get_string('notloggedin', 'auth_oauth2');
$SESSION->loginerrormsg = $errormsg;
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
}
$userinfo['username'] = trim(core_text::strtolower($userinfo['username']));

View File

@ -68,6 +68,7 @@ class api {
$endpoint = new endpoint(0, $record);
$endpoint->create();
// Microsoft is a custom setup.
$record = (object) [
'name' => 'Microsoft',
'image' => 'https://www.microsoft.com/favicon.ico',
@ -81,29 +82,43 @@ class api {
$issuer = new issuer(0, $record);
$issuer->create();
$record = (object) [
'issuerid' => $issuer->get('id'),
'name' => 'authorization_endpoint',
'url' => 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize'
$endpoints = [
'authorization_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
'token_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
'userinfo_endpoint' => 'https://graph.microsoft.com/v1.0/me/',
'userpicture_endpoint' => 'https://graph.microsoft.com/v1.0/me/photo/$value',
];
$endpoint = new endpoint(0, $record);
$endpoint->create();
$record = (object) [
'issuerid' => $issuer->get('id'),
'name' => 'token_endpoint',
'url' => 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
];
$endpoint = new endpoint(0, $record);
$endpoint->create();
foreach ($endpoints as $name => $url) {
$record = (object) [
'issuerid' => $issuer->get('id'),
'name' => $name,
'url' => $url
];
$endpoint = new endpoint(0, $record);
$endpoint->create();
}
$record = (object) [
'issuerid' => $issuer->get('id'),
'name' => 'end_session_endpoint',
'url' => 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
// Create the field mappings.
$mapping = [
'givenName' => 'firstname',
'surname' => 'lastname',
'mail' => 'email',
'userPrincipalName' => 'username',
'displayName' => 'alternatename',
'officeLocation' => 'address',
'mobilePhone' => 'phone',
'preferredLanguage' => 'lang'
];
$endpoint = new endpoint(0, $record);
$endpoint->create();
foreach ($mapping as $external => $internal) {
$record = (object) [
'issuerid' => $issuer->get('id'),
'externalfield' => $external,
'internalfield' => $internal
];
$userfieldmapping = new user_field_mapping(0, $record);
$userfieldmapping->create();
}
return issuer::count_records();
}
@ -115,6 +130,14 @@ class api {
return new issuer($id);
}
public static function get_endpoint($id) {
return new endpoint($id);
}
public static function get_user_field_mapping($id) {
return new user_field_mapping($id);
}
public static function get_system_account(issuer $issuer) {
return system_account::get_record(['issuerid' => $issuer->get('id')]);
}
@ -132,11 +155,13 @@ class api {
}
public static function get_endpoints(issuer $issuer) {
require_capability('moodle/site:config', context_system::instance());
return endpoint::get_records(['issuerid' => $issuer->get('id')]);
}
public static function get_user_field_mappings(issuer $issuer) {
return user_field_mapping::get_records(['issuerid' => $issuer->get('id')]);
}
protected static function guess_image($issuer) {
if (empty($issuer->get('image'))) {
$baseurl = parse_url($issuer->get('discoveryurl'));
@ -202,6 +227,32 @@ class api {
}
}
// We got to here - must be a decent OpenID connect service. Add the default user field mapping list.
// Create the field mappings.
$mapping = [
'given_name' => 'firstname',
'middle_name' => 'middlename',
'family_name' => 'lastname',
'email' => 'email',
'sub' => 'username',
'website' => 'url',
'nickname' => 'alternatename',
'picture' => 'picture',
'address' => 'address',
'phone' => 'phone',
'locale' => 'lang'
];
foreach ($mapping as $external => $internal) {
$record = (object) [
'issuerid' => $issuer->get('id'),
'externalfield' => $external,
'internalfield' => $internal
];
$userfieldmapping = new user_field_mapping(0, $record);
$userfieldmapping->create();
}
return endpoint::count_records(['issuerid' => $issuer->get('id')]);
}
@ -215,6 +266,7 @@ class api {
// Perform service discovery.
self::discover_endpoints($issuer);
self::guess_image($issuer);
return $issuer;
}
public static function create_issuer($data) {
@ -227,6 +279,45 @@ class api {
// Perform service discovery.
self::discover_endpoints($issuer);
self::guess_image($issuer);
return $issuer;
}
public static function update_endpoint($data) {
require_capability('moodle/site:config', context_system::instance());
$endpoint = new endpoint(0, $data);
// Will throw exceptions on validation failures.
$endpoint->update();
return $endpoint;
}
public static function create_endpoint($data) {
require_capability('moodle/site:config', context_system::instance());
$endpoint = new endpoint(0, $data);
// Will throw exceptions on validation failures.
$endpoint->create();
return $endpoint;
}
public static function update_user_field_mapping($data) {
require_capability('moodle/site:config', context_system::instance());
$userfieldmapping = new user_field_mapping(0, $data);
// Will throw exceptions on validation failures.
$userfieldmapping->update();
return $userfieldmapping;
}
public static function create_user_field_mapping($data) {
require_capability('moodle/site:config', context_system::instance());
$userfieldmapping = new user_field_mapping(0, $data);
// Will throw exceptions on validation failures.
$userfieldmapping->create();
return $userfieldmapping;
}
/**
@ -307,7 +398,23 @@ class api {
}
// Will throw exceptions on validation failures.
$issuer->delete();
return $issuer->delete();
}
public static function delete_endpoint($id) {
require_capability('moodle/site:config', context_system::instance());
$endpoint = new endpoint($id);
// Will throw exceptions on validation failures.
return $endpoint->delete();
}
public static function delete_user_field_mapping($id) {
require_capability('moodle/site:config', context_system::instance());
$userfieldmapping = new user_field_mapping($id);
// Will throw exceptions on validation failures.
return $userfieldmapping->delete();
}
public static function connect_system_account($issuer, $returnurl) {
@ -324,6 +431,10 @@ class api {
$client->log_out();
}
if (optional_param('error', '', PARAM_RAW)) {
return false;
}
if (!$client->is_logged_in()) {
redirect($client->get_login_url());
}

View File

@ -30,6 +30,7 @@ require_once($CFG->libdir . '/filelib.php');
use moodle_url;
use curl;
use stdClass;
/**
* Configurable oauth2 client class where the urls come from DB.
@ -83,35 +84,98 @@ abstract class client extends \oauth2_client {
return $this->issuer->get_endpoint_url('authorization');
}
public function get_issuer() {
/**
* Get the oauth2 issuer for this client.
*
* @return \core\oauth2\issuer Issuer
*/
public function get_issuer() {
return $this->issuer;
}
/**
* Override to append additional params to a authentication request.
*
* @return array (name value pairs).
*/
public function get_additional_login_parameters() {
if ($this->issuer->get('behaviour') == issuer::BEHAVIOUR_OPENID_CONNECT) {
return ['access_type' => 'offline', 'prompt' => 'consent'];
}
return [];
}
/**
* Override to change the scopes requested with an authentiction request.
*
* @return string
*/
protected function get_login_scopes() {
return 'openid profile email';
}
/**
* Returns the token url for OAuth 2.0 request
*
* We are overriding the parent function so we get this from the configured endpoint.
*
* @return string the auth url
*/
protected function token_url() {
return $this->issuer->get_endpoint_url('token');
}
/**
* We want a unique key for each issuer / and a different key for system vs user oauth.
*
* @return string The unique key for the session value.
*/
protected function get_tokenname() {
$name = static::class;
$name = 'oauth2-state-' . $this->issuer->get('id');
if ($this->system) {
$name .= '-system';
}
return $name;
}
protected function get_userinfo_mapping() {
$fields = user_field_mapping::get_records(['issuerid' => $this->issuer->get('id')]);
$map = [];
foreach ($fields as $field) {
$map[$field->get('externalfield')] = $field->get('internalfield');
}
return $map;
}
public function get_userinfo() {
$url = $this->get_issuer()->get_endpoint_url('userinfo');
$response = $this->get($url);
if (!$response) {
return false;
}
$userinfo = new stdClass();
try {
$userinfo = json_decode($response);
} catch (Exception $e) {
return false;
}
$map = $this->get_userinfo_mapping();
$user = new stdClass();
foreach ($map as $openidproperty => $moodleproperty) {
if (!empty($userinfo->$openidproperty)) {
$user->$moodleproperty = $userinfo->$openidproperty;
}
}
if (!empty($user->picture)) {
$user->picture = download_file_content($user->picture, null, null, false, 10, 10, true, null, false);
} else {
$pictureurl = $this->issuer->get_endpoint_url('userpicture');
if (!empty($pictureurl)) {
$user->picture = $this->get($pictureurl);
}
}
return (array)$user;
}
}

View File

@ -26,6 +26,7 @@ namespace core\oauth2;
defined('MOODLE_INTERNAL') || die();
use moodle_url;
use stdClass;
/**
* We have to call directly to the graph APIs because the Microsoft Open ID Connect API is
@ -36,19 +37,13 @@ use moodle_url;
*/
class client_microsoft extends client {
public function get_additional_login_parameters() {
return ['prompt' => 'consent'];
}
public function get_login_scopes() {
return 'openid profile email user.read';
if ($this->system) {
return 'openid profile email user.read offline_access';
} else {
return 'openid profile email user.read';
}
}
public function get_userinfo() {
$me = $client->get('https://graph.microsoft.com/v1.0/me/');
var_dump($me);
}
}

View File

@ -37,62 +37,10 @@ use Exception;
*/
class client_openid_connect extends client {
/**
* Returns a mapping of openid properties to moodle properties.
*
* @return array
*/
private function get_mapping() {
return [
'given_name' => 'firstname',
'middle_name' => 'middlename',
'family_name' => 'lastname',
'email' => 'email',
'username' => 'username',
'website' => 'url',
'nickname' => 'alternatename',
'picture' => 'picture',
'address' => 'address',
'phone' => 'phone',
'locale' => 'lang'
];
}
public function get_additional_login_parameters() {
if ($this->system) {
return ['access_type' => 'offline', 'prompt' => 'consent'];
}
return [];
}
public function get_userinfo() {
$url = $this->get_issuer()->get_endpoint_url('userinfo');
$response = $this->get($url);
if (!$response) {
return false;
}
$userinfo = new stdClass();
try {
$userinfo = json_decode($response);
} catch (Exception $e) {
return false;
}
if (!empty($userinfo->preferred_username)) {
$userinfo->username = $userinfo->preferred_username;
} else {
$userinfo->username = $userinfo->sub;
}
$map = $this->get_mapping();
$user = new stdClass();
foreach ($map as $openidproperty => $moodleproperty) {
if (!empty($userinfo->$openidproperty)) {
$user->$moodleproperty = $userinfo->$openidproperty;
}
}
return (array)$user;
}
}

View File

@ -26,6 +26,7 @@ namespace core\oauth2;
defined('MOODLE_INTERNAL') || die();
use core\persistent;
use lang_string;
/**
* Class for loading/storing oauth2 endpoints from the DB
@ -55,4 +56,11 @@ class endpoint extends persistent {
)
);
}
protected function validate_url($value) {
if (strpos($value, 'https://') !== 0) {
return new lang_string('sslonlyaccess', 'error');
}
return true;
}
}

View File

@ -0,0 +1,78 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Class for loading/storing oauth2 endpoints from the DB.
*
* @package core_oauth2
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\oauth2;
defined('MOODLE_INTERNAL') || die();
use core\persistent;
/**
* Class for loading/storing oauth2 user field mappings from the DB
*
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class user_field_mapping extends persistent {
const TABLE = 'oauth2_user_field_mapping';
private static $userfields = [
'firstname',
'middlename',
'lastname',
'email',
'username',
'idnumber',
'url',
'alternatename',
'picture',
'address',
'phone',
'lang'
];
/**
* Return the definition of the properties of this model.
*
* @return array
*/
protected static function define_properties() {
return array(
'issuerid' => array(
'type' => PARAM_INT
),
'externalfield' => array(
'type' => PARAM_ALPHANUMEXT,
),
'internalfield' => array(
'type' => PARAM_ALPHANUMEXT,
'choices' => self::$userfields,
)
);
}
public function get_internalfield_list() {
return array_combine(self::$userfields, self::$userfields);
}
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="lib/db" VERSION="20170221" COMMENT="XMLDB file for core Moodle tables"
<XMLDB PATH="lib/db" VERSION="20170224" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
@ -3513,5 +3513,22 @@
<KEY NAME="issueridkey" TYPE="foreign-unique" FIELDS="issuerid" REFTABLE="oauth2_issuer" REFFIELDS="id"/>
</KEYS>
</TABLE>
<TABLE NAME="oauth2_user_field_mapping" COMMENT="Mapping of oauth user fields to moodle fields.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The time this record was modified"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The time this record was created."/>
<FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The user who modified this record."/>
<FIELD NAME="issuerid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The oauth issuer."/>
<FIELD NAME="externalfield" TYPE="char" LENGTH="64" NOTNULL="true" SEQUENCE="false" COMMENT="The fieldname returned by the userinfo endpoint."/>
<FIELD NAME="internalfield" TYPE="char" LENGTH="64" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the Moodle field this user field maps to."/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="issuerkey" TYPE="foreign" FIELDS="issuerid" REFTABLE="oauth2_issuer" REFFIELDS="id"/>
<KEY NAME="uniqexternal" TYPE="unique" FIELDS="issuerid, externalfield"/>
<KEY NAME="uniqinternal" TYPE="unique" FIELDS="issuerid, internalfield"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>

View File

@ -2699,10 +2699,39 @@ function xmldb_main_upgrade($oldversion) {
if ($oldversion < 2017033100.01) {
\core\oauth2\api::install_default_issuers();
// Define table oauth2_user_field_mapping to be created.
$table = new xmldb_table('oauth2_user_field_mapping');
// Adding fields to table oauth2_user_field_mapping.
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('externalfield', XMLDB_TYPE_CHAR, '64', null, XMLDB_NOTNULL, null, null);
$table->add_field('internalfield', XMLDB_TYPE_CHAR, '64', null, XMLDB_NOTNULL, null, null);
// Adding keys to table oauth2_user_field_mapping.
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
$table->add_key('issuerkey', XMLDB_KEY_FOREIGN, array('issuerid'), 'oauth2_issuer', array('id'));
$table->add_key('uniqexternal', XMLDB_KEY_UNIQUE, array('issuerid', 'externalfield'));
$table->add_key('uniqinternal', XMLDB_KEY_UNIQUE, array('issuerid', 'internalfield'));
// Conditionally launch create table for oauth2_user_field_mapping.
if (!$dbman->table_exists($table)) {
$dbman->create_table($table);
}
// Main savepoint reached.
upgrade_main_savepoint(true, 2017033100.01);
}
if ($oldversion < 2017033100.02) {
\core\oauth2\api::install_default_issuers();
// Main savepoint reached.
upgrade_main_savepoint(true, 2017033100.02);
}
return true;
}

View File

@ -2766,9 +2766,9 @@ class curl {
// All settings of this class should be init here.
$this->resetopt();
//if (!empty($settings['debug'])) {
if (!empty($settings['debug'])) {
$this->debug = true;
//}
}
if (!empty($settings['cookie'])) {
if($settings['cookie'] === true) {
$this->cookie = $CFG->dataroot.'/curl_cookie.txt';

View File

@ -441,6 +441,15 @@ abstract class oauth2_client extends curl {
// We have a token so we are logged in.
if (isset($this->accesstoken->token)) {
// Check that the access token has all the requested scopes.
$scopecheck = ' ' . $this->accesstoken->scope . ' ';
$requiredscopes = explode(' ', $this->scope);
foreach ($requiredscopes as $requiredscope) {
if (strpos($scopecheck, ' ' . $requiredscope . ' ') === false) {
return false;
}
}
return true;
}
@ -533,6 +542,10 @@ abstract class oauth2_client extends curl {
$r = json_decode($response);
if (!empty($r->error)) {
throw new moodle_exception($r->error . ' ' . $r->error_description);
}
if (!isset($r->access_token)) {
return false;
}
@ -548,6 +561,12 @@ abstract class oauth2_client extends curl {
// Expires 10 seconds before actual expiry.
$accesstoken->expires = (time() + ($r->expires_in - 10));
}
if (isset($r->scope)) {
$accesstoken->scope = $r->scope;
} else {
$accesstoken->scope = $this->scope;
}
// Also add the scopes.
$this->store_token($accesstoken);
return true;

View File

@ -178,7 +178,7 @@
<div class="potentialidplist" class="m-t-1">
{{#identityproviders}}
<div class="potentialidp">
<a href="{{url}}" title={{#quote}}{{name}}{{/quote}} class="btn btn-secondary">
<a href="{{url}}" title={{#quote}}{{name}}{{/quote}} class="btn btn-secondary btn-block">
{{#iconurl}}
<img src="{{iconurl}}" alt="" width="24" height="24"/>
{{/iconurl}}

View File

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2017033100.01; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2017033100.02; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.