Merge branch 'MDL-58220-master' of git://github.com/damyon/moodle
This commit is contained in:
@@ -30,6 +30,17 @@
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
|
||||
$error = optional_param('error', '', PARAM_RAW);
|
||||
if ($error) {
|
||||
$message = optional_param('error_description', '', PARAM_RAW);
|
||||
if ($message) {
|
||||
print_error($message);
|
||||
} else {
|
||||
print_error($error);
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
// The authorization code generated by the authorization server.
|
||||
$code = required_param('code', PARAM_RAW);
|
||||
// The state parameter we've given (used in moodle as a redirect url).
|
||||
|
||||
@@ -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 {
|
||||
|
||||
/** @var string $persistentclass */
|
||||
protected static $persistentclass = 'core\\oauth2\\endpoint';
|
||||
|
||||
/** @var array $fieldstoremove */
|
||||
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();
|
||||
|
||||
// Name.
|
||||
$mform->addElement('text', 'name', get_string('endpointname', 'tool_oauth2'));
|
||||
$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'));
|
||||
$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_ALPHA);
|
||||
|
||||
$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'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
<?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 issuer.
|
||||
*
|
||||
* @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 issuer extends persistent {
|
||||
|
||||
/** @var string $persistentclass */
|
||||
protected static $persistentclass = 'core\\oauth2\\issuer';
|
||||
|
||||
/** @var array $fieldstoremove */
|
||||
protected static $fieldstoremove = array('submitbutton', 'action');
|
||||
|
||||
/**
|
||||
* Define the form - called by parent constructor
|
||||
*/
|
||||
public function definition() {
|
||||
global $PAGE, $OUTPUT;
|
||||
|
||||
$mform = $this->_form;
|
||||
$issuer = $this->get_persistent();
|
||||
|
||||
$docslink = optional_param('docslink', '', PARAM_ALPHAEXT);
|
||||
if ($docslink) {
|
||||
$name = s($issuer->get('name'));
|
||||
$mform->addElement('html', $OUTPUT->doc_link($docslink, get_string('issuersetuptype', 'tool_oauth2', $name)));
|
||||
} else {
|
||||
$mform->addElement('html', $OUTPUT->page_doc_link(get_string('issuersetup', 'tool_oauth2')));
|
||||
}
|
||||
|
||||
// Name.
|
||||
$mform->addElement('text', 'name', get_string('issuername', 'tool_oauth2'));
|
||||
$mform->addRule('name', null, 'required', null, 'client');
|
||||
$mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
|
||||
$mform->addHelpButton('name', 'issuername', 'tool_oauth2');
|
||||
|
||||
// Client ID.
|
||||
$mform->addElement('text', 'clientid', get_string('issuerclientid', 'tool_oauth2'));
|
||||
$mform->addRule('clientid', null, 'required', null, 'client');
|
||||
$mform->addRule('clientid', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
|
||||
$mform->addHelpButton('clientid', 'issuerclientid', 'tool_oauth2');
|
||||
|
||||
// Client Secret.
|
||||
$mform->addElement('text', 'clientsecret', get_string('issuerclientsecret', 'tool_oauth2'));
|
||||
$mform->addRule('clientsecret', null, 'required', null, 'client');
|
||||
$mform->addRule('clientsecret', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
|
||||
$mform->addHelpButton('clientsecret', 'issuerclientsecret', 'tool_oauth2');
|
||||
|
||||
// Login scopes.
|
||||
$mform->addElement('text', 'loginscopes', get_string('issuerloginscopes', 'tool_oauth2'));
|
||||
$mform->addRule('loginscopes', null, 'required', null, 'client');
|
||||
$mform->addRule('loginscopes', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
|
||||
$mform->addHelpButton('loginscopes', 'issuerloginscopes', 'tool_oauth2');
|
||||
|
||||
// Login scopes offline.
|
||||
$mform->addElement('text', 'loginscopesoffline', get_string('issuerloginscopesoffline', 'tool_oauth2'));
|
||||
$mform->addRule('loginscopesoffline', null, 'required', null, 'client');
|
||||
$mform->addRule('loginscopesoffline', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
|
||||
$mform->addHelpButton('loginscopesoffline', 'issuerloginscopesoffline', 'tool_oauth2');
|
||||
|
||||
// Login params.
|
||||
$mform->addElement('text', 'loginparams', get_string('issuerloginparams', 'tool_oauth2'));
|
||||
$mform->addRule('loginparams', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
|
||||
$mform->addHelpButton('loginparams', 'issuerloginparams', 'tool_oauth2');
|
||||
|
||||
// Login params offline.
|
||||
$mform->addElement('text', 'loginparamsoffline', get_string('issuerloginparamsoffline', 'tool_oauth2'));
|
||||
$mform->addRule('loginparamsoffline', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
|
||||
$mform->addHelpButton('loginparamsoffline', 'issuerloginparamsoffline', 'tool_oauth2');
|
||||
|
||||
// Base Url.
|
||||
$mform->addElement('text', 'baseurl', get_string('issuerbaseurl', 'tool_oauth2'));
|
||||
$mform->addRule('baseurl', get_string('maximumchars', '', 1024), 'maxlength', 1024, 'client');
|
||||
$mform->addHelpButton('baseurl', 'issuerbaseurl', 'tool_oauth2');
|
||||
|
||||
// Allowed Domains.
|
||||
$mform->addElement('text', 'alloweddomains', get_string('issueralloweddomains', 'tool_oauth2'));
|
||||
$mform->addRule('alloweddomains', get_string('maximumchars', '', 1024), 'maxlength', 1024, 'client');
|
||||
$mform->addHelpButton('alloweddomains', 'issueralloweddomains', 'tool_oauth2');
|
||||
|
||||
// Image.
|
||||
$mform->addElement('text', 'image', get_string('issuerimage', 'tool_oauth2'), 'maxlength="1024"');
|
||||
$mform->addRule('image', get_string('maximumchars', '', 1024), 'maxlength', 1024, 'client');
|
||||
$mform->addHelpButton('image', 'issuername', 'tool_oauth2');
|
||||
|
||||
// Show on login page.
|
||||
$mform->addElement('checkbox', 'showonloginpage', get_string('issuershowonloginpage', 'tool_oauth2'));
|
||||
$mform->addHelpButton('showonloginpage', 'issuershowonloginpage', 'tool_oauth2');
|
||||
|
||||
$mform->addElement('hidden', 'sortorder');
|
||||
$mform->setType('sortorder', PARAM_INT);
|
||||
|
||||
$mform->addElement('hidden', 'action', 'edit');
|
||||
$mform->setType('action', PARAM_ALPHA);
|
||||
|
||||
$mform->addElement('hidden', 'enabled', $issuer->get('enabled'));
|
||||
$mform->setType('enabled', PARAM_BOOL);
|
||||
|
||||
$mform->addElement('hidden', 'id', $issuer->get('id'));
|
||||
$mform->setType('id', PARAM_INT);
|
||||
|
||||
$this->add_action_buttons(true, get_string('savechanges', 'tool_oauth2'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
/** @var string $persistentclass */
|
||||
protected static $persistentclass = 'core\\oauth2\\user_field_mapping';
|
||||
|
||||
/** @var array $fieldstoremove */
|
||||
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();
|
||||
|
||||
// External.
|
||||
$mform->addElement('text', 'externalfield', get_string('userfieldexternalfield', 'tool_oauth2'));
|
||||
$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_ALPHA);
|
||||
|
||||
$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'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Output rendering for the plugin.
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_oauth2\output;
|
||||
|
||||
use plugin_renderer_base;
|
||||
use html_table;
|
||||
use html_table_cell;
|
||||
use html_table_row;
|
||||
use html_writer;
|
||||
use core\oauth2\issuer;
|
||||
use core\oauth2\api;
|
||||
use moodle_url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Implements the plugin renderer
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class renderer extends plugin_renderer_base {
|
||||
/**
|
||||
* This function will render one beautiful table with all the issuers.
|
||||
*
|
||||
* @param \core\oauth2\issuer[] $issuers - list of all issuers.
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
public function issuers_table($issuers) {
|
||||
global $CFG;
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = [
|
||||
get_string('name'),
|
||||
get_string('configuredstatus', 'tool_oauth2'),
|
||||
get_string('loginissuer', 'tool_oauth2'),
|
||||
get_string('discoverystatus', 'tool_oauth2') . ' ' . $this->help_icon('discovered', 'tool_oauth2'),
|
||||
get_string('systemauthstatus', 'tool_oauth2') . ' ' . $this->help_icon('systemaccountconnected', 'tool_oauth2'),
|
||||
get_string('edit'),
|
||||
];
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$data = [];
|
||||
|
||||
$index = 0;
|
||||
|
||||
foreach ($issuers as $issuer) {
|
||||
// We need to handle the first and last ones specially.
|
||||
$first = false;
|
||||
if ($index == 0) {
|
||||
$first = true;
|
||||
}
|
||||
$last = false;
|
||||
if ($index == count($issuers) - 1) {
|
||||
$last = true;
|
||||
}
|
||||
|
||||
// Name.
|
||||
$name = $issuer->get('name');
|
||||
$image = $issuer->get('image');
|
||||
if ($image) {
|
||||
$name = '<img width="24" height="24" alt="" src="' . s($image) . '"> ' . s($name);
|
||||
}
|
||||
$namecell = new html_table_cell($name);
|
||||
$namecell->header = true;
|
||||
|
||||
// Configured.
|
||||
if ($issuer->is_configured()) {
|
||||
$configured = $this->pix_icon('yes', get_string('configured', 'tool_oauth2'), 'tool_oauth2');
|
||||
} else {
|
||||
$configured = $this->pix_icon('no', get_string('notconfigured', 'tool_oauth2'), 'tool_oauth2');
|
||||
}
|
||||
$configuredstatuscell = new html_table_cell($configured);
|
||||
|
||||
// Login issuer.
|
||||
if (!empty($issuer->get('showonloginpage'))) {
|
||||
$loginissuer = $this->pix_icon('yes', get_string('loginissuer', 'tool_oauth2'), 'tool_oauth2');
|
||||
} else {
|
||||
$loginissuer = $this->pix_icon('no', get_string('notloginissuer', 'tool_oauth2'), 'tool_oauth2');
|
||||
}
|
||||
$loginissuerstatuscell = new html_table_cell($loginissuer);
|
||||
|
||||
// Discovered.
|
||||
if (!empty($issuer->get('scopessupported'))) {
|
||||
$discovered = $this->pix_icon('yes', get_string('discovered', 'tool_oauth2'), 'tool_oauth2');
|
||||
} else {
|
||||
if (!empty($issuer->get_endpoint_url('discovery'))) {
|
||||
$discovered = $this->pix_icon('no', get_string('notdiscovered', 'tool_oauth2'), 'tool_oauth2');
|
||||
} else {
|
||||
$discovered = '-';
|
||||
}
|
||||
}
|
||||
|
||||
$discoverystatuscell = new html_table_cell($discovered);
|
||||
|
||||
// Connected.
|
||||
if ($issuer->is_system_account_connected()) {
|
||||
$systemaccount = \core\oauth2\api::get_system_account($issuer);
|
||||
$systemauth = s($systemaccount->get('email')) . ' (' . s($systemaccount->get('username')). ') ';
|
||||
$systemauth .= $this->pix_icon('yes', get_string('systemaccountconnected', 'tool_oauth2'), 'tool_oauth2');
|
||||
} else {
|
||||
$systemauth = $this->pix_icon('no', get_string('systemaccountnotconnected', 'tool_oauth2'), 'tool_oauth2');
|
||||
}
|
||||
|
||||
$params = ['id' => $issuer->get('id'), 'action' => 'auth'];
|
||||
$authurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params);
|
||||
$icon = $this->pix_icon('auth', get_string('connectsystemaccount', 'tool_oauth2'), 'tool_oauth2');
|
||||
$authlink = html_writer::link($authurl, $icon);
|
||||
$systemauth .= ' ' . $authlink;
|
||||
|
||||
$systemauthstatuscell = new html_table_cell($systemauth);
|
||||
|
||||
$links = '';
|
||||
// Action links.
|
||||
$editurl = new moodle_url('/admin/tool/oauth2/issuers.php', ['id' => $issuer->get('id'), 'action' => 'edit']);
|
||||
$editlink = html_writer::link($editurl, $this->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, $this->pix_icon('t/viewdetails', $str));
|
||||
$links .= ' ' . $editendpointlink;
|
||||
|
||||
// User field mapping.
|
||||
$params = ['issuerid' => $issuer->get('id')];
|
||||
$edituserfieldmappingsurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', $params);
|
||||
$str = get_string('edituserfieldmappings', 'tool_oauth2');
|
||||
$edituserfieldmappinglink = html_writer::link($edituserfieldmappingsurl, $this->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, $this->pix_icon('t/delete', get_string('delete')));
|
||||
$links .= ' ' . $deletelink;
|
||||
// Enable / Disable.
|
||||
if ($issuer->get('enabled')) {
|
||||
// Disable.
|
||||
$disableparams = ['id' => $issuer->get('id'), 'sesskey' => sesskey(), 'action' => 'disable'];
|
||||
$disableurl = new moodle_url('/admin/tool/oauth2/issuers.php', $disableparams);
|
||||
$disablelink = html_writer::link($disableurl, $this->pix_icon('t/hide', get_string('disable')));
|
||||
$links .= ' ' . $disablelink;
|
||||
} else {
|
||||
// Enable.
|
||||
$enableparams = ['id' => $issuer->get('id'), 'sesskey' => sesskey(), 'action' => 'enable'];
|
||||
$enableurl = new moodle_url('/admin/tool/oauth2/issuers.php', $enableparams);
|
||||
$enablelink = html_writer::link($enableurl, $this->pix_icon('t/show', get_string('enable')));
|
||||
$links .= ' ' . $enablelink;
|
||||
}
|
||||
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, $this->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, $this->pix_icon('t/up', get_string('moveup')));
|
||||
$links .= ' ' . $moveuplink;
|
||||
}
|
||||
|
||||
$editcell = new html_table_cell($links);
|
||||
|
||||
$row = new html_table_row([
|
||||
$namecell,
|
||||
$configuredstatuscell,
|
||||
$loginissuerstatuscell,
|
||||
$discoverystatuscell,
|
||||
$systemauthstatuscell,
|
||||
$editcell,
|
||||
]);
|
||||
|
||||
$data[] = $row;
|
||||
$index++;
|
||||
}
|
||||
$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.
|
||||
* @param int $issuerid
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
public function endpoints_table($endpoints, $issuerid) {
|
||||
global $CFG;
|
||||
|
||||
$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, $this->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, $this->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.
|
||||
* @param int $issuerid
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
public function user_field_mappings_table($userfieldmappings, $issuerid) {
|
||||
global $CFG;
|
||||
|
||||
$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, $this->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, $this->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);
|
||||
}
|
||||
}
|
||||
@@ -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 <[email protected]>
|
||||
* @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();
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<?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 Configuration page.
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese <[email protected]>
|
||||
* @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/issuers.php');
|
||||
$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 = optional_param('id', '', PARAM_RAW);
|
||||
$issuer = null;
|
||||
$mform = null;
|
||||
|
||||
if ($issuerid) {
|
||||
$issuer = \core\oauth2\api::get_issuer($issuerid);
|
||||
if (!$issuer) {
|
||||
print_error('invaliddata');
|
||||
}
|
||||
}
|
||||
|
||||
if ($action == 'edit') {
|
||||
if ($issuer) {
|
||||
$PAGE->navbar->add(get_string('editissuer', 'tool_oauth2', s($issuer->get('name'))));
|
||||
} else {
|
||||
$PAGE->navbar->add(get_string('createnewissuer', 'tool_oauth2'));
|
||||
}
|
||||
|
||||
$mform = new \tool_oauth2\form\issuer(null, ['persistent' => $issuer]);
|
||||
}
|
||||
|
||||
if ($mform && $mform->is_cancelled()) {
|
||||
redirect(new moodle_url('/admin/tool/oauth2/issuers.php'));
|
||||
} else if ($action == 'edit') {
|
||||
|
||||
if ($data = $mform->get_data()) {
|
||||
try {
|
||||
if (!empty($data->id)) {
|
||||
core\oauth2\api::update_issuer($data);
|
||||
} else {
|
||||
core\oauth2\api::create_issuer($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('editissuer', 'tool_oauth2', s($issuer->get('name'))));
|
||||
} else {
|
||||
echo $OUTPUT->heading(get_string('createnewissuer', 'tool_oauth2'));
|
||||
}
|
||||
$mform->display();
|
||||
echo $OUTPUT->footer();
|
||||
}
|
||||
} else if ($action == 'edittemplate') {
|
||||
|
||||
$type = required_param('type', PARAM_ALPHA);
|
||||
$docs = required_param('docslink', PARAM_ALPHAEXT);
|
||||
require_sesskey();
|
||||
$issuer = core\oauth2\api::create_standard_issuer($type);
|
||||
$params = ['action' => 'edit', 'id' => $issuer->get('id'), 'docslink' => $docs];
|
||||
$editurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params);
|
||||
redirect($editurl, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
} else if ($action == 'enable') {
|
||||
|
||||
require_sesskey();
|
||||
core\oauth2\api::enable_issuer($issuerid);
|
||||
redirect($PAGE->url, get_string('issuerenabled', 'tool_oauth2'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
|
||||
} else if ($action == 'disable') {
|
||||
|
||||
require_sesskey();
|
||||
core\oauth2\api::disable_issuer($issuerid);
|
||||
redirect($PAGE->url, get_string('issuerdisabled', 'tool_oauth2'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
|
||||
} else if ($action == 'delete') {
|
||||
|
||||
if (!optional_param('confirm', false, PARAM_BOOL)) {
|
||||
$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', s($issuer->get('name'))), $continueurl, $cancelurl);
|
||||
echo $OUTPUT->footer();
|
||||
} else {
|
||||
require_sesskey();
|
||||
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' => $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', s($issuer->get('name'))), $continueurl, $cancelurl);
|
||||
echo $OUTPUT->footer();
|
||||
} else {
|
||||
require_sesskey();
|
||||
$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 {
|
||||
redirect($PAGE->url, get_string('authnotconnected', 'tool_oauth2'), null, \core\output\notification::NOTIFY_ERROR);
|
||||
}
|
||||
}
|
||||
} else if ($action == 'moveup') {
|
||||
require_sesskey();
|
||||
core\oauth2\api::move_up_issuer($issuerid);
|
||||
redirect($PAGE->url);
|
||||
|
||||
} else if ($action == 'movedown') {
|
||||
require_sesskey();
|
||||
core\oauth2\api::move_down_issuer($issuerid);
|
||||
redirect($PAGE->url);
|
||||
|
||||
} else {
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('pluginname', 'tool_oauth2'));
|
||||
echo $OUTPUT->doc_link('OAuth2_Services', get_string('serviceshelp', 'tool_oauth2'));
|
||||
$issuers = core\oauth2\api::get_all_issuers();
|
||||
echo $renderer->issuers_table($issuers);
|
||||
|
||||
$docs = 'admin/tool/oauth2/issuers/google';
|
||||
$params = ['action' => 'edittemplate', 'type' => 'google', 'sesskey' => sesskey(), 'docslink' => $docs];
|
||||
$addurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params);
|
||||
echo $renderer->single_button($addurl, get_string('createnewgoogleissuer', 'tool_oauth2'));
|
||||
$docs = 'admin/tool/oauth2/issuers/microsoft';
|
||||
$params = ['action' => 'edittemplate', 'type' => 'microsoft', 'sesskey' => sesskey(), 'docslink' => $docs];
|
||||
$addurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params);
|
||||
echo $renderer->single_button($addurl, get_string('createnewmicrosoftissuer', 'tool_oauth2'));
|
||||
$docs = 'admin/tool/oauth2/issuers/facebook';
|
||||
$params = ['action' => 'edittemplate', 'type' => 'microsoft', 'sesskey' => sesskey(), 'docslink' => $docs];
|
||||
$params = ['action' => 'edittemplate', 'type' => 'facebook', 'sesskey' => sesskey(), 'docslink' => $docs];
|
||||
$addurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params);
|
||||
echo $renderer->single_button($addurl, get_string('createnewfacebookissuer', 'tool_oauth2'));
|
||||
$addurl = new moodle_url('/admin/tool/oauth2/issuers.php', ['action' => 'edit']);
|
||||
echo $renderer->single_button($addurl, get_string('createnewissuer', 'tool_oauth2'));
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Strings for component 'tool_oauth2', language 'en'
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$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['configured'] = 'Configured';
|
||||
$string['configuredstatus'] = 'Configured';
|
||||
$string['connectsystemaccount'] = 'Connect to a system account';
|
||||
$string['createfromtemplate'] = 'Create an OAuth 2 service from a template';
|
||||
$string['createfromtemplatedesc'] = 'Choose one of the OAuth 2 service template below to create an OAuth service with a valid configuration for one of the known service types. This will create the OAuth 2 service, with all the correct end points and parameters required for authentication, but you will still need to enter the client ID and secret for the new service before it can be used.';
|
||||
$string['createnewendpoint'] = 'Create new endpoint for issuer "{$a}"';
|
||||
$string['createnewfacebookissuer'] = 'Create new Facebook service';
|
||||
$string['createnewgoogleissuer'] = 'Create new Google service';
|
||||
$string['createnewissuer'] = 'Create new custom service';
|
||||
$string['createnewmicrosoftissuer'] = 'Create new Microsoft service';
|
||||
$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['discovered_help'] = 'Discovery means that the OAuth2 endpoints could be automatically determined from the base url for the OAuth service. Not all services are required to be "discovered", but if they are not, then the endpoints and user mapping information will need to be entered manually.';
|
||||
$string['discovered'] = 'Service discovery successful';
|
||||
$string['discoverystatus'] = 'Discovery';
|
||||
$string['editendpoint'] = 'Edit endpoint: {$a->endpoint} for issuer {$a->issuer}';
|
||||
$string['editendpoints'] = 'Configure endpoints';
|
||||
$string['editissuer'] = 'Edit identity issuer: {$a}';
|
||||
$string['edituserfieldmapping'] = 'Edit user field mapping for issuer {$a}';
|
||||
$string['edituserfieldmappings'] = 'Configure user field mappings';
|
||||
$string['endpointdeleted'] = 'Endpoint deleted';
|
||||
$string['endpointname_help'] = 'Key used to search for this endpoint. Must end with "_endpoint".';
|
||||
$string['endpointname'] = 'Name';
|
||||
$string['endpointsforissuer'] = 'Endpoints for issuer: {$a}';
|
||||
$string['endpointurl_help'] = 'URL for this endpoint. Must use https:// protocol.';
|
||||
$string['endpointurl'] = 'Url';
|
||||
$string['issuersetup'] = 'Detailed instructions on configuring the common OAuth 2 Services';
|
||||
$string['issuersetuptype'] = 'Detailed instructions on setting up the {$a} OAuth 2 provider';
|
||||
$string['issueralloweddomains_help'] = 'If set, this setting is a comma separated list of domains that logins will be restricted to when using this provider.';
|
||||
$string['issueralloweddomains_link'] = 'OAuth_2_login_domains';
|
||||
$string['issueralloweddomains'] = 'Login domains';
|
||||
$string['issuerbaseurl_help'] = 'Base url used to access the service.';
|
||||
$string['issuerbaseurl'] = 'Service base url';
|
||||
$string['issuerclientid'] = 'Client Id';
|
||||
$string['issuerclientid_help'] = 'The OAuth client ID for this issuer.';
|
||||
$string['issuerclientsecret'] = 'Client Secret';
|
||||
$string['issuerclientsecret_help'] = 'The OAuth client secret for this issuer.';
|
||||
$string['issuerdeleted'] = 'Identity issuer deleted';
|
||||
$string['issuerdisabled'] = 'Identity issuer disabled';
|
||||
$string['issuerenabled'] = 'Identity issuer enabled';
|
||||
$string['issuerimage_help'] = 'An image url used to show a logo for this issuer. May be displayed on login page.';
|
||||
$string['issuerimage'] = 'Logo URL';
|
||||
$string['issuerloginparams'] = 'Additional parameters included in a login request.';
|
||||
$string['issuerloginparams_help'] = 'Some systems require additional parameters for a login request in order to read the users basic profile.';
|
||||
$string['issuerloginparamsoffline'] = 'Additional parameters included in a login request for offline access.';
|
||||
$string['issuerloginparamsoffline_help'] = 'Each OAuth system defines a different way to request offline access. E.g. Google requires the additional params: "access_type=offline&prompt=consent" these parameters should be in url query parameter format.';
|
||||
$string['issuerloginscopes_help'] = 'Some systems require additional scopes for a login request in order to read the users basic profile. The standard scopes for an OpenID Connect compliant system are "openid profile email".';
|
||||
$string['issuerloginscopesoffline_help'] = 'Each OAuth system defines a different way to request offline access. E.g. Microsoft requires an additional scope "offline_access"';
|
||||
$string['issuerloginscopesoffline'] = 'Scopes included in a login request for offline access.';
|
||||
$string['issuerloginscopes'] = 'Scopes included in a login request.';
|
||||
$string['issuername_help'] = 'Name of the identity issuer. May be displayed on login page.';
|
||||
$string['issuername'] = 'Name';
|
||||
$string['issuershowonloginpage_help'] = 'If the OpenID Connect Authentication plugin is enabled, this login issuer will be listed on the login page to allow users to login with accounts from this issuer.';
|
||||
$string['issuershowonloginpage'] = 'Show on login page.';
|
||||
$string['issuers'] = 'Issuers';
|
||||
$string['loginissuer'] = 'Allow login';
|
||||
$string['notconfigured'] = 'Not configured';
|
||||
$string['notdiscovered'] = 'Service discovery not successful';
|
||||
$string['notloginissuer'] = 'Do not allow login';
|
||||
$string['pluginname'] = 'OAuth 2 Services';
|
||||
$string['savechanges'] = 'Save changes';
|
||||
$string['serviceshelp'] = 'Service provider setup instructions.';
|
||||
$string['systemaccountconnected_help'] = 'System accounts are used to provide advanced functionality for plugins. They are not required for login functionality only, but other plugins using the OAuth service may offer a reduced set of features if the system account has not been connected. For example repositories cannot support "controlled links" without a system account to perform file operations.';
|
||||
$string['systemaccountconnected'] = 'System account connected';
|
||||
$string['systemaccountnotconnected'] = 'System account not connected';
|
||||
$string['systemauthstatus'] = 'System account connected';
|
||||
$string['userfieldexternalfield'] = 'External field name';
|
||||
$string['userfieldexternalfield_help'] = 'Name of the field provided by the external OAuth system.';
|
||||
$string['userfieldinternalfield_help'] = 'Name of the Moodle user field that should be mapped from the external field.';
|
||||
$string['userfieldinternalfield'] = 'Internal field name';
|
||||
$string['userfieldmappingdeleted'] = 'User field mapping deleted';
|
||||
$string['userfieldmappingsforissuer'] = 'User field mappings for issuer: {$a}';
|
||||
@@ -0,0 +1,3 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M9 16H1c-.5 0-1-.5-1-1V1c0-.5.5-1 1-1h8v2H3c-.6 0-1 .4-1 1v10c0 .6.4 1 1 1h6v2zM5 7.5v1c0 .5.5 1 1 1h4.7l-1.1 1.1c-.4.4-.4 1 0 1.4l.7.7c.4.4 1 .4 1.4 0l4-4c.4-.4.4-1 0-1.4l-4-4c-.4-.4-1-.4-1.4 0l-.7.7c-.4.4-.4 1 0 1.4l1 1H6c-.5.1-1 .6-1 1.1z" fill="#989898"/></svg>
|
||||
|
After Width: | Height: | Size: 569 B |
@@ -0,0 +1,3 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-1.6 -0.5 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M12.8 2.7L10.1 0S8.5 1.5 6.4 4C4.3 1.5 2.7 0 2.7 0L0 2.7S1.9 4 4.6 6.4C3 8.7 1.3 11.6 0 14.9c2.2-2.7 4.4-5 6.4-6.9 2 1.9 4.2 4.2 6.4 6.9-1.3-3.3-3-6.2-4.6-8.6 2.7-2.3 4.6-3.6 4.6-3.6z" fill="#FF403C"/></svg>
|
||||
|
After Width: | Height: | Size: 517 B |
@@ -0,0 +1,3 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-0.1 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M6.4 11.1c-2-2.5-3.7-4-3.7-4L0 9.8C5 13.1 8.1 16 8.1 16s.2-.7.6-1.8c.9-2.7 3.2-8.1 7.1-14.2-4.6 3.7-7.7 8.2-9.4 11.1z" fill="#9C3"/></svg>
|
||||
|
After Width: | Height: | Size: 445 B |
@@ -0,0 +1,30 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Oauth2 system configuration.
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
if ($hassiteconfig) {
|
||||
$ADMIN->add('server', new admin_externalpage('oauth2', new lang_string('pluginname', 'tool_oauth2'),
|
||||
"$CFG->wwwroot/$CFG->admin/tool/oauth2/issuers.php"));
|
||||
}
|
||||
@@ -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 Endpoint Configuration page.
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese <[email protected]>
|
||||
* @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();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Plugin version info
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2016112900; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_oauth2'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -124,7 +124,13 @@ class login implements renderable, templatable {
|
||||
global $CFG;
|
||||
|
||||
$identityproviders = array_map(function($idp) use ($output) {
|
||||
$idp['icon'] = $idp['icon']->export_for_template($output);
|
||||
|
||||
if (!empty($idp['icon'])) {
|
||||
$idp['iconurl'] = $output->pix_url($idp['icon']->key, $idp['icon']->component);
|
||||
} else if ($idp['iconurl'] instanceof moodle_url) {
|
||||
$idp['iconurl'] = $idp['iconurl']->out(false);
|
||||
}
|
||||
unset($idp['icon']);
|
||||
if ($idp['url'] instanceof moodle_url) {
|
||||
$idp['url'] = $idp['url']->out(false);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Open ID authentication.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir.'/authlib.php');
|
||||
|
||||
/**
|
||||
* Plugin for oauth2 authentication.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
class auth_plugin_oauth2 extends \auth_oauth2\auth {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
<?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 linked logins from the DB.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace auth_oauth2;
|
||||
|
||||
use context_user;
|
||||
use stdClass;
|
||||
use moodle_exception;
|
||||
use moodle_url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Static list of api methods for auth oauth2 configuration.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class api {
|
||||
|
||||
/**
|
||||
* List linked logins
|
||||
*
|
||||
* Requires auth/oauth2:managelinkedlogins capability at the user context.
|
||||
*
|
||||
* @param int $userid (defaults to $USER->id)
|
||||
* @return boolean
|
||||
*/
|
||||
public static function get_linked_logins($userid = false) {
|
||||
global $USER;
|
||||
|
||||
if ($userid === false) {
|
||||
$userid = $USER->id;
|
||||
}
|
||||
|
||||
if (\core\session\manager::is_loggedinas()) {
|
||||
throw new moodle_exception('notwhileloggedinas', 'auth_oauth2');
|
||||
}
|
||||
|
||||
$context = context_user::instance($userid);
|
||||
require_capability('auth/oauth2:managelinkedlogins', $context);
|
||||
|
||||
return linked_login::get_records(['userid' => $userid, 'confirmtoken' => '']);
|
||||
}
|
||||
|
||||
/**
|
||||
* See if there is a match for this username and issuer in the linked_login table.
|
||||
*
|
||||
* @param string $username as returned from an oauth client.
|
||||
* @param \core\oauth2\issuer $issuer
|
||||
* @return stdClass User record if found.
|
||||
*/
|
||||
public static function match_username_to_user($username, $issuer) {
|
||||
$params = [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'username' => $username
|
||||
];
|
||||
$result = linked_login::get_record($params);
|
||||
|
||||
if ($result) {
|
||||
$user = \core_user::get_user($result->get('userid'));
|
||||
if (!empty($user) && !$user->deleted) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a login to this account.
|
||||
*
|
||||
* Requires auth/oauth2:managelinkedlogins capability at the user context.
|
||||
*
|
||||
* @param array $userinfo as returned from an oauth client.
|
||||
* @param \core\oauth2\issuer $issuer
|
||||
* @param int $userid (defaults to $USER->id)
|
||||
* @param bool $skippermissions During signup we need to set this before the user is setup for capability checks.
|
||||
* @return bool
|
||||
*/
|
||||
public static function link_login($userinfo, $issuer, $userid = false, $skippermissions = false) {
|
||||
global $USER;
|
||||
|
||||
if ($userid === false) {
|
||||
$userid = $USER->id;
|
||||
}
|
||||
|
||||
if (\core\session\manager::is_loggedinas()) {
|
||||
throw new moodle_exception('notwhileloggedinas', 'auth_oauth2');
|
||||
}
|
||||
|
||||
$context = context_user::instance($userid);
|
||||
if (!$skippermissions) {
|
||||
require_capability('auth/oauth2:managelinkedlogins', $context);
|
||||
}
|
||||
|
||||
$record = new stdClass();
|
||||
$record->issuerid = $issuer->get('id');
|
||||
$record->username = $userinfo['username'];
|
||||
$record->userid = $userid;
|
||||
$existing = linked_login::get_record((array)$record);
|
||||
if ($existing) {
|
||||
$existing->set('confirmtoken', '');
|
||||
$existing->update();
|
||||
return $existing;
|
||||
}
|
||||
$record->email = $userinfo['email'];
|
||||
$record->confirmtoken = '';
|
||||
$linkedlogin = new linked_login(0, $record);
|
||||
return $linkedlogin->create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email with a link to confirm linking this account.
|
||||
*
|
||||
* @param array $userinfo as returned from an oauth client.
|
||||
* @param \core\oauth2\issuer $issuer
|
||||
* @param int $userid (defaults to $USER->id)
|
||||
* @return bool
|
||||
*/
|
||||
public static function send_confirm_link_login_email($userinfo, $issuer, $userid) {
|
||||
$record = new stdClass();
|
||||
$record->issuerid = $issuer->get('id');
|
||||
$record->username = $userinfo['username'];
|
||||
$record->userid = $userid;
|
||||
$existing = linked_login::get_record((array)$record);
|
||||
if ($existing) {
|
||||
return false;
|
||||
}
|
||||
$record->email = $userinfo['email'];
|
||||
$record->confirmtoken = random_string(32);
|
||||
$expires = new \DateTime('NOW');
|
||||
$expires->add(new \DateInterval('PT30M'));
|
||||
$record->confirmtokenexpires = $expires->getTimestamp();
|
||||
|
||||
$linkedlogin = new linked_login(0, $record);
|
||||
$linkedlogin->create();
|
||||
|
||||
// Construct the email.
|
||||
$site = get_site();
|
||||
$supportuser = \core_user::get_support_user();
|
||||
$user = get_complete_user_data('id', $userid);
|
||||
|
||||
$data = new stdClass();
|
||||
$data->fullname = fullname($user);
|
||||
$data->sitename = format_string($site->fullname);
|
||||
$data->admin = generate_email_signoff();
|
||||
$data->issuername = format_string($issuer->get('name'));
|
||||
$data->linkedemail = format_string($linkedlogin->get('email'));
|
||||
|
||||
$subject = get_string('confirmlinkedloginemailsubject', 'auth_oauth2', format_string($site->fullname));
|
||||
|
||||
$params = [
|
||||
'token' => $linkedlogin->get('confirmtoken'),
|
||||
'userid' => $userid,
|
||||
'username' => $userinfo['username'],
|
||||
'issuerid' => $issuer->get('id'),
|
||||
];
|
||||
$confirmationurl = new moodle_url('/auth/oauth2/confirm-linkedlogin.php', $params);
|
||||
|
||||
// Remove data parameter just in case it was included in the confirmation so we can add it manually later.
|
||||
$data->link = $confirmationurl->out();
|
||||
|
||||
$message = get_string('confirmlinkedloginemail', 'auth_oauth2', $data);
|
||||
$messagehtml = text_to_html(get_string('confirmlinkedloginemail', 'auth_oauth2', $data), false, false, true);
|
||||
|
||||
$user->mailformat = 1; // Always send HTML version as well.
|
||||
|
||||
// Directly email rather than using the messaging system to ensure its not routed to a popup or jabber.
|
||||
return email_to_user($user, $supportuser, $subject, $message, $messagehtml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a waiting confirmation token, and if we find a match - confirm it.
|
||||
*
|
||||
* @param int $userid
|
||||
* @param string $username
|
||||
* @param int $issuerid
|
||||
* @param string $token
|
||||
* @return boolean True if we linked.
|
||||
*/
|
||||
public static function confirm_link_login($userid, $username, $issuerid, $token) {
|
||||
if (empty($token) || empty($userid) || empty($issuerid) || empty($username)) {
|
||||
return false;
|
||||
}
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
'username' => $username,
|
||||
'issuerid' => $issuerid,
|
||||
'confirmtoken' => $token,
|
||||
];
|
||||
|
||||
$login = linked_login::get_record($params);
|
||||
if (empty($login)) {
|
||||
return false;
|
||||
}
|
||||
$expires = $login->get('confirmtokenexpires');
|
||||
if (time() > $expires) {
|
||||
$login->delete();
|
||||
return;
|
||||
}
|
||||
$login->set('confirmtokenexpires', 0);
|
||||
$login->set('confirmtoken', '');
|
||||
$login->update();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email with a link to confirm creating this account.
|
||||
*
|
||||
* @param array $userinfo as returned from an oauth client.
|
||||
* @param \core\oauth2\issuer $issuer
|
||||
* @param int $userid (defaults to $USER->id)
|
||||
* @return bool
|
||||
*/
|
||||
public static function send_confirm_account_email($userinfo, $issuer) {
|
||||
global $CFG, $DB;
|
||||
require_once($CFG->dirroot.'/user/profile/lib.php');
|
||||
require_once($CFG->dirroot.'/user/lib.php');
|
||||
|
||||
$user = new stdClass();
|
||||
$user->username = $userinfo['username'];
|
||||
$user->email = $userinfo['email'];
|
||||
$user->auth = 'oauth2';
|
||||
$user->mnethostid = $CFG->mnet_localhost_id;
|
||||
$user->lastname = isset($userinfo['lastname']) ? $userinfo['lastname'] : '';
|
||||
$user->firstname = isset($userinfo['firstname']) ? $userinfo['firstname'] : '';
|
||||
$user->url = isset($userinfo['url']) ? $userinfo['url'] : '';
|
||||
$user->alternatename = isset($userinfo['alternatename']) ? $userinfo['alternatename'] : '';
|
||||
$user->secret = random_string(15);
|
||||
|
||||
$user->password = '';
|
||||
// This user is not confirmed.
|
||||
$user->confirmed = 0;
|
||||
|
||||
$user->id = user_create_user($user, false, true);
|
||||
|
||||
// The linked account is pre-confirmed.
|
||||
$record = new stdClass();
|
||||
$record->issuerid = $issuer->get('id');
|
||||
$record->username = $userinfo['username'];
|
||||
$record->userid = $user->id;
|
||||
$record->email = $userinfo['email'];
|
||||
$record->confirmtoken = '';
|
||||
$record->confirmtokenexpires = 0;
|
||||
|
||||
$linkedlogin = new linked_login(0, $record);
|
||||
$linkedlogin->create();
|
||||
|
||||
// Construct the email.
|
||||
$site = get_site();
|
||||
$supportuser = \core_user::get_support_user();
|
||||
$user = get_complete_user_data('id', $user->id);
|
||||
|
||||
$data = new stdClass();
|
||||
$data->fullname = fullname($user);
|
||||
$data->sitename = format_string($site->fullname);
|
||||
$data->admin = generate_email_signoff();
|
||||
|
||||
$subject = get_string('confirmaccountemailsubject', 'auth_oauth2', format_string($site->fullname));
|
||||
|
||||
$params = [
|
||||
'token' => $user->secret,
|
||||
'username' => $userinfo['username']
|
||||
];
|
||||
$confirmationurl = new moodle_url('/auth/oauth2/confirm-account.php', $params);
|
||||
|
||||
$data->link = $confirmationurl->out();
|
||||
|
||||
$message = get_string('confirmaccountemail', 'auth_oauth2', $data);
|
||||
$messagehtml = text_to_html(get_string('confirmaccountemail', 'auth_oauth2', $data), false, false, true);
|
||||
|
||||
$user->mailformat = 1; // Always send HTML version as well.
|
||||
|
||||
// Directly email rather than using the messaging system to ensure its not routed to a popup or jabber.
|
||||
email_to_user($user, $supportuser, $subject, $message, $messagehtml);
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete linked login
|
||||
*
|
||||
* Requires auth/oauth2:managelinkedlogins capability at the user context.
|
||||
*
|
||||
* @param int $linkedloginid
|
||||
* @return boolean
|
||||
*/
|
||||
public static function delete_linked_login($linkedloginid) {
|
||||
$login = new linked_login($linkedloginid);
|
||||
$userid = $login->get('userid');
|
||||
|
||||
if (\core\session\manager::is_loggedinas()) {
|
||||
throw new moodle_exception('notwhileloggedinas', 'auth_oauth2');
|
||||
}
|
||||
|
||||
$context = context_user::instance($userid);
|
||||
require_capability('auth/oauth2:managelinkedlogins', $context);
|
||||
|
||||
$login->delete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,487 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Anobody can login with any password.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
namespace auth_oauth2;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use pix_icon;
|
||||
use moodle_url;
|
||||
use core_text;
|
||||
use context_system;
|
||||
use stdClass;
|
||||
use core\oauth2\issuer;
|
||||
use core\oauth2\client;
|
||||
|
||||
require_once($CFG->libdir.'/authlib.php');
|
||||
|
||||
/**
|
||||
* Plugin for oauth2 authentication.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
class auth extends \auth_plugin_base {
|
||||
|
||||
/**
|
||||
* @var stdClass $userinfo The set of user info returned from the oauth handshake
|
||||
*/
|
||||
private static $userinfo;
|
||||
|
||||
/**
|
||||
* @var stdClass $userpicture The url to a picture.
|
||||
*/
|
||||
private static $userpicture;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->authtype = 'oauth2';
|
||||
$this->config = get_config('auth_oauth2');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the username and password work or don't exist and false
|
||||
* if the user exists and the password is wrong.
|
||||
*
|
||||
* @param string $username The username
|
||||
* @param string $password The password
|
||||
* @return bool Authentication success or failure.
|
||||
*/
|
||||
public function user_login($username, $password) {
|
||||
$cached = $this->get_static_user_info();
|
||||
if (empty($cached)) {
|
||||
// This means we were called as part of a normal login flow - without using oauth.
|
||||
return false;
|
||||
}
|
||||
$verifyusername = $cached['username'];
|
||||
if ($verifyusername == $username) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* We don't want to allow users setting an internal password.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function prevent_local_passwords() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this authentication plugin is 'internal'.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_internal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if moodle should automatically update internal user
|
||||
* records with data from external sources using the information
|
||||
* from auth_plugin_base::get_userinfo().
|
||||
*
|
||||
* @return bool true means automatically copy data from ext to user table
|
||||
*/
|
||||
public function is_synchronised_with_external() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this authentication plugin can change the user's
|
||||
* password.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function can_change_password() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL for changing the user's pw, or empty if the default can
|
||||
* be used.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function change_password_url() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if plugin allows resetting of internal password.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function can_reset_password() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if plugin can be manually set.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function can_be_manually_set() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a form for configuring this authentication plugin.
|
||||
*
|
||||
* This function is called from admin/auth.php, and outputs a full page with
|
||||
* a form for configuring this plugin.
|
||||
*
|
||||
* @param stdClass $config
|
||||
* @param string $err
|
||||
* @param array $userfields
|
||||
*/
|
||||
public function config_form($config, $err, $userfields) {
|
||||
include(__DIR__ . "/../config.html");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the userinfo from the oauth handshake. Will only be valid
|
||||
* for the logged in user.
|
||||
* @param string $username
|
||||
*/
|
||||
public function get_userinfo($username) {
|
||||
$cached = $this->get_static_user_info();
|
||||
if (!empty($cached) && $cached['username'] == $username) {
|
||||
return $cached;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do some checks on the identity provider before showing it on the login page.
|
||||
* @param core\oauth2\issuer $issuer
|
||||
* @return boolean
|
||||
*/
|
||||
private function is_ready_for_login_page(\core\oauth2\issuer $issuer) {
|
||||
return $issuer->get('enabled') &&
|
||||
$issuer->is_configured() &&
|
||||
!empty($issuer->get('showonloginpage'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of identity providers to display on the login page.
|
||||
*
|
||||
* @param string|moodle_url $wantsurl The requested URL.
|
||||
* @return array (containing url, iconurl and name).
|
||||
*/
|
||||
public function loginpage_idp_list($wantsurl) {
|
||||
$providers = \core\oauth2\api::get_all_issuers();
|
||||
$result = [];
|
||||
if (empty($wantsurl)) {
|
||||
$wantsurl = '/';
|
||||
}
|
||||
foreach ($providers as $idp) {
|
||||
if ($this->is_ready_for_login_page($idp)) {
|
||||
$params = ['id' => $idp->get('id'), 'wantsurl' => $wantsurl, 'sesskey' => sesskey()];
|
||||
$url = new moodle_url('/auth/oauth2/login.php', $params);
|
||||
$icon = $idp->get('image');
|
||||
$result[] = ['url' => $url, 'iconurl' => $icon, 'name' => $idp->get('name')];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Statically cache the user info from the oauth handshake
|
||||
* @param stdClass $userinfo
|
||||
*/
|
||||
private function set_static_user_info($userinfo) {
|
||||
self::$userinfo = $userinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the static cached user info
|
||||
* @return stdClass
|
||||
*/
|
||||
private function get_static_user_info() {
|
||||
return self::$userinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Statically cache the user picture from the oauth handshake
|
||||
* @param string $userpicture
|
||||
*/
|
||||
private function set_static_user_picture($userpicture) {
|
||||
self::$userpicture = $userpicture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the static cached user picture
|
||||
* @return string
|
||||
*/
|
||||
private function get_static_user_picture() {
|
||||
return self::$userpicture;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this user has no picture - but we got one from oauth - set it.
|
||||
* @param stdClass $user
|
||||
* @return boolean True if the image was updated.
|
||||
*/
|
||||
private function update_picture($user) {
|
||||
global $CFG, $DB, $USER;
|
||||
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
require_once($CFG->libdir . '/gdlib.php');
|
||||
|
||||
$fs = get_file_storage();
|
||||
$userid = $user->id;
|
||||
if (!empty($user->picture)) {
|
||||
return false;
|
||||
}
|
||||
$picture = $this->get_static_user_picture();
|
||||
if (empty($picture)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$context = \context_user::instance($userid, MUST_EXIST);
|
||||
$fs->delete_area_files($context->id, 'user', 'newicon');
|
||||
|
||||
$filerecord = array(
|
||||
'contextid' => $context->id,
|
||||
'component' => 'user',
|
||||
'filearea' => 'newicon',
|
||||
'itemid' => 0,
|
||||
'filepath' => '/',
|
||||
'filename' => 'image'
|
||||
);
|
||||
|
||||
try {
|
||||
$fs->create_file_from_string($filerecord, $picture);
|
||||
} catch (\file_exception $e) {
|
||||
return get_string($e->errorcode, $e->module, $e->a);
|
||||
}
|
||||
|
||||
$iconfile = $fs->get_area_files($context->id, 'user', 'newicon', false, 'itemid', false);
|
||||
|
||||
// There should only be one.
|
||||
$iconfile = reset($iconfile);
|
||||
|
||||
// Something went wrong while creating temp file - remove the uploaded file.
|
||||
if (!$iconfile = $iconfile->copy_content_to_temp()) {
|
||||
$fs->delete_area_files($context->id, 'user', 'newicon');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy file to temporary location and the send it for processing icon.
|
||||
$newpicture = (int) process_new_icon($context, 'user', 'icon', 0, $iconfile);
|
||||
// Delete temporary file.
|
||||
@unlink($iconfile);
|
||||
// Remove uploaded file.
|
||||
$fs->delete_area_files($context->id, 'user', 'newicon');
|
||||
// Set the user's picture.
|
||||
$updateuser = new stdClass();
|
||||
$updateuser->id = $userid;
|
||||
$updateuser->picture = $newpicture;
|
||||
$USER->picture = $newpicture;
|
||||
user_update_user($updateuser);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the new user as registered.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $confirmsecret
|
||||
*/
|
||||
public function user_confirm($username, $confirmsecret) {
|
||||
global $DB;
|
||||
$user = get_complete_user_data('username', $username);
|
||||
|
||||
if (!empty($user)) {
|
||||
if ($user->auth != $this->authtype) {
|
||||
return AUTH_CONFIRM_ERROR;
|
||||
|
||||
} else if ($user->secret == $confirmsecret && $user->confirmed) {
|
||||
return AUTH_CONFIRM_ALREADY;
|
||||
|
||||
} else if ($user->secret == $confirmsecret) { // They have provided the secret key to get in.
|
||||
$DB->set_field("user", "confirmed", 1, array("id" => $user->id));
|
||||
return AUTH_CONFIRM_OK;
|
||||
}
|
||||
} else {
|
||||
return AUTH_CONFIRM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a page showing that a confirm email was sent with instructions.
|
||||
*
|
||||
* @param string $title
|
||||
* @param string $message
|
||||
*/
|
||||
public function print_confirm_required($title, $message) {
|
||||
global $PAGE, $OUTPUT, $CFG;
|
||||
|
||||
$PAGE->navbar->add($title);
|
||||
$PAGE->set_title($title);
|
||||
$PAGE->set_heading($PAGE->course->fullname);
|
||||
echo $OUTPUT->header();
|
||||
notice($message, "$CFG->httpswwwroot/index.php");
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the login process after oauth handshake is complete.
|
||||
* @param \core\oauth2\client $client
|
||||
* @param string $redirecturl
|
||||
* @return none Either redirects or throws an exception
|
||||
*/
|
||||
public function complete_login(client $client, $redirecturl) {
|
||||
global $CFG, $SESSION, $PAGE;
|
||||
|
||||
$userinfo = $client->get_userinfo();
|
||||
|
||||
if (!$userinfo) {
|
||||
$errormsg = get_string('loginerror_nouserinfo', 'auth_oauth2');
|
||||
$SESSION->loginerrormsg = $errormsg;
|
||||
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
|
||||
}
|
||||
if (empty($userinfo['username']) || empty($userinfo['email'])) {
|
||||
$errormsg = get_string('loginerror_userincomplete', 'auth_oauth2');
|
||||
$SESSION->loginerrormsg = $errormsg;
|
||||
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
|
||||
}
|
||||
|
||||
$userinfo['username'] = trim(core_text::strtolower($userinfo['username']));
|
||||
|
||||
// Once we get here we have the user info from oauth.
|
||||
$userwasmapped = false;
|
||||
|
||||
// Clean and remember the picture / lang.
|
||||
if (!empty($userinfo['picture'])) {
|
||||
$this->set_static_user_picture($userinfo['picture']);
|
||||
unset($userinfo['picture']);
|
||||
}
|
||||
|
||||
if (!empty($userinfo['lang'])) {
|
||||
$userinfo['lang'] = str_replace('-', '_', trim(core_text::strtolower($userinfo['lang'])));
|
||||
if (!get_string_manager()->translation_exists($userinfo['lang'], false)) {
|
||||
unset($userinfo['lang']);
|
||||
}
|
||||
}
|
||||
|
||||
// First we try and find a defined mapping.
|
||||
$linkedlogin = api::match_username_to_user($userinfo['username'], $client->get_issuer());
|
||||
|
||||
if (!empty($linkedlogin) && empty($linkedlogin->get('confirmtoken'))) {
|
||||
$mappeduser = get_complete_user_data('id', $linkedlogin->get('userid'));
|
||||
|
||||
if ($mappeduser && $mappeduser->confirmed) {
|
||||
$userinfo = (array) $mappeduser;
|
||||
$userwasmapped = true;
|
||||
} else {
|
||||
$errormsg = get_string('confirmationpending', 'auth_oauth2');
|
||||
$SESSION->loginerrormsg = $errormsg;
|
||||
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
|
||||
}
|
||||
} else if (!empty($linkedlogin)) {
|
||||
$errormsg = get_string('confirmationpending', 'auth_oauth2');
|
||||
$SESSION->loginerrormsg = $errormsg;
|
||||
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
|
||||
}
|
||||
$issuer = $client->get_issuer();
|
||||
if (!$issuer->is_valid_login_domain($userinfo['email'])) {
|
||||
$errormsg = get_string('notloggedindebug', 'auth_oauth2', get_string('loginerror_invaliddomain', 'auth_oauth2'));
|
||||
$SESSION->loginerrormsg = $errormsg;
|
||||
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
|
||||
}
|
||||
|
||||
if (!$userwasmapped) {
|
||||
// No defined mapping - we need to see if there is an existing account with the same email.
|
||||
|
||||
$moodleuser = \core_user::get_user_by_email($userinfo['email']);
|
||||
if (!empty($moodleuser)) {
|
||||
$PAGE->set_url('/auth/oauth2/confirm-link-login.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
\auth_oauth2\api::send_confirm_link_login_email($userinfo, $issuer, $moodleuser->id);
|
||||
// Request to link to existing account.
|
||||
$emailconfirm = get_string('emailconfirmlink', 'auth_oauth2');
|
||||
$message = get_string('emailconfirmlinksent', 'auth_oauth2', $moodleuser->email);
|
||||
$this->print_confirm_required($emailconfirm, $message);
|
||||
exit();
|
||||
|
||||
} else {
|
||||
// This is a new account.
|
||||
$exists = \core_user::get_user_by_username($userinfo['username']);
|
||||
// Creating a new user?
|
||||
if ($exists) {
|
||||
|
||||
// The username exists but the emails don't match. Refuse to continue.
|
||||
$errormsg = get_string('accountexists', 'auth_oauth2');
|
||||
$SESSION->loginerrormsg = $errormsg;
|
||||
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
|
||||
}
|
||||
|
||||
if (email_is_not_allowed($userinfo['email'])) {
|
||||
// The username exists but the emails don't match. Refuse to continue.
|
||||
$reason = get_string('loginerror_invaliddomain', 'auth_oauth2');
|
||||
$errormsg = get_string('notloggedindebug', 'auth_oauth2', $reason);
|
||||
$SESSION->loginerrormsg = $errormsg;
|
||||
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
|
||||
}
|
||||
|
||||
$PAGE->set_url('/auth/oauth2/confirm-account.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
// Create a new (unconfirmed account) and send an email to confirm it.
|
||||
$user = \auth_oauth2\api::send_confirm_account_email($userinfo, $issuer);
|
||||
|
||||
$this->update_picture($user);
|
||||
$emailconfirm = get_string('emailconfirm');
|
||||
$message = get_string('emailconfirmsent', '', $userinfo['email']);
|
||||
$this->print_confirm_required($emailconfirm, $message);
|
||||
exit();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// If we got to here - we must have found a real user account that is confirmed.
|
||||
$this->set_static_user_info($userinfo);
|
||||
$user = authenticate_user_login($userinfo['username'], '');
|
||||
|
||||
if ($user) {
|
||||
complete_user_login($user);
|
||||
$this->update_picture($user);
|
||||
redirect($redirecturl);
|
||||
}
|
||||
$errormsg = get_string('notloggedindebug', 'auth_oauth2', get_string('loginerror_authenticationfailed', 'auth_oauth2'));
|
||||
$SESSION->loginerrormsg = $errormsg;
|
||||
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<?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 issuers from the DB.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace auth_oauth2;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\persistent;
|
||||
|
||||
/**
|
||||
* Class for loading/storing issuer from the DB
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class linked_login extends persistent {
|
||||
|
||||
const TABLE = 'auth_oauth2_linked_login';
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return array(
|
||||
'issuerid' => array(
|
||||
'type' => PARAM_INT
|
||||
),
|
||||
'userid' => array(
|
||||
'type' => PARAM_INT
|
||||
),
|
||||
'username' => array(
|
||||
'type' => PARAM_RAW
|
||||
),
|
||||
'email' => array(
|
||||
'type' => PARAM_RAW
|
||||
),
|
||||
'confirmtoken' => array(
|
||||
'type' => PARAM_RAW
|
||||
),
|
||||
'confirmtokenexpires' => array(
|
||||
'type' => PARAM_INT
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Output rendering for the plugin.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace auth_oauth2\output;
|
||||
|
||||
use plugin_renderer_base;
|
||||
use html_table;
|
||||
use html_table_cell;
|
||||
use html_table_row;
|
||||
use html_writer;
|
||||
use auth\oauth2\linked_login;
|
||||
use moodle_url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Implements the plugin renderer
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class renderer extends plugin_renderer_base {
|
||||
/**
|
||||
* This function will render one beautiful table with all the linked_logins.
|
||||
*
|
||||
* @param \auth\oauth2\linked_login[] $linkedlogins - list of all linked logins.
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
public function linked_logins_table($linkedlogins) {
|
||||
global $CFG;
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = [
|
||||
get_string('issuer', 'auth_oauth2'),
|
||||
get_string('info', 'auth_oauth2'),
|
||||
get_string('edit'),
|
||||
];
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$data = [];
|
||||
|
||||
$index = 0;
|
||||
|
||||
foreach ($linkedlogins as $linkedlogin) {
|
||||
// Issuer.
|
||||
$issuerid = $linkedlogin->get('issuerid');
|
||||
$issuer = \core\oauth2\api::get_issuer($issuerid);
|
||||
$issuercell = new html_table_cell(s($issuer->get('name')));
|
||||
|
||||
// Issuer.
|
||||
$username = $linkedlogin->get('username');
|
||||
$email = $linkedlogin->get('email');
|
||||
$usernamecell = new html_table_cell(s($email) . ', (' . s($username) . ')');
|
||||
|
||||
$links = '';
|
||||
|
||||
// Delete.
|
||||
$deleteparams = ['linkedloginid' => $linkedlogin->get('id'), 'action' => 'delete', 'sesskey' => sesskey()];
|
||||
$deleteurl = new moodle_url('/auth/oauth2/linkedlogins.php', $deleteparams);
|
||||
$deletelink = html_writer::link($deleteurl, $this->pix_icon('t/delete', get_string('delete')));
|
||||
$links .= ' ' . $deletelink;
|
||||
|
||||
$editcell = new html_table_cell($links);
|
||||
|
||||
$row = new html_table_row([
|
||||
$issuercell,
|
||||
$usernamecell,
|
||||
$editcell,
|
||||
]);
|
||||
|
||||
$data[] = $row;
|
||||
$index++;
|
||||
}
|
||||
$table->data = $data;
|
||||
return html_writer::table($table);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<!-- No config needed -->
|
||||
<div style="text-align: center"><?php print_string('plugindescription', 'auth_oauth2'); ?></div>
|
||||
|
||||
<div class="alert alert-warning m-y-2" style="text-align: center"><?php print_string('createaccountswarning', 'auth_oauth2'); ?></div>
|
||||
|
||||
<table cellspacing="0" cellpadding="5" border="0">
|
||||
<?php
|
||||
|
||||
print_auth_lock_options($this->authtype, $userfields, get_string('auth_fieldlocks_help', 'auth'), false, false);
|
||||
|
||||
?>
|
||||
</table>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Confirm self oauth2 user.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require('../../config.php');
|
||||
require_once($CFG->libdir . '/authlib.php');
|
||||
|
||||
$usersecret = required_param('token', PARAM_RAW);
|
||||
$username = required_param('username', PARAM_USERNAME);
|
||||
$redirect = optional_param('redirect', '', PARAM_LOCALURL); // Where to redirect the browser once the user has been confirmed.
|
||||
|
||||
$PAGE->set_url('/auth/oauth2/confirm-account.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
$auth = get_auth_plugin('oauth2');
|
||||
|
||||
$confirmed = $auth->user_confirm($username, $usersecret);
|
||||
|
||||
if ($confirmed == AUTH_CONFIRM_ALREADY) {
|
||||
$user = get_complete_user_data('username', $username);
|
||||
$PAGE->navbar->add(get_string("alreadyconfirmed"));
|
||||
$PAGE->set_title(get_string("alreadyconfirmed"));
|
||||
$PAGE->set_heading($COURSE->fullname);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->box_start('generalbox centerpara boxwidthnormal boxaligncenter');
|
||||
echo "<p>".get_string("alreadyconfirmed")."</p>\n";
|
||||
echo $OUTPUT->single_button("$CFG->wwwroot/course/", get_string('courses'));
|
||||
echo $OUTPUT->box_end();
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
|
||||
} else if ($confirmed == AUTH_CONFIRM_OK) {
|
||||
|
||||
// The user has confirmed successfully, let's log them in.
|
||||
|
||||
if (!$user = get_complete_user_data('username', $username)) {
|
||||
print_error('cannotfinduser', '', '', s($username));
|
||||
}
|
||||
|
||||
if (!$user->suspended) {
|
||||
complete_user_login($user);
|
||||
|
||||
\core\session\manager::apply_concurrent_login_limit($user->id, session_id());
|
||||
|
||||
// Check where to go, $redirect has a higher preference.
|
||||
if (empty($redirect) and !empty($SESSION->wantsurl) ) {
|
||||
$redirect = $SESSION->wantsurl;
|
||||
unset($SESSION->wantsurl);
|
||||
}
|
||||
|
||||
if (!empty($redirect)) {
|
||||
redirect($redirect);
|
||||
}
|
||||
}
|
||||
|
||||
$PAGE->navbar->add(get_string("confirmed"));
|
||||
$PAGE->set_title(get_string("confirmed"));
|
||||
$PAGE->set_heading($COURSE->fullname);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->box_start('generalbox centerpara boxwidthnormal boxaligncenter');
|
||||
echo "<h3>".get_string("thanks").", ". fullname($USER) . "</h3>\n";
|
||||
echo "<p>".get_string("confirmed")."</p>\n";
|
||||
echo $OUTPUT->single_button("$CFG->wwwroot/course/", get_string('courses'));
|
||||
echo $OUTPUT->box_end();
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
} else {
|
||||
print_error('invalidconfirmdata');
|
||||
}
|
||||
|
||||
redirect("$CFG->wwwroot/");
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* Confirm self oauth2 user.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require('../../config.php');
|
||||
require_once($CFG->libdir . '/authlib.php');
|
||||
|
||||
$token = required_param('token', PARAM_RAW);
|
||||
$username = required_param('username', PARAM_USERNAME);
|
||||
$userid = required_param('userid', PARAM_INT);
|
||||
$issuerid = required_param('issuerid', PARAM_INT);
|
||||
$redirect = optional_param('redirect', '', PARAM_LOCALURL); // Where to redirect the browser once the user has been confirmed.
|
||||
|
||||
$PAGE->set_url('/auth/oauth2/confirm-linkedlogin.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
$confirmed = \auth_oauth2\api::confirm_link_login($userid, $username, $issuerid, $token);
|
||||
|
||||
if ($confirmed) {
|
||||
|
||||
// The user has confirmed successfully, let's log them in.
|
||||
|
||||
if (!$user = get_complete_user_data('username', $username)) {
|
||||
print_error('cannotfinduser', '', '', s($username));
|
||||
}
|
||||
|
||||
if (!$user->suspended) {
|
||||
complete_user_login($user);
|
||||
|
||||
\core\session\manager::apply_concurrent_login_limit($user->id, session_id());
|
||||
|
||||
// Check where to go, $redirect has a higher preference.
|
||||
if (empty($redirect) and !empty($SESSION->wantsurl) ) {
|
||||
$redirect = $SESSION->wantsurl;
|
||||
unset($SESSION->wantsurl);
|
||||
}
|
||||
|
||||
if (!empty($redirect)) {
|
||||
redirect($redirect);
|
||||
}
|
||||
}
|
||||
|
||||
$PAGE->navbar->add(get_string("confirmed"));
|
||||
$PAGE->set_title(get_string("confirmed"));
|
||||
$PAGE->set_heading($COURSE->fullname);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->box_start('generalbox centerpara boxwidthnormal boxaligncenter');
|
||||
echo "<h3>".get_string("thanks").", ". fullname($USER) . "</h3>\n";
|
||||
echo "<p>".get_string("confirmed")."</p>\n";
|
||||
echo $OUTPUT->single_button("$CFG->wwwroot/course/", get_string('courses'));
|
||||
echo $OUTPUT->box_end();
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
} else {
|
||||
print_error('invalidconfirmdata');
|
||||
}
|
||||
|
||||
redirect("$CFG->wwwroot/");
|
||||
@@ -0,0 +1,37 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Capability definitions for this plugin.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$capabilities = [
|
||||
|
||||
'auth/oauth2:managelinkedlogins' => array(
|
||||
|
||||
'captype' => 'write',
|
||||
'contextlevel' => CONTEXT_USER,
|
||||
'archetypes' => array(
|
||||
'user' => CAP_ALLOW
|
||||
)
|
||||
),
|
||||
];
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="auth/oauth2/db" VERSION="20170323" COMMENT="XMLDB file for Moodle auth/oauth2"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
<TABLES>
|
||||
<TABLE NAME="auth_oauth2_linked_login" COMMENT="Accounts linked to a users Moodle account.">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
|
||||
<FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
|
||||
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The user account this oauth login is linked to."/>
|
||||
<FIELD NAME="issuerid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
|
||||
<FIELD NAME="username" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The external username to map to this moodle account"/>
|
||||
<FIELD NAME="email" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The external email to map to this moodle account"/>
|
||||
<FIELD NAME="confirmtoken" TYPE="char" LENGTH="64" NOTNULL="true" SEQUENCE="false" COMMENT="If this is not empty - the user has not confirmed their email to create the link."/>
|
||||
<FIELD NAME="confirmtokenexpires" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="usermodified_key" TYPE="foreign" FIELDS="usermodified" REFTABLE="user" REFFIELDS="id"/>
|
||||
<KEY NAME="userid_key" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id"/>
|
||||
<KEY NAME="issuerid_key" TYPE="foreign" FIELDS="issuerid" REFTABLE="oauth2_issuer" REFFIELDS="id"/>
|
||||
<KEY NAME="uniq_key" TYPE="unique" FIELDS="userid, issuerid, username"/>
|
||||
</KEYS>
|
||||
<INDEXES>
|
||||
<INDEX NAME="search_index" UNIQUE="false" FIELDS="issuerid, username"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
</XMLDB>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* OAuth2 authentication plugin upgrade code
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Upgrade function
|
||||
*
|
||||
* @param int $oldversion the version we are upgrading from
|
||||
* @return bool result
|
||||
*/
|
||||
function xmldb_auth_oauth2_upgrade($oldversion) {
|
||||
global $DB;
|
||||
|
||||
$dbman = $DB->get_manager();
|
||||
|
||||
// Automatically generated Moodle v3.2.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Strings for component 'auth_oauth2', language 'en'.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['accountexists'] = 'A user already exists on this site with this username. If this is your account, login manually and link this link from your preferences page.';
|
||||
$string['auth_oauth2description'] = 'OAuth 2 standards based authentication';
|
||||
$string['auth_oauth2settings'] = 'OAuth 2 authentication settings.';
|
||||
$string['confirmaccountemail'] = 'Hi {$a->fullname},
|
||||
|
||||
A new account has been requested at \'{$a->sitename}\'
|
||||
using your email address.
|
||||
|
||||
To confirm your new account, please go to this web address:
|
||||
|
||||
{$a->link}
|
||||
|
||||
In most mail programs, this should appear as a blue link
|
||||
which you can just click on. If that doesn\'t work,
|
||||
then cut and paste the address into the address
|
||||
line at the top of your web browser window.
|
||||
|
||||
If you need help, please contact the site administrator,
|
||||
{$a->admin}';
|
||||
$string['confirmaccountemailsubject'] = '{$a}: account confirmation';
|
||||
$string['confirmationpending'] = 'This account is pending email confirmation.';
|
||||
$string['confirmlinkedloginemail'] = 'Hi {$a->fullname},
|
||||
|
||||
A request has been made to link the {$a->issuername} login
|
||||
{$a->linkedemail} to your account at \'{$a->sitename}\'
|
||||
using your email address.
|
||||
|
||||
To confirm this request and link these logins, please go to this web address:
|
||||
|
||||
{$a->link}
|
||||
|
||||
In most mail programs, this should appear as a blue link
|
||||
which you can just click on. If that doesn\'t work,
|
||||
then cut and paste the address into the address
|
||||
line at the top of your web browser window.
|
||||
|
||||
If you need help, please contact the site administrator,
|
||||
{$a->admin}';
|
||||
$string['confirmlinkedloginemailsubject'] = '{$a}: linked login confirmation';
|
||||
$string['createaccountswarning'] = 'This authentication plugin allows users to create accounts on your site. You may want to enable the setting "authpreventaccountcreation" if you use this plugin.';
|
||||
$string['createnewlinkedlogin'] = 'Link a new account ({$a})';
|
||||
$string['emailconfirmlink'] = 'Link your accounts';
|
||||
$string['emailconfirmlinksent'] = '<p>An existing account was found with this email address but it is not linked yet.</p>
|
||||
<p>The accounts must be linked before you can login.</p>
|
||||
<p>An email should have been sent to your address at <b>{$a}</b></p>
|
||||
<p>It contains easy instructions to link your accounts.</p>
|
||||
<p>If you continue to have difficulty, contact the site administrator.</p>';
|
||||
$string['info'] = 'External account';
|
||||
$string['issuer'] = 'OAuth 2 Service';
|
||||
$string['linkedlogins'] = 'Linked logins';
|
||||
$string['linkedloginshelp'] = 'Help with linked logins.';
|
||||
$string['loginerror_userincomplete'] = 'The user information returned did not contain a username and email address. The OAuth 2 service may be configured incorrectly.';
|
||||
$string['loginerror_nouserinfo'] = 'No user information was returned. The OAuth 2 service may be configured incorrectly.';
|
||||
$string['loginerror_invaliddomain'] = 'The email address is not allowed at this site.';
|
||||
$string['loginerror_authenticationfailed'] = 'The authentication process failed.';
|
||||
$string['notloggedindebug'] = 'The login attempt failed. Reason: {$a}';
|
||||
$string['notwhileloggedinas'] = 'Linked logins cannot be managed while logged in as another user.';
|
||||
$string['oauth2:managelinkedlogins'] = 'Manage own linked login accounts';
|
||||
$string['plugindescription'] = 'This authentication plugin displays a list of the configured identity providers on the moodle login page. Selecting an identity provider allows users to login with their credentials from an OAuth 2 provider.';
|
||||
$string['pluginname'] = 'OAuth 2';
|
||||
@@ -0,0 +1,59 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Callbacks for auth_oauth2
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Navigation hook to add to preferences page.
|
||||
*
|
||||
* @param navigation_node $useraccount
|
||||
* @param stdClass $user
|
||||
* @param context_user $context
|
||||
* @param stdClass $course
|
||||
* @param context_course $coursecontext
|
||||
*/
|
||||
function auth_oauth2_extend_navigation_user_settings(navigation_node $useraccount,
|
||||
stdClass $user,
|
||||
context_user $context,
|
||||
stdClass $course,
|
||||
context_course $coursecontext) {
|
||||
|
||||
if (!\core\session\manager::is_loggedinas()) {
|
||||
if (has_capability('auth/oauth2:managelinkedlogins', $context)) {
|
||||
|
||||
$parent = $useraccount->parent->find('useraccount', navigation_node::TYPE_CONTAINER);
|
||||
$parent->add(get_string('linkedlogins', 'auth_oauth2'), new moodle_url('/auth/oauth2/linkedlogins.php'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to remove linked logins for deleted users.
|
||||
*
|
||||
* @param stdClass $user
|
||||
*/
|
||||
function auth_oauth2_pre_user_delete($user) {
|
||||
global $DB;
|
||||
$DB->delete_records(auth_oauth2\linked_login::TABLE, ['userid' => $user->id]);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?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 Linked login configuration page.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese <[email protected]>
|
||||
* @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('/auth/oauth2/linkedlogins.php');
|
||||
$PAGE->set_context(context_user::instance($USER->id));
|
||||
$PAGE->set_pagelayout('admin');
|
||||
$strheading = get_string('linkedlogins', 'auth_oauth2');
|
||||
$PAGE->set_title($strheading);
|
||||
$PAGE->set_heading($strheading);
|
||||
|
||||
require_login();
|
||||
|
||||
$action = optional_param('action', '', PARAM_ALPHAEXT);
|
||||
if ($action == 'new') {
|
||||
require_sesskey();
|
||||
$issuerid = required_param('issuerid', PARAM_INT);
|
||||
$issuer = \core\oauth2\api::get_issuer($issuerid);
|
||||
|
||||
|
||||
// We do a login dance with this issuer.
|
||||
$addparams = ['action' => 'new', 'issuerid' => $issuerid, 'sesskey' => sesskey()];
|
||||
$addurl = new moodle_url('/auth/oauth2/linkedlogins.php', $addparams);
|
||||
$client = \core\oauth2\api::get_user_oauth_client($issuer, $addurl);
|
||||
|
||||
if (optional_param('logout', false, PARAM_BOOL)) {
|
||||
$client->log_out();
|
||||
}
|
||||
|
||||
if (!$client->is_logged_in()) {
|
||||
redirect($client->get_login_url());
|
||||
}
|
||||
|
||||
$userinfo = $client->get_userinfo();
|
||||
|
||||
if (!empty($userinfo)) {
|
||||
\auth_oauth2\api::link_login($userinfo, $issuer);
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
} else {
|
||||
redirect($PAGE->url, get_string('notloggedin', 'auth_oauth2'), null, \core\output\notification::NOTIFY_ERROR);
|
||||
}
|
||||
} else if ($action == 'delete') {
|
||||
require_sesskey();
|
||||
$linkedloginid = required_param('linkedloginid', PARAM_INT);
|
||||
|
||||
auth_oauth2\api::delete_linked_login($linkedloginid);
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
|
||||
$renderer = $PAGE->get_renderer('auth_oauth2');
|
||||
|
||||
$linkedloginid = optional_param('id', '', PARAM_RAW);
|
||||
$linkedlogin = null;
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('linkedlogins', 'auth_oauth2'));
|
||||
echo $OUTPUT->doc_link('Linked_Logins', get_string('linkedloginshelp', 'auth_oauth2'));
|
||||
$linkedlogins = auth_oauth2\api::get_linked_logins();
|
||||
|
||||
echo $renderer->linked_logins_table($linkedlogins);
|
||||
|
||||
$issuers = \core\oauth2\api::get_all_issuers();
|
||||
|
||||
foreach ($issuers as $issuer) {
|
||||
if (!$issuer->is_authentication_supported()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$addparams = ['action' => 'new', 'issuerid' => $issuer->get('id'), 'sesskey' => sesskey(), 'logout' => true];
|
||||
$addurl = new moodle_url('/auth/oauth2/linkedlogins.php', $addparams);
|
||||
echo $renderer->single_button($addurl, get_string('createnewlinkedlogin', 'auth_oauth2', s($issuer->get('name'))));
|
||||
}
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Open ID authentication. This file is a simple login entry point for OAuth identity providers.
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
require_once('../../config.php');
|
||||
|
||||
$issuerid = required_param('id', PARAM_INT);
|
||||
$wantsurl = new moodle_url(optional_param('wantsurl', '', PARAM_URL));
|
||||
|
||||
require_sesskey();
|
||||
|
||||
$issuer = new \core\oauth2\issuer($issuerid);
|
||||
|
||||
$returnparams = ['wantsurl' => $wantsurl, 'sesskey' => sesskey(), 'id' => $issuerid];
|
||||
$returnurl = new moodle_url('/auth/oauth2/login.php', $returnparams);
|
||||
|
||||
$client = \core\oauth2\api::get_user_oauth_client($issuer, $returnurl);
|
||||
|
||||
if ($client) {
|
||||
if (!$client->is_logged_in()) {
|
||||
redirect($client->get_login_url());
|
||||
}
|
||||
|
||||
$auth = new \auth_oauth2\auth();
|
||||
$auth->complete_login($client, $wantsurl);
|
||||
} else {
|
||||
throw new moodle_exception('Could not get an OAuth client.');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Version information
|
||||
*
|
||||
* @package auth_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017032300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2016112900; // Requires this Moodle version.
|
||||
$plugin->component = 'auth_oauth2'; // Full name of the plugin (used for diagnostics).
|
||||
@@ -30,7 +30,8 @@ class backup_files_edit_form extends moodleform {
|
||||
public function definition() {
|
||||
$mform =& $this->_form;
|
||||
|
||||
$options = array('subdirs' => 0, 'maxfiles' => -1, 'accepted_types' => '*', 'return_types' => FILE_INTERNAL | FILE_REFERENCE);
|
||||
$types = (FILE_INTERNAL | FILE_REFERENCE | FILE_CONTRLLED_LINK);
|
||||
$options = array('subdirs' => 0, 'maxfiles' => -1, 'accepted_types' => '*', 'return_types' => $types);
|
||||
|
||||
$mform->addElement('filemanager', 'files_filemanager', get_string('files'), null, $options);
|
||||
|
||||
|
||||
@@ -114,8 +114,13 @@ class block_login extends block_base {
|
||||
$this->content->text .= '<h6>' . get_string('potentialidps', 'auth') . '</h6>';
|
||||
$this->content->text .= '<div class="potentialidplist">';
|
||||
foreach ($potentialidps as $idp) {
|
||||
$this->content->text .= '<div class="potentialidp"><a href="' . $idp['url']->out() . '" title="' . s($idp['name']) . '">';
|
||||
$this->content->text .= $OUTPUT->render($idp['icon'], $idp['name']) . s($idp['name']) . '</a></div>';
|
||||
$this->content->text .= '<div class="potentialidp">';
|
||||
$this->content->text .= '<a class="btn btn-secondary btn-block" ';
|
||||
$this->content->text .= 'href="' . $idp['url']->out() . '" title="' . s($idp['name']) . '">';
|
||||
if (!empty($idp['iconurl'])) {
|
||||
$this->content->text .= '<img src="' . s($idp['iconurl']) . '" width="24" height="24" class="m-r-1"/>';
|
||||
}
|
||||
$this->content->text .= s($idp['name']) . '</a></div>';
|
||||
}
|
||||
$this->content->text .= '</div>';
|
||||
$this->content->text .= '</div>';
|
||||
|
||||
@@ -42,9 +42,11 @@ class core_calendar_export_form extends moodleform {
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public function definition() {
|
||||
global $CFG;
|
||||
global $CFG, $OUTPUT;
|
||||
$mform = $this->_form;
|
||||
|
||||
$mform->addElement('html', $OUTPUT->doc_link('calendar/export', get_string('exporthelp', 'calendar'), true));
|
||||
|
||||
$export = array();
|
||||
$export[] = $mform->createElement('radio', 'exportevents', '', get_string('eventsall', 'calendar'), 'all');
|
||||
$export[] = $mform->createElement('radio', 'exportevents', '', get_string('eventsrelatedtocourses', 'calendar'), 'courses');
|
||||
|
||||
@@ -169,4 +169,5 @@ if ($action != 'advanced') {
|
||||
echo $calendarurl;
|
||||
|
||||
echo $renderer->complete_layout();
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
+7
-1
@@ -601,7 +601,7 @@ class core_files_renderer extends plugin_renderer_base {
|
||||
</a>
|
||||
</div>
|
||||
<div class="fp-tb-manage">
|
||||
<a title="'. get_string('settings', 'repository') .'" href="#">
|
||||
<a title="'. get_string('manageurl', 'repository') .'" href="#">
|
||||
' . $this->pix_icon('a/setting', '') . '
|
||||
</a>
|
||||
</div>
|
||||
@@ -772,6 +772,12 @@ class core_files_renderer extends plugin_renderer_base {
|
||||
<input type="radio"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fp-linktype-8 control-group control-radio clearfix">
|
||||
<label class="control-label control-radio">'.get_string('makefilecontrolledlink', 'repository').'</label>
|
||||
<div class="controls control-radio">
|
||||
<input type="radio"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fp-saveas control-group clearfix">
|
||||
<label class="control-label">'.get_string('saveas', 'repository').'</label>
|
||||
<div class="controls">
|
||||
|
||||
@@ -795,6 +795,8 @@ $string['notifyloginthreshold'] = 'Threshold for email notifications';
|
||||
$string['notloggedinroleid'] = 'Role for visitors';
|
||||
$string['numberofmissingstrings'] = 'Number of missing strings: {$a}';
|
||||
$string['numberofstrings'] = 'Total number of strings: {$a->strings}<br />Missing: {$a->missing} ({$a->missingpercent} %)';
|
||||
$string['oauthrefreshtokenexpired'] = 'The refresh token for one of the OAuth services {$a->issuer} on your site {$a->siteurl} has expired. This will limit the functionality of any plugins that use this service. To fix this issue, visit the OAuth 2 Services configuration page and click on the "Connect system account" icon in the table row for this service. Be sure to login using the same service account for the OAuth system each time.';
|
||||
$string['oauthrefreshtokenexpiredshort'] = 'OAuth refresh token expired for {$a->issuer} on your site {$a->siteurl}.';
|
||||
$string['onlynoreply'] = 'Only when from a no-reply address';
|
||||
$string['opcacherecommended'] = 'PHP opcode caching improves performance and lowers memory requirements, OPcache extension is recommended and fully supported.';
|
||||
$string['opensslrecommended'] = 'Installing the optional OpenSSL library is highly recommended -- it enables Moodle Networking functionality.';
|
||||
@@ -1094,6 +1096,7 @@ $string['taskpasswordresetcleanup'] = 'Cleanup password reset attempts';
|
||||
$string['taskplagiarismcron'] = 'Background processing for legacy cron in plagiarism plugins';
|
||||
$string['taskportfoliocron'] = 'Background processing for portfolio plugins';
|
||||
$string['taskquestioncron'] = 'Background processing for question engine';
|
||||
$string['taskrefreshoauthtokens'] = 'Refresh OAuth tokens for service accounts';
|
||||
$string['taskregistrationcron'] = 'Site registration';
|
||||
$string['tasksendfailedloginnotifications'] = 'Send failed login notifications';
|
||||
$string['tasksendnewuserpasswords'] = 'Send new user passwords';
|
||||
|
||||
@@ -117,6 +117,7 @@ $string['eventsubscriptioneditwarning'] = 'This calendar event is part of a subs
|
||||
$string['expired'] = 'Expired';
|
||||
$string['explain_site_timeformat'] = 'You can choose to see times in either 12 or 24 hour format for the whole site. If you choose "default", then the format will be automatically chosen according to the language you use in the site. This setting can be overridden by user preferences.';
|
||||
$string['export'] = 'Export';
|
||||
$string['exporthelp'] = 'How do I subscribe to this calendar from a calendar application (Google/Outlook/Other)?';
|
||||
$string['exportbutton'] = 'Export';
|
||||
$string['exportcalendar'] = 'Export calendar';
|
||||
$string['forcecalendartype'] = 'Force calendar';
|
||||
|
||||
@@ -160,6 +160,7 @@ $string['lostsource'] = 'Error. Source is missing. {$a}';
|
||||
$string['makefileinternal'] = 'Make a copy of the file';
|
||||
$string['makefilelink'] = 'Link to the file directly';
|
||||
$string['makefilereference'] = 'Create an alias/shortcut to the file';
|
||||
$string['makefilecontrolledlink'] = 'Create an access controlled link to the file';
|
||||
$string['manage'] = 'Manage repositories';
|
||||
$string['manageinstances'] = 'Manage instances';
|
||||
$string['manageurl'] = 'Manage';
|
||||
@@ -232,6 +233,7 @@ $string['unknownoriginal'] = 'Unknown';
|
||||
$string['upload'] = 'Upload this file';
|
||||
$string['uploading'] = 'Uploading...';
|
||||
$string['uploadsucc'] = 'The file has been uploaded successfully';
|
||||
$string['unknownsource'] = 'Unknown source';
|
||||
$string['undisclosedsource'] = '(Undisclosed)';
|
||||
$string['undisclosedreference'] = '(Undisclosed)';
|
||||
$string['uselatestfile'] = 'Use latest file';
|
||||
|
||||
+1
-20
@@ -102,26 +102,7 @@ class auth_plugin_base {
|
||||
* The fields we can lock and update from/to external authentication backends
|
||||
* @var array
|
||||
*/
|
||||
var $userfields = array(
|
||||
'firstname',
|
||||
'lastname',
|
||||
'email',
|
||||
'city',
|
||||
'country',
|
||||
'lang',
|
||||
'description',
|
||||
'url',
|
||||
'idnumber',
|
||||
'institution',
|
||||
'department',
|
||||
'phone1',
|
||||
'phone2',
|
||||
'address',
|
||||
'firstnamephonetic',
|
||||
'lastnamephonetic',
|
||||
'middlename',
|
||||
'alternatename'
|
||||
);
|
||||
var $userfields = \core_user::AUTHSYNCFIELDS;
|
||||
|
||||
/**
|
||||
* Moodle custom fields to sync with.
|
||||
|
||||
@@ -100,6 +100,12 @@ abstract class core_filetypes {
|
||||
'gallery' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'),
|
||||
'galleryitem' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'),
|
||||
'gallerycollection' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'),
|
||||
'gdraw' => array('type' => 'application/vnd.google-apps.drawing', 'icon' => 'image', 'groups' => array('image')),
|
||||
'gdoc' => array('type' => 'application/vnd.google-apps.document', 'icon' => 'document', 'groups' => array('document')),
|
||||
'gsheet' => array('type' => 'application/vnd.google-apps.spreadsheet', 'icon' => 'spreadsheet',
|
||||
'groups' => array('spreadsheet')),
|
||||
'gslides' => array('type' => 'application/vnd.google-apps.presentation', 'icon' => 'powerpoint',
|
||||
'groups' => array('presentation')),
|
||||
'gif' => array('type' => 'image/gif', 'icon' => 'gif', 'groups' => array('image', 'web_image'), 'string' => 'image'),
|
||||
'gtar' => array('type' => 'application/x-gtar', 'icon' => 'archive',
|
||||
'groups' => array('archive'), 'string' => 'archive'),
|
||||
|
||||
@@ -0,0 +1,765 @@
|
||||
<?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
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core\oauth2;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
use context_system;
|
||||
use curl;
|
||||
use stdClass;
|
||||
use moodle_exception;
|
||||
use moodle_url;
|
||||
|
||||
|
||||
/**
|
||||
* Static list of api methods for system oauth2 configuration.
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class api {
|
||||
|
||||
/**
|
||||
* Create a google ready OAuth 2 service.
|
||||
* @return core\oauth2\issuer
|
||||
*/
|
||||
private static function create_google() {
|
||||
$record = (object) [
|
||||
'name' => 'Google',
|
||||
'image' => 'https://accounts.google.com/favicon.ico',
|
||||
'baseurl' => 'http://accounts.google.com/',
|
||||
'loginparamsoffline' => 'access_type=offline&prompt=consent',
|
||||
'showonloginpage' => true
|
||||
];
|
||||
|
||||
$issuer = new issuer(0, $record);
|
||||
$issuer->create();
|
||||
|
||||
$record = (object) [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'name' => 'discovery_endpoint',
|
||||
'url' => 'https://accounts.google.com/.well-known/openid-configuration'
|
||||
];
|
||||
$endpoint = new endpoint(0, $record);
|
||||
$endpoint->create();
|
||||
return $issuer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a facebook ready OAuth 2 service.
|
||||
* @return core\oauth2\issuer
|
||||
*/
|
||||
private static function create_facebook() {
|
||||
// Facebook is a custom setup.
|
||||
$record = (object) [
|
||||
'name' => 'Facebook',
|
||||
'image' => 'https://facebookbrand.com/wp-content/themes/fb-branding/prj-fb-branding/assets/images/fb-art.png',
|
||||
'baseurl' => '',
|
||||
'loginscopes' => 'public_profile email',
|
||||
'loginscopesoffline' => 'public_profile email',
|
||||
'showonloginpage' => true
|
||||
];
|
||||
|
||||
$issuer = new issuer(0, $record);
|
||||
$issuer->create();
|
||||
|
||||
$endpoints = [
|
||||
'authorization_endpoint' => 'https://www.facebook.com/v2.8/dialog/oauth',
|
||||
'token_endpoint' => 'https://graph.facebook.com/v2.8/oauth/access_token',
|
||||
'userinfo_endpoint' => 'https://graph.facebook.com/v2.8/me?fields=id,first_name,last_name,link,picture,name,email'
|
||||
];
|
||||
|
||||
foreach ($endpoints as $name => $url) {
|
||||
$record = (object) [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'name' => $name,
|
||||
'url' => $url
|
||||
];
|
||||
$endpoint = new endpoint(0, $record);
|
||||
$endpoint->create();
|
||||
}
|
||||
|
||||
// Create the field mappings.
|
||||
$mapping = [
|
||||
'name' => 'alternatename',
|
||||
'last_name' => 'lastname',
|
||||
'email' => 'email',
|
||||
'first_name' => 'firstname',
|
||||
'picture-data-url' => 'picture',
|
||||
'link' => 'url',
|
||||
];
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a microsoft ready OAuth 2 service.
|
||||
* @return core\oauth2\issuer
|
||||
*/
|
||||
private static function create_microsoft() {
|
||||
// Microsoft is a custom setup.
|
||||
$record = (object) [
|
||||
'name' => 'Microsoft',
|
||||
'image' => 'https://www.microsoft.com/favicon.ico',
|
||||
'baseurl' => '',
|
||||
'loginscopes' => 'openid profile email user.read',
|
||||
'loginscopesoffline' => 'openid profile email user.read offline_access',
|
||||
'showonloginpage' => true
|
||||
];
|
||||
|
||||
$issuer = new issuer(0, $record);
|
||||
$issuer->create();
|
||||
|
||||
$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',
|
||||
];
|
||||
|
||||
foreach ($endpoints as $name => $url) {
|
||||
$record = (object) [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'name' => $name,
|
||||
'url' => $url
|
||||
];
|
||||
$endpoint = new endpoint(0, $record);
|
||||
$endpoint->create();
|
||||
}
|
||||
|
||||
// Create the field mappings.
|
||||
$mapping = [
|
||||
'givenName' => 'firstname',
|
||||
'surname' => 'lastname',
|
||||
'userPrincipalName' => 'email',
|
||||
'displayName' => 'alternatename',
|
||||
'officeLocation' => 'address',
|
||||
'mobilePhone' => 'phone1',
|
||||
'preferredLanguage' => '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 $issuer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create one of the standard issuers.
|
||||
* @param string $type One of google, facebook, microsoft
|
||||
* @return \core\oauth2\issuer
|
||||
*/
|
||||
public static function create_standard_issuer($type) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
if ($type == 'google') {
|
||||
return self::create_google();
|
||||
} else if ($type == 'microsoft') {
|
||||
return self::create_microsoft();
|
||||
} else if ($type == 'facebook') {
|
||||
return self::create_facebook();
|
||||
} else {
|
||||
throw new moodle_exception('OAuth 2 service type not recognised: ' . $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all the issuers, ordered by the sortorder field
|
||||
* @return core\oauth2\issuer[]
|
||||
*/
|
||||
public static function get_all_issuers() {
|
||||
return issuer::get_records([], 'sortorder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single issuer by id.
|
||||
*
|
||||
* @param int $id
|
||||
* @return core\oauth2\issuer
|
||||
*/
|
||||
public static function get_issuer($id) {
|
||||
return new issuer($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single endpoint by id.
|
||||
*
|
||||
* @param int $id
|
||||
* @return core\oauth2\endpoint
|
||||
*/
|
||||
public static function get_endpoint($id) {
|
||||
return new endpoint($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single user field mapping by id.
|
||||
*
|
||||
* @param int $id
|
||||
* @return core\oauth2\user_field_mapping
|
||||
*/
|
||||
public static function get_user_field_mapping($id) {
|
||||
return new user_field_mapping($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the system account for an installed OAuth service.
|
||||
* Never ever ever expose this to a webservice because it contains the refresh token which grants API access.
|
||||
*
|
||||
* @param \core\oauth2\issuer $issuer
|
||||
* @return \core\oauth2\client
|
||||
*/
|
||||
public static function get_system_account(issuer $issuer) {
|
||||
return system_account::get_record(['issuerid' => $issuer->get('id')]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full list of system scopes required by an oauth issuer.
|
||||
* This includes the list required for login as well as any scopes injected by the oauth2_system_scopes callback in plugins.
|
||||
*
|
||||
* @param \core\oauth2\issuer $issuer
|
||||
* @return string
|
||||
*/
|
||||
public static function get_system_scopes_for_issuer($issuer) {
|
||||
$scopes = $issuer->get('loginscopesoffline');
|
||||
|
||||
$pluginsfunction = get_plugins_with_function('oauth2_system_scopes', 'lib.php');
|
||||
foreach ($pluginsfunction as $plugintype => $plugins) {
|
||||
foreach ($plugins as $pluginfunction) {
|
||||
// Get additional scopes from the plugin.
|
||||
$pluginscopes = $pluginfunction($issuer);
|
||||
if (empty($pluginscopes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Merge the additional scopes with the existing ones.
|
||||
$additionalscopes = explode(' ', $pluginscopes);
|
||||
|
||||
foreach ($additionalscopes as $scope) {
|
||||
if (!empty($scope)) {
|
||||
if (strpos(' ' . $scopes . ' ', ' ' . $scope . ' ') === false) {
|
||||
$scopes .= ' ' . $scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an authenticated oauth2 client using the system account.
|
||||
* This call uses the refresh token to get an access token.
|
||||
*
|
||||
* @param core\oauth2\issuer $issuer
|
||||
* @return core\oauth2\client
|
||||
*/
|
||||
public static function get_system_oauth_client(issuer $issuer) {
|
||||
$systemaccount = self::get_system_account($issuer);
|
||||
if (empty($systemaccount)) {
|
||||
return false;
|
||||
}
|
||||
// Get all the scopes!
|
||||
$scopes = self::get_system_scopes_for_issuer($issuer);
|
||||
|
||||
$client = new \core\oauth2\client($issuer, null, $scopes, true);
|
||||
|
||||
if (!$client->is_logged_in()) {
|
||||
if (!$client->upgrade_refresh_token($systemaccount)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an authenticated oauth2 client using the current user account.
|
||||
* This call does the redirect dance back to the current page after authentication.
|
||||
*
|
||||
* @param core\oauth2\issuer $issuer The desired OAuth issuer
|
||||
* @param moodle_url $currenturl The url to the current page.
|
||||
* @param string $additionalscopes The additional scopes required for authorization.
|
||||
* @return core\oauth2\client
|
||||
*/
|
||||
public static function get_user_oauth_client(issuer $issuer, moodle_url $currenturl, $additionalscopes = '') {
|
||||
$client = new \core\oauth2\client($issuer, $currenturl, $additionalscopes);
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of defined endpoints for this OAuth issuer
|
||||
*
|
||||
* @param core\oauth2\issuer $issuer The desired OAuth issuer
|
||||
* @return core\oauth2\endpoint[]
|
||||
*/
|
||||
public static function get_endpoints(issuer $issuer) {
|
||||
return endpoint::get_records(['issuerid' => $issuer->get('id')]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of defined mapping from OAuth user fields to moodle user fields.
|
||||
*
|
||||
* @param core\oauth2\issuer $issuer The desired OAuth issuer
|
||||
* @return core\oauth2\user_field_mapping[]
|
||||
*/
|
||||
public static function get_user_field_mappings(issuer $issuer) {
|
||||
return user_field_mapping::get_records(['issuerid' => $issuer->get('id')]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess an image from the discovery URL.
|
||||
*
|
||||
* @param core\oauth2\issuer $issuer The desired OAuth issuer
|
||||
*/
|
||||
protected static function guess_image($issuer) {
|
||||
if (empty($issuer->get('image'))) {
|
||||
$baseurl = parse_url($issuer->get('discoveryurl'));
|
||||
$imageurl = $baseurl['scheme'] . '://' . $baseurl['host'] . '/favicon.ico';
|
||||
$issuer->set('image', $imageurl);
|
||||
$issuer->update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the discovery endpoint exists for this issuer, try and determine the list of valid endpoints.
|
||||
*
|
||||
* @param issuer $issuer
|
||||
* @return int The number of discovered services.
|
||||
*/
|
||||
protected static function discover_endpoints($issuer) {
|
||||
$curl = new curl();
|
||||
|
||||
if (empty($issuer->get('baseurl'))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$url = $issuer->get_endpoint_url('discovery');
|
||||
if (!$url) {
|
||||
$url = $issuer->get('baseurl') . '/.well-known/openid-configuration';
|
||||
}
|
||||
|
||||
if (!$json = $curl->get($url)) {
|
||||
$msg = 'Could not discover end points for identity issuer' . $issuer->get('name');
|
||||
throw new moodle_exception($msg);
|
||||
}
|
||||
|
||||
if ($msg = $curl->error) {
|
||||
throw new moodle_exception('Could not discover service endpoints: ' . $msg);
|
||||
}
|
||||
|
||||
$info = json_decode($json);
|
||||
if (empty($info)) {
|
||||
$msg = 'Could not discover end points for identity issuer' . $issuer->get('name');
|
||||
throw new moodle_exception($msg);
|
||||
}
|
||||
|
||||
foreach (endpoint::get_records(['issuerid' => $issuer->get('id')]) as $endpoint) {
|
||||
if ($endpoint->get('name') != 'discovery_endpoint') {
|
||||
$endpoint->delete();
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($info as $key => $value) {
|
||||
if (substr_compare($key, '_endpoint', - strlen('_endpoint')) === 0) {
|
||||
$record = new stdClass();
|
||||
$record->issuerid = $issuer->get('id');
|
||||
$record->name = $key;
|
||||
$record->url = $value;
|
||||
|
||||
$endpoint = new endpoint(0, $record);
|
||||
$endpoint->create();
|
||||
}
|
||||
|
||||
if ($key == 'scopes_supported') {
|
||||
$issuer->set('scopessupported', implode(' ', $value));
|
||||
$issuer->update();
|
||||
}
|
||||
}
|
||||
|
||||
// We got to here - must be a decent OpenID connect service. Add the default user field mapping list.
|
||||
foreach (user_field_mapping::get_records(['issuerid' => $issuer->get('id')]) as $userfieldmapping) {
|
||||
$userfieldmapping->delete();
|
||||
}
|
||||
|
||||
// Create the field mappings.
|
||||
$mapping = [
|
||||
'given_name' => 'firstname',
|
||||
'middle_name' => 'middlename',
|
||||
'family_name' => 'lastname',
|
||||
'email' => 'email',
|
||||
'website' => 'url',
|
||||
'nickname' => 'alternatename',
|
||||
'picture' => 'picture',
|
||||
'address' => 'address',
|
||||
'phone' => 'phone1',
|
||||
'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')]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the data from the mform and update the issuer.
|
||||
*
|
||||
* @param stdClass $data
|
||||
* @return core\oauth2\issuer
|
||||
*/
|
||||
public static function update_issuer($data) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$issuer = new issuer(0, $data);
|
||||
|
||||
// Will throw exceptions on validation failures.
|
||||
$issuer->update();
|
||||
|
||||
// Perform service discovery.
|
||||
self::discover_endpoints($issuer);
|
||||
self::guess_image($issuer);
|
||||
return $issuer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the data from the mform and create the issuer.
|
||||
*
|
||||
* @param stdClass $data
|
||||
* @return core\oauth2\issuer
|
||||
*/
|
||||
public static function create_issuer($data) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$issuer = new issuer(0, $data);
|
||||
|
||||
// Will throw exceptions on validation failures.
|
||||
$issuer->create();
|
||||
|
||||
// Perform service discovery.
|
||||
self::discover_endpoints($issuer);
|
||||
self::guess_image($issuer);
|
||||
return $issuer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the data from the mform and update the endpoint.
|
||||
*
|
||||
* @param stdClass $data
|
||||
* @return core\oauth2\endpoint
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the data from the mform and create the endpoint.
|
||||
*
|
||||
* @param stdClass $data
|
||||
* @return core\oauth2\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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the data from the mform and update the user field mapping.
|
||||
*
|
||||
* @param stdClass $data
|
||||
* @return core\oauth2\user_field_mapping
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the data from the mform and create the user field mapping.
|
||||
*
|
||||
* @param stdClass $data
|
||||
* @return core\oauth2\user_field_mapping
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder this identity issuer.
|
||||
*
|
||||
* Requires moodle/site:config capability at the system context.
|
||||
*
|
||||
* @param int $id The id of the identity issuer to move.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function move_up_issuer($id) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$current = new issuer($id);
|
||||
|
||||
$sortorder = $current->get('sortorder');
|
||||
if ($sortorder == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sortorder = $sortorder - 1;
|
||||
$current->set('sortorder', $sortorder);
|
||||
|
||||
$filters = array('sortorder' => $sortorder);
|
||||
$children = issuer::get_records($filters, 'id');
|
||||
foreach ($children as $needtoswap) {
|
||||
$needtoswap->set('sortorder', $sortorder + 1);
|
||||
$needtoswap->update();
|
||||
}
|
||||
|
||||
// OK - all set.
|
||||
$result = $current->update();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder this identity issuer.
|
||||
*
|
||||
* Requires moodle/site:config capability at the system context.
|
||||
*
|
||||
* @param int $id The id of the identity issuer to move.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function move_down_issuer($id) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$current = new issuer($id);
|
||||
|
||||
$max = issuer::count_records();
|
||||
if ($max > 0) {
|
||||
$max--;
|
||||
}
|
||||
|
||||
$sortorder = $current->get('sortorder');
|
||||
if ($sortorder >= $max) {
|
||||
return false;
|
||||
}
|
||||
$sortorder = $sortorder + 1;
|
||||
$current->set('sortorder', $sortorder);
|
||||
|
||||
$filters = array('sortorder' => $sortorder);
|
||||
$children = issuer::get_records($filters);
|
||||
foreach ($children as $needtoswap) {
|
||||
$needtoswap->set('sortorder', $sortorder - 1);
|
||||
$needtoswap->update();
|
||||
}
|
||||
|
||||
// OK - all set.
|
||||
$result = $current->update();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable an identity issuer.
|
||||
*
|
||||
* Requires moodle/site:config capability at the system context.
|
||||
*
|
||||
* @param int $id The id of the identity issuer to disable.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function disable_issuer($id) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$issuer = new issuer($id);
|
||||
|
||||
$issuer->set('enabled', 0);
|
||||
return $issuer->update();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable an identity issuer.
|
||||
*
|
||||
* Requires moodle/site:config capability at the system context.
|
||||
*
|
||||
* @param int $id The id of the identity issuer to enable.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function enable_issuer($id) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$issuer = new issuer($id);
|
||||
|
||||
$issuer->set('enabled', 1);
|
||||
return $issuer->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an identity issuer.
|
||||
*
|
||||
* Requires moodle/site:config capability at the system context.
|
||||
*
|
||||
* @param int $id The id of the identity issuer to delete.
|
||||
* @return boolean
|
||||
*/
|
||||
public static function delete_issuer($id) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$issuer = new issuer($id);
|
||||
|
||||
$systemaccount = self::get_system_account($issuer);
|
||||
if ($systemaccount) {
|
||||
$systemaccount->delete();
|
||||
}
|
||||
$endpoints = self::get_endpoints($issuer);
|
||||
if ($endpoints) {
|
||||
foreach ($endpoints as $endpoint) {
|
||||
$endpoint->delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Will throw exceptions on validation failures.
|
||||
return $issuer->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an endpoint.
|
||||
*
|
||||
* Requires moodle/site:config capability at the system context.
|
||||
*
|
||||
* @param int $id The id of the endpoint to delete.
|
||||
* @return boolean
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a user_field_mapping.
|
||||
*
|
||||
* Requires moodle/site:config capability at the system context.
|
||||
*
|
||||
* @param int $id The id of the user_field_mapping to delete.
|
||||
* @return boolean
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the OAuth dance and get a refresh token.
|
||||
*
|
||||
* Requires moodle/site:config capability at the system context.
|
||||
*
|
||||
* @param core\oauth2\issuer $issuer
|
||||
* @param moodle_url $returnurl The url to the current page (we will be redirected back here after authentication).
|
||||
* @return boolean
|
||||
*/
|
||||
public static function connect_system_account($issuer, $returnurl) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
// We need to authenticate with an oauth 2 client AS a system user and get a refresh token for offline access.
|
||||
$scopes = self::get_system_scopes_for_issuer($issuer);
|
||||
|
||||
// Allow callbacks to inject non-standard scopes to the auth request.
|
||||
|
||||
$client = new client($issuer, $returnurl, $scopes, true);
|
||||
|
||||
if (!optional_param('response', false, PARAM_BOOL)) {
|
||||
$client->log_out();
|
||||
}
|
||||
|
||||
if (optional_param('error', '', PARAM_RAW)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$client->is_logged_in()) {
|
||||
redirect($client->get_login_url());
|
||||
}
|
||||
|
||||
$refreshtoken = $client->get_refresh_token();
|
||||
if (!$refreshtoken) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$systemaccount = self::get_system_account($issuer);
|
||||
if ($systemaccount) {
|
||||
$systemaccount->delete();
|
||||
}
|
||||
|
||||
$userinfo = $client->get_userinfo();
|
||||
|
||||
$record = new stdClass();
|
||||
$record->issuerid = $issuer->get('id');
|
||||
$record->refreshtoken = $refreshtoken;
|
||||
$record->grantedscopes = $scopes;
|
||||
$record->email = $userinfo['email'];
|
||||
$record->username = $userinfo['username'];
|
||||
|
||||
$systemaccount = new system_account(0, $record);
|
||||
|
||||
$systemaccount->create();
|
||||
|
||||
$client->log_out();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Configurable oauth2 client class.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core\oauth2;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/oauthlib.php');
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
use moodle_url;
|
||||
use curl;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Configurable oauth2 client class where the urls come from DB.
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class client extends \oauth2_client {
|
||||
|
||||
/** @var \core\oauth2\issuer $issuer */
|
||||
private $issuer;
|
||||
|
||||
/** @var bool $system */
|
||||
protected $system = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param issuer $issuer
|
||||
* @param moodle_url|null $returnurl
|
||||
* @param string $scopesrequired
|
||||
* @param boolean $system
|
||||
*/
|
||||
public function __construct(issuer $issuer, $returnurl, $scopesrequired, $system = false) {
|
||||
$this->issuer = $issuer;
|
||||
$this->system = $system;
|
||||
$scopes = $this->get_login_scopes();
|
||||
$additionalscopes = explode(' ', $scopesrequired);
|
||||
|
||||
foreach ($additionalscopes as $scope) {
|
||||
if (!empty($scope)) {
|
||||
if (strpos(' ' . $scopes . ' ', ' ' . $scope . ' ') === false) {
|
||||
$scopes .= ' ' . $scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (empty($returnurl)) {
|
||||
$returnurl = new moodle_url('/');
|
||||
}
|
||||
parent::__construct($issuer->get('clientid'), $issuer->get('clientsecret'), $returnurl, $scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the auth url for OAuth 2.0 request
|
||||
* @return string the auth url
|
||||
*/
|
||||
protected function auth_url() {
|
||||
return $this->issuer->get_endpoint_url('authorization');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
$params = '';
|
||||
if ($this->system) {
|
||||
if (!empty($this->issuer->get('loginparamsoffline'))) {
|
||||
$params = $this->issuer->get('loginparamsoffline');
|
||||
}
|
||||
} else {
|
||||
if (!empty($this->issuer->get('loginparams'))) {
|
||||
$params = $this->issuer->get('loginparams');
|
||||
}
|
||||
}
|
||||
if (empty($params)) {
|
||||
return [];
|
||||
}
|
||||
$result = [];
|
||||
parse_str($params, $result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to change the scopes requested with an authentiction request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_login_scopes() {
|
||||
if ($this->system) {
|
||||
return $this->issuer->get('loginscopesoffline');
|
||||
} else {
|
||||
return $this->issuer->get('loginscopes');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = 'oauth2-state-' . $this->issuer->get('id');
|
||||
if ($this->system) {
|
||||
$name .= '-system';
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of the mapping user fields in an associative array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade a refresh token from oauth 2.0 to an access token
|
||||
*
|
||||
* @param \core\oauth2\system_account $systemaccount
|
||||
* @return boolean true if token is upgraded succesfully
|
||||
*/
|
||||
public function upgrade_refresh_token(system_account $systemaccount) {
|
||||
$refreshtoken = $systemaccount->get('refreshtoken');
|
||||
|
||||
$params = array('refresh_token' => $refreshtoken,
|
||||
'client_id' => $this->issuer->get('clientid'),
|
||||
'client_secret' => $this->issuer->get('clientsecret'),
|
||||
'grant_type' => 'refresh_token'
|
||||
);
|
||||
|
||||
// Requests can either use http GET or POST.
|
||||
if ($this->use_http_get()) {
|
||||
$response = $this->get($this->token_url(), $params);
|
||||
} else {
|
||||
$response = $this->post($this->token_url(), $this->build_post_data($params));
|
||||
}
|
||||
|
||||
if (!$this->info['http_code'] === 200) {
|
||||
throw new moodle_exception('Could not upgrade oauth token');
|
||||
}
|
||||
|
||||
$r = json_decode($response);
|
||||
|
||||
if (!empty($r->error)) {
|
||||
throw new moodle_exception($r->error . ' ' . $r->error_description);
|
||||
}
|
||||
|
||||
if (!isset($r->access_token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($r->refresh_token)) {
|
||||
$systemaccount->set('refreshtoken', $r->refresh_token);
|
||||
$systemaccount->update();
|
||||
$this->refreshtoken = $r->refresh_token;
|
||||
}
|
||||
|
||||
// Store the token an expiry time.
|
||||
$accesstoken = new stdClass;
|
||||
$accesstoken->token = $r->access_token;
|
||||
if (isset($r->expires_in)) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the user info from the user info endpoint and map all
|
||||
* the fields back into moodle fields.
|
||||
*
|
||||
* @return array (Moodle user fields for the logged in user).
|
||||
*/
|
||||
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) {
|
||||
// We support nested objects via a-b-c syntax.
|
||||
$getfunc = function($obj, $prop) use (&$getfunc) {
|
||||
$proplist = explode('-', $prop, 2);
|
||||
if (empty($proplist[0]) || empty($obj->{$proplist[0]})) {
|
||||
return false;
|
||||
}
|
||||
$obj = $obj->{$proplist[0]};
|
||||
|
||||
if (count($proplist) > 1) {
|
||||
return $getfunc($obj, $proplist[1]);
|
||||
}
|
||||
return $obj;
|
||||
};
|
||||
|
||||
$resolved = $getfunc($userinfo, $openidproperty);
|
||||
if (!empty($resolved)) {
|
||||
$user->$moodleproperty = $resolved;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($user->username) && !empty($user->email)) {
|
||||
$user->username = $user->email;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($user->picture)) {
|
||||
// If it doesn't look like a picture lets unset it.
|
||||
if (function_exists('imagecreatefromstring')) {
|
||||
$img = @imagecreatefromstring($user->picture);
|
||||
if (empty($img)) {
|
||||
unset($user->picture);
|
||||
} else {
|
||||
imagedestroy($img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (array)$user;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?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
|
||||
* @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;
|
||||
use lang_string;
|
||||
|
||||
/**
|
||||
* Class for loading/storing oauth2 endpoints from the DB
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class endpoint extends persistent {
|
||||
|
||||
const TABLE = 'oauth2_endpoint';
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return array(
|
||||
'issuerid' => array(
|
||||
'type' => PARAM_INT
|
||||
),
|
||||
'name' => array(
|
||||
'type' => PARAM_ALPHANUMEXT,
|
||||
),
|
||||
'url' => array(
|
||||
'type' => PARAM_URL,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom validator for end point URLs.
|
||||
* Because we send Bearer tokens we must ensure SSL.
|
||||
*
|
||||
* @param string $value The value to check.
|
||||
* @return lang_string|boolean
|
||||
*/
|
||||
protected function validate_url($value) {
|
||||
if (strpos($value, 'https://') !== 0) {
|
||||
return new lang_string('sslonlyaccess', 'error');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
<?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 issuers from the DB.
|
||||
*
|
||||
* @package core
|
||||
* @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 issuer from the DB
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class issuer extends persistent {
|
||||
|
||||
const TABLE = 'oauth2_issuer';
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return array(
|
||||
'name' => array(
|
||||
'type' => PARAM_TEXT
|
||||
),
|
||||
'image' => array(
|
||||
'type' => PARAM_URL,
|
||||
'null' => NULL_ALLOWED,
|
||||
'default' => null
|
||||
),
|
||||
'clientid' => array(
|
||||
'type' => PARAM_RAW_TRIMMED,
|
||||
'default' => ''
|
||||
),
|
||||
'clientsecret' => array(
|
||||
'type' => PARAM_RAW_TRIMMED,
|
||||
'default' => ''
|
||||
),
|
||||
'baseurl' => array(
|
||||
'type' => PARAM_URL,
|
||||
'default' => ''
|
||||
),
|
||||
'enabled' => array(
|
||||
'type' => PARAM_BOOL,
|
||||
'default' => true
|
||||
),
|
||||
'showonloginpage' => array(
|
||||
'type' => PARAM_BOOL,
|
||||
'default' => false
|
||||
),
|
||||
'scopessupported' => array(
|
||||
'type' => PARAM_RAW,
|
||||
'null' => NULL_ALLOWED,
|
||||
'default' => null
|
||||
),
|
||||
'loginscopes' => array(
|
||||
'type' => PARAM_RAW,
|
||||
'default' => 'openid profile email'
|
||||
),
|
||||
'loginscopesoffline' => array(
|
||||
'type' => PARAM_RAW,
|
||||
'default' => 'openid profile email'
|
||||
),
|
||||
'loginparams' => array(
|
||||
'type' => PARAM_RAW,
|
||||
'default' => ''
|
||||
),
|
||||
'loginparamsoffline' => array(
|
||||
'type' => PARAM_RAW,
|
||||
'default' => ''
|
||||
),
|
||||
'alloweddomains' => array(
|
||||
'type' => PARAM_RAW,
|
||||
'default' => ''
|
||||
),
|
||||
'sortorder' => array(
|
||||
'type' => PARAM_INT,
|
||||
'default' => 0,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to execute before validate.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function before_validate() {
|
||||
if (($this->get('id') && $this->get('sortorder') === null) || !$this->get('id')) {
|
||||
$this->set('sortorder', $this->count_records());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper the get a named service endpoint.
|
||||
* @param string $type
|
||||
* @return string|false
|
||||
*/
|
||||
public function get_endpoint_url($type) {
|
||||
$endpoint = endpoint::get_record([
|
||||
'issuerid' => $this->get('id'),
|
||||
'name' => $type . '_endpoint'
|
||||
]);
|
||||
|
||||
if ($endpoint) {
|
||||
return $endpoint->get('url');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform matching against the list of allowed login domains for this issuer.
|
||||
*
|
||||
* @param string $email The email to check.
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_valid_login_domain($email) {
|
||||
if (empty($this->get('alloweddomains'))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$validdomains = explode(',', $this->get('alloweddomains'));
|
||||
|
||||
$parts = explode('@', $email, 2);
|
||||
$emaildomain = '';
|
||||
if (count($parts) > 1) {
|
||||
$emaildomain = $parts[1];
|
||||
}
|
||||
|
||||
return \core\ip_utils::is_domain_in_allowed_list($emaildomain, $validdomains);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this OAuth service support user authentication?
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_authentication_supported() {
|
||||
return (!empty($this->get_endpoint_url('userinfo')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this issuer looks like it has been configured.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_configured() {
|
||||
return (!empty($this->get('clientid')) && !empty($this->get('clientsecret')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we have a refresh token for a system account?
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_system_account_connected() {
|
||||
if (!$this->is_configured()) {
|
||||
return false;
|
||||
}
|
||||
$sys = system_account::get_record(['issuerid' => $this->get('id')]);
|
||||
if (!empty($sys) and !empty($sys->get('refreshtoken'))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* A scheduled task.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core\oauth2;
|
||||
|
||||
use \core\task\scheduled_task;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Simple task to delete old messaging records.
|
||||
* @package core
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class refresh_system_tokens_task extends scheduled_task {
|
||||
|
||||
/**
|
||||
* Get a descriptive name for this task (shown to admins).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return get_string('taskrefreshsystemtokens', 'admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify admins when an OAuth refresh token expires. Should not happen if cron is running regularly.
|
||||
* @param \core\oauth2\issuer $issuer
|
||||
*/
|
||||
protected function notify_admins(\core\oauth2\issuer $issuer) {
|
||||
$admins = get_admins();
|
||||
|
||||
if (empty($admins)) {
|
||||
return;
|
||||
}
|
||||
foreach ($admins as $admin) {
|
||||
$strparams = ['siteurl' => $CFG->wwwroot, 'issuer' => $issuer->get('name')];
|
||||
$long = get_string('oauthrefreshtokenexpired', 'core_admin', $strparams);
|
||||
$short = get_string('oauthrefreshtokenexpiredshort', 'core_admin', $strparams);
|
||||
$message = new \core\message\message();
|
||||
$message->courseid = SITEID;
|
||||
$message->component = 'moodle';
|
||||
$message->name = 'oauthrefreshtokenexpired';
|
||||
$message->userfrom = core\user::get_noreply_user();
|
||||
$message->userto = $admin;
|
||||
$message->subject = $short;
|
||||
$message->fullmessage = $long;
|
||||
$message->fullmessageformat = FORMAT_PLAIN;
|
||||
$message->fullmessagehtml = $long;
|
||||
$message->smallmessage = $short;
|
||||
$message->notification = 1;
|
||||
message_send($message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do the job.
|
||||
* Throw exceptions on errors (the job will be retried).
|
||||
*/
|
||||
public function execute() {
|
||||
$issuers = \core\oauth2\api::get_all_issuers();
|
||||
foreach ($issuers as $issuer) {
|
||||
if ($issuer->is_system_account_connected()) {
|
||||
if (!\core\oauth2\api::get_system_oauth_client($issuer)) {
|
||||
$this->notify_admins($issuer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* Rest API base class mapping rest api methods to endpoints with http methods, args and post body.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core\oauth2;
|
||||
|
||||
use curl;
|
||||
use coding_exception;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
/**
|
||||
* Rest API base class mapping rest api methods to endpoints with http methods, args and post body.
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class rest {
|
||||
|
||||
/** @var curl $curl */
|
||||
private $curl;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param curl $curl
|
||||
*/
|
||||
public function __construct(curl $curl) {
|
||||
$this->curl = $curl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract function to define the functions of the rest API.
|
||||
*
|
||||
* @return array Example:
|
||||
* [ 'listFiles' => [ 'method' => 'get', 'args' => [ 'folder' => PARAM_STRING ], 'response' => 'json' ] ]
|
||||
*/
|
||||
public abstract function get_api_functions();
|
||||
|
||||
/**
|
||||
* Call a function from the Api with a set of arguments and optional data.
|
||||
*
|
||||
* @param string $functionname
|
||||
* @param array $functionargs
|
||||
* @param string $rawpost Optional param to include in the body of a post.
|
||||
* @return string|object
|
||||
*/
|
||||
public function call($functionname, $functionargs, $rawpost = false) {
|
||||
$functions = $this->get_api_functions();
|
||||
$supportedmethods = [ 'get', 'put', 'post', 'patch', 'head', 'delete' ];
|
||||
if (empty($functions[$functionname])) {
|
||||
throw new coding_exception('unsupported api functionname: ' . $functionname);
|
||||
}
|
||||
|
||||
$method = $functions[$functionname]['method'];
|
||||
$endpoint = $functions[$functionname]['endpoint'];
|
||||
|
||||
$responsetype = $functions[$functionname]['response'];
|
||||
if (!in_array($method, $supportedmethods)) {
|
||||
throw new coding_exception('unsupported api method: ' . $method);
|
||||
}
|
||||
|
||||
$args = $functions[$functionname]['args'];
|
||||
$callargs = [];
|
||||
foreach ($args as $argname => $argtype) {
|
||||
if (isset($functionargs[$argname])) {
|
||||
$callargs[$argname] = clean_param($functionargs[$argname], $argtype);
|
||||
}
|
||||
}
|
||||
|
||||
// Allow params in the URL path like /me/{parent}/children.
|
||||
foreach ($callargs as $argname => $value) {
|
||||
$newendpoint = str_replace('{' . $argname . '}', $value, $endpoint);
|
||||
if ($newendpoint != $endpoint) {
|
||||
$endpoint = $newendpoint;
|
||||
unset($callargs[$argname]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($rawpost !== false) {
|
||||
$queryparams = $this->curl->build_post_data($callargs);
|
||||
if (!empty($queryparams)) {
|
||||
$endpoint .= '?' . $queryparams;
|
||||
}
|
||||
$callargs = $rawpost;
|
||||
}
|
||||
|
||||
$this->curl->setHeader('Content-type: application/json');
|
||||
$response = $this->curl->$method($endpoint, $callargs);
|
||||
|
||||
if ($this->curl->errno == 0) {
|
||||
if ($responsetype == 'json') {
|
||||
$json = json_decode($response);
|
||||
|
||||
if (!empty($json->error)) {
|
||||
throw new rest_exception($json->error->code . ': ' . $json->error->message);
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
return $response;
|
||||
} else {
|
||||
throw new rest_exception($this->curl->error, $this->curl->errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Rest Exception class containing error code and message.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core\oauth2;
|
||||
|
||||
use Exception;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
/**
|
||||
* Rest Exception class containing error code and message.
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class rest_exception extends Exception {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* When using OAuth sometimes it makes sense to authenticate as a system user, and not the current user.
|
||||
*
|
||||
* @package core
|
||||
* @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 refresh tokens from the DB.
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class system_account extends persistent {
|
||||
|
||||
const TABLE = 'oauth2_system_account';
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return array(
|
||||
'issuerid' => array(
|
||||
'type' => PARAM_INT
|
||||
),
|
||||
'refreshtoken' => array(
|
||||
'type' => PARAM_RAW,
|
||||
),
|
||||
'grantedscopes' => array(
|
||||
'type' => PARAM_RAW,
|
||||
),
|
||||
'email' => array(
|
||||
'type' => PARAM_RAW,
|
||||
),
|
||||
'username' => array(
|
||||
'type' => PARAM_RAW,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?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
|
||||
* @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';
|
||||
|
||||
/**
|
||||
* Return the list of valid internal user fields.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function get_user_fields() {
|
||||
return array_merge(\core_user::AUTHSYNCFIELDS, ['picture', 'username']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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::get_user_fields()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of internal fields
|
||||
* in a format they can be used for choices in a select menu
|
||||
* @return array
|
||||
*/
|
||||
public function get_internalfield_list() {
|
||||
return array_combine(self::get_user_fields(), self::get_user_fields());
|
||||
}
|
||||
}
|
||||
@@ -1701,7 +1701,7 @@ class core_plugin_manager {
|
||||
|
||||
'auth' => array(
|
||||
'cas', 'db', 'email', 'fc', 'imap', 'ldap', 'lti', 'manual', 'mnet',
|
||||
'nntp', 'nologin', 'none', 'pam', 'pop3', 'shibboleth', 'webservice'
|
||||
'nntp', 'nologin', 'none', 'oauth2', 'pam', 'pop3', 'shibboleth', 'webservice'
|
||||
),
|
||||
|
||||
'availability' => array(
|
||||
@@ -1902,7 +1902,7 @@ class core_plugin_manager {
|
||||
'assignmentupgrade', 'availabilityconditions', 'behat', 'capability', 'cohortroles', 'customlang',
|
||||
'dbtransfer', 'filetypes', 'generator', 'health', 'innodb', 'installaddon',
|
||||
'langimport', 'log', 'lp', 'lpimportcsv', 'lpmigrate', 'messageinbound', 'mobile', 'multilangupgrade', 'monitor',
|
||||
'phpunit', 'profiling', 'recyclebin', 'replace', 'spamcleaner', 'task', 'templatelibrary',
|
||||
'oauth2', 'phpunit', 'profiling', 'recyclebin', 'replace', 'spamcleaner', 'task', 'templatelibrary',
|
||||
'unittest', 'uploadcourse', 'uploaduser', 'unsuproles', 'usertours', 'xmldb'
|
||||
),
|
||||
|
||||
|
||||
@@ -58,6 +58,30 @@ class core_user {
|
||||
*/
|
||||
const MAILDISPLAY_COURSE_MEMBERS_ONLY = 2;
|
||||
|
||||
/**
|
||||
* List of fields that can be synched/locked during authentication.
|
||||
*/
|
||||
const AUTHSYNCFIELDS = [
|
||||
'firstname',
|
||||
'lastname',
|
||||
'email',
|
||||
'city',
|
||||
'country',
|
||||
'lang',
|
||||
'description',
|
||||
'url',
|
||||
'idnumber',
|
||||
'institution',
|
||||
'department',
|
||||
'phone1',
|
||||
'phone2',
|
||||
'address',
|
||||
'firstnamephonetic',
|
||||
'lastnamephonetic',
|
||||
'middlename',
|
||||
'alternatename'
|
||||
];
|
||||
|
||||
/** @var stdClass keep record of noreply user */
|
||||
public static $noreplyuser = false;
|
||||
|
||||
@@ -100,6 +124,29 @@ class core_user {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return user object from db based on their email.
|
||||
*
|
||||
* @param string $email The email of the user searched.
|
||||
* @param string $fields A comma separated list of user fields to be returned, support and noreply user.
|
||||
* @param int $mnethostid The id of the remote host.
|
||||
* @param int $strictness IGNORE_MISSING means compatible mode, false returned if user not found, debug message if more found;
|
||||
* IGNORE_MULTIPLE means return first user, ignore multiple user records found(not recommended);
|
||||
* MUST_EXIST means throw an exception if no user record or multiple records found.
|
||||
* @return stdClass|bool user record if found, else false.
|
||||
* @throws dml_exception if user record not found and respective $strictness is set.
|
||||
*/
|
||||
public static function get_user_by_email($email, $fields = '*', $mnethostid = null, $strictness = IGNORE_MISSING) {
|
||||
global $DB, $CFG;
|
||||
|
||||
// Because we use the username as the search criteria, we must also restrict our search based on mnet host.
|
||||
if (empty($mnethostid)) {
|
||||
// If empty, we restrict to local users.
|
||||
$mnethostid = $CFG->mnet_localhost_id;
|
||||
}
|
||||
|
||||
return $DB->get_record('user', array('email' => $email, 'mnethostid' => $mnethostid), $fields, $strictness);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return user object from db based on their username.
|
||||
@@ -864,4 +911,5 @@ class core_user {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Regular → Executable
+73
-1
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="lib/db" VERSION="20170220" COMMENT="XMLDB file for core Moodle tables"
|
||||
<XMLDB PATH="lib/db" VERSION="20170310" COMMENT="XMLDB file for core Moodle tables"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
@@ -3463,5 +3463,77 @@
|
||||
<INDEX NAME="cmidcompetencyid" UNIQUE="true" FIELDS="cmid, competencyid"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
<TABLE NAME="oauth2_endpoint" COMMENT="Describes the named endpoint for an oauth2 service.">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The time this record was created."/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The time this record was modified."/>
|
||||
<FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The user who modified this record."/>
|
||||
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The service name."/>
|
||||
<FIELD NAME="url" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The url to the endpoint"/>
|
||||
<FIELD NAME="issuerid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The identity provider this service belongs to."/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="issuer_id_key" TYPE="foreign" FIELDS="issuerid" REFTABLE="oauth2_issuer" REFFIELDS="id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="oauth2_issuer" COMMENT="Details for an oauth 2 connect identity issuer.">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Time this record was created."/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Time this record was modified."/>
|
||||
<FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The user who modified this record"/>
|
||||
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of this identity issuer"/>
|
||||
<FIELD NAME="image" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
|
||||
<FIELD NAME="baseurl" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The base url to the issuer"/>
|
||||
<FIELD NAME="clientid" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The client id used to connect to this oauth2 service."/>
|
||||
<FIELD NAME="clientsecret" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The secret used to connect to this oauth2 service."/>
|
||||
<FIELD NAME="loginscopes" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The scopes requested for a normal login attempt."/>
|
||||
<FIELD NAME="loginscopesoffline" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The scopes requested for a login attempt to generate a refresh token."/>
|
||||
<FIELD NAME="loginparams" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Additional parameters sent for a login attempt."/>
|
||||
<FIELD NAME="loginparamsoffline" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Additional parameters sent for a login attempt to generate a refresh token."/>
|
||||
<FIELD NAME="scopessupported" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="The list of scopes this service supports."/>
|
||||
<FIELD NAME="enabled" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
|
||||
<FIELD NAME="showonloginpage" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
|
||||
<FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The defined sort order."/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="oauth2_system_account" COMMENT="Stored details used to get an access token as a system user for this oauth2 service.">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Time this record was created."/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Time this record was modified."/>
|
||||
<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 id of the oauth 2 identity issuer"/>
|
||||
<FIELD NAME="refreshtoken" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The refresh token used to request access tokens."/>
|
||||
<FIELD NAME="grantedscopes" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The scopes that this system account has been granted access to."/>
|
||||
<FIELD NAME="email" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The email that was connected to this issuer."/>
|
||||
<FIELD NAME="username" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The username that was connected as a system account to this issue."/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<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="uniqinternal" TYPE="unique" FIELDS="issuerid, internalfield"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
</XMLDB>
|
||||
|
||||
@@ -347,4 +347,13 @@ $tasks = array(
|
||||
'dayofweek' => '*',
|
||||
'month' => '*'
|
||||
),
|
||||
array(
|
||||
'classname' => 'core\oauth2\refresh_system_tokens_task',
|
||||
'blocking' => 0,
|
||||
'minute' => '30',
|
||||
'hour' => '*',
|
||||
'day' => '*',
|
||||
'dayofweek' => '*',
|
||||
'month' => '*'
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2611,5 +2611,126 @@ function xmldb_main_upgrade($oldversion) {
|
||||
upgrade_main_savepoint(true, 2017031400.00);
|
||||
}
|
||||
|
||||
if ($oldversion < 2017033100.01) {
|
||||
|
||||
// Define table oauth2_issuer to be created.
|
||||
$table = new xmldb_table('oauth2_issuer');
|
||||
|
||||
// Adding fields to table oauth2_issuer.
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('timemodified', 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('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('image', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('baseurl', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('clientid', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('clientsecret', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('loginscopes', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('loginscopesoffline', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('loginparams', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('loginparamsoffline', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('alloweddomains', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('scopessupported', XMLDB_TYPE_TEXT, null, null, null, null, null);
|
||||
$table->add_field('showonloginpage', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1');
|
||||
$table->add_field('enabled', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1');
|
||||
$table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
|
||||
// Adding keys to table oauth2_issuer.
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
|
||||
// Conditionally launch create table for oauth2_issuer.
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2017033100.01);
|
||||
}
|
||||
|
||||
if ($oldversion < 2017033100.02) {
|
||||
|
||||
// Define table oauth2_endpoint to be created.
|
||||
$table = new xmldb_table('oauth2_endpoint');
|
||||
|
||||
// Adding fields to table oauth2_endpoint.
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('timemodified', 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('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('url', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
|
||||
// Adding keys to table oauth2_endpoint.
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
$table->add_key('issuer_id_key', XMLDB_KEY_FOREIGN, array('issuerid'), 'oauth2_issuer', array('id'));
|
||||
|
||||
// Conditionally launch create table for oauth2_endpoint.
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2017033100.02);
|
||||
}
|
||||
|
||||
if ($oldversion < 2017033100.03) {
|
||||
|
||||
// Define table oauth2_system_account to be created.
|
||||
$table = new xmldb_table('oauth2_system_account');
|
||||
|
||||
// Adding fields to table oauth2_system_account.
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('timemodified', 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('refreshtoken', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('grantedscopes', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('username', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('email', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
|
||||
|
||||
// Adding keys to table oauth2_system_account.
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
$table->add_key('issueridkey', XMLDB_KEY_FOREIGN_UNIQUE, array('issuerid'), 'oauth2_issuer', array('id'));
|
||||
|
||||
// Conditionally launch create table for oauth2_system_account.
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2017033100.03);
|
||||
}
|
||||
|
||||
if ($oldversion < 2017033100.04) {
|
||||
|
||||
// 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('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.04);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+97
-35
@@ -813,7 +813,7 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea
|
||||
$options['areamaxbytes'] = FILE_AREA_MAX_BYTES_UNLIMITED; // Unlimited.
|
||||
}
|
||||
$allowreferences = true;
|
||||
if (isset($options['return_types']) && !($options['return_types'] & FILE_REFERENCE)) {
|
||||
if (isset($options['return_types']) && !($options['return_types'] & (FILE_REFERENCE | FILE_CONTROLLED_LINK))) {
|
||||
// we assume that if $options['return_types'] is NOT specified, we DO allow references.
|
||||
// this is not exactly right. BUT there are many places in code where filemanager options
|
||||
// are not passed to file_save_draft_area_files()
|
||||
@@ -953,8 +953,15 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea
|
||||
if ($file->is_external_file()) {
|
||||
$repoid = $file->get_repository_id();
|
||||
if (!empty($repoid)) {
|
||||
$context = context::instance_by_id($contextid, MUST_EXIST);
|
||||
$repo = repository::get_repository_by_id($repoid, $context);
|
||||
|
||||
$file_record['repositoryid'] = $repoid;
|
||||
$file_record['reference'] = $file->get_reference();
|
||||
// This hook gives the repo a place to do some house cleaning, and update the $reference before it's saved
|
||||
// to the file store. E.g. transfer ownership of the file to a system account etc.
|
||||
$reference = $repo->reference_file_selected($file->get_reference(), $context, $component, $filearea, $itemid);
|
||||
|
||||
$file_record['reference'] = $reference;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2741,6 +2748,8 @@ class curl {
|
||||
private $securityhelper;
|
||||
/** @var bool ignoresecurity a flag which can be supplied to the constructor, allowing security to be bypassed. */
|
||||
private $ignoresecurity;
|
||||
/** @var array $mockresponses For unit testing only - return the head of this list instead of making the next request. */
|
||||
private static $mockresponses = [];
|
||||
|
||||
/**
|
||||
* Curl constructor.
|
||||
@@ -2949,6 +2958,7 @@ class curl {
|
||||
* Set HTTP Request Header
|
||||
*
|
||||
* @param array $header
|
||||
* @param bool $replace If true, will remove any existing headers before appending the new one.
|
||||
*/
|
||||
public function setHeader($header) {
|
||||
if (is_array($header)) {
|
||||
@@ -3264,6 +3274,19 @@ class curl {
|
||||
$this->responsefinished = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* For use only in unit tests - we can pre-set the next curl response.
|
||||
* This is useful for unit testing APIs that call external systems.
|
||||
* @param string $response
|
||||
*/
|
||||
public static function mock_response($response) {
|
||||
if ((defined('PHPUNIT_TEST') && PHPUNIT_TEST)) {
|
||||
array_push(self::$mockresponses, $response);
|
||||
} else {
|
||||
throw new coding_excpetion('mock_response function is only available for unit tests.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Single HTTP Request
|
||||
*
|
||||
@@ -3275,6 +3298,13 @@ class curl {
|
||||
// Reset here so that the data is valid when result returned from cache, or if we return due to a blacklist hit.
|
||||
$this->reset_request_state_vars();
|
||||
|
||||
if ((defined('PHPUNIT_TEST') && PHPUNIT_TEST)) {
|
||||
if ($mockresponse = array_pop(self::$mockresponses)) {
|
||||
$this->info = [ 'http_code' => 200 ];
|
||||
return $mockresponse;
|
||||
}
|
||||
}
|
||||
|
||||
// If curl security is enabled, check the URL against the blacklist before calling curl_exec.
|
||||
// Note: This will only check the base url. In the case of redirects, the blacklist is also after the curl_exec.
|
||||
if (!$this->ignoresecurity && $this->securityhelper->url_is_blocked($url)) {
|
||||
@@ -3435,6 +3465,34 @@ class curl {
|
||||
return $this->request($url, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP PATCH method
|
||||
*
|
||||
* @param string $url
|
||||
* @param array|string $params
|
||||
* @param array $options
|
||||
* @return bool
|
||||
*/
|
||||
public function patch($url, $params = '', $options = array()) {
|
||||
$options['CURLOPT_CUSTOMREQUEST'] = 'PATCH';
|
||||
if (is_array($params)) {
|
||||
$this->_tmp_file_post_params = array();
|
||||
foreach ($params as $key => $value) {
|
||||
if ($value instanceof stored_file) {
|
||||
$value->add_to_curl_request($this, $key);
|
||||
} else {
|
||||
$this->_tmp_file_post_params[$key] = $value;
|
||||
}
|
||||
}
|
||||
$options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params;
|
||||
unset($this->_tmp_file_post_params);
|
||||
} else {
|
||||
// The variable $params is the raw post data.
|
||||
$options['CURLOPT_POSTFIELDS'] = $params;
|
||||
}
|
||||
return $this->request($url, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP POST method
|
||||
*
|
||||
@@ -3798,9 +3856,11 @@ class curl_cache {
|
||||
* @param string $relativepath
|
||||
* @param bool $forcedownload
|
||||
* @param null|string $preview the preview mode, defaults to serving the original file
|
||||
* @param boolean $offline If offline is requested - don't serve a redirect to an external file, return a file suitable for viewing
|
||||
* offline (e.g. mobile app).
|
||||
* @todo MDL-31088 file serving improments
|
||||
*/
|
||||
function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
function file_pluginfile($relativepath, $forcedownload, $preview = null, $offline = false) {
|
||||
global $DB, $CFG, $USER;
|
||||
// relative path must start with '/'
|
||||
if (!$relativepath) {
|
||||
@@ -3824,6 +3884,8 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
|
||||
$fs = get_file_storage();
|
||||
|
||||
$sendfileoptions = ['preview' => $preview, 'offline' => $offline];
|
||||
|
||||
// ========================================================================================================================
|
||||
if ($component === 'blog') {
|
||||
// Blog file serving
|
||||
@@ -3876,7 +3938,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
send_stored_file($file, 10*60, 0, true, array('preview' => $preview)); // download MUST be forced - security!
|
||||
send_stored_file($file, 10*60, 0, true, $sendfileoptions); // download MUST be forced - security!
|
||||
|
||||
// ========================================================================================================================
|
||||
} else if ($component === 'grade') {
|
||||
@@ -3893,7 +3955,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else if ($filearea === 'feedback' and $context->contextlevel == CONTEXT_COURSE) {
|
||||
//TODO: nobody implemented this yet in grade edit form!!
|
||||
@@ -3910,7 +3972,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
} else {
|
||||
send_file_not_found();
|
||||
}
|
||||
@@ -3931,7 +3993,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, true, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, true, $sendfileoptions);
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -3953,14 +4015,14 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close();
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
} else if ($filearea === 'userbadge' and $context->contextlevel == CONTEXT_USER) {
|
||||
if (!$file = $fs->get_file($context->id, 'badges', 'userbadge', $badge->id, '/', $filename.'.png')) {
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
\core\session\manager::write_close();
|
||||
send_stored_file($file, 60*60, 0, true, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, true, $sendfileoptions);
|
||||
}
|
||||
// ========================================================================================================================
|
||||
} else if ($component === 'calendar') {
|
||||
@@ -3987,7 +4049,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_USER) {
|
||||
|
||||
@@ -4015,7 +4077,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 0, 0, true, array('preview' => $preview));
|
||||
send_stored_file($file, 0, 0, true, $sendfileoptions);
|
||||
|
||||
} else if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_COURSE) {
|
||||
|
||||
@@ -4062,7 +4124,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -4116,7 +4178,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
send_file($imagefile, basename($imagefile), 60*60*24*14);
|
||||
}
|
||||
|
||||
$options = array('preview' => $preview);
|
||||
$options = $sendfileoptions;
|
||||
if (empty($CFG->forcelogin) && empty($CFG->forceloginforprofileimage)) {
|
||||
// Profile images should be cache-able by both browsers and proxies according
|
||||
// to $CFG->forcelogin and $CFG->forceloginforprofileimage.
|
||||
@@ -4142,7 +4204,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
|
||||
send_stored_file($file, 0, 0, true, $sendfileoptions); // must force download - security!
|
||||
|
||||
} else if ($filearea === 'profile' and $context->contextlevel == CONTEXT_USER) {
|
||||
|
||||
@@ -4189,7 +4251,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
|
||||
send_stored_file($file, 0, 0, true, $sendfileoptions); // must force download - security!
|
||||
|
||||
} else if ($filearea === 'profile' and $context->contextlevel == CONTEXT_COURSE) {
|
||||
$userid = (int)array_shift($args);
|
||||
@@ -4227,7 +4289,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
|
||||
send_stored_file($file, 0, 0, true, $sendfileoptions); // must force download - security!
|
||||
|
||||
} else if ($filearea === 'backup' and $context->contextlevel == CONTEXT_USER) {
|
||||
require_login();
|
||||
@@ -4248,7 +4310,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
|
||||
send_stored_file($file, 0, 0, true, $sendfileoptions); // must force download - security!
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -4281,7 +4343,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
} else {
|
||||
send_file_not_found();
|
||||
}
|
||||
@@ -4304,7 +4366,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else if ($filearea === 'section') {
|
||||
if ($CFG->forcelogin) {
|
||||
@@ -4326,7 +4388,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -4355,7 +4417,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
if (($file = $fs->get_file($cohortcontext->id, 'cohort', 'description', $cohort->id, $filepath, $filename))
|
||||
&& !$file->is_directory()) {
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60 * 60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60 * 60, 0, $forcedownload, $sendfileoptions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4387,7 +4449,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else if ($filearea === 'icon') {
|
||||
$filename = array_pop($args);
|
||||
@@ -4402,7 +4464,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, false, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, false, $sendfileoptions);
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -4427,7 +4489,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -4446,7 +4508,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 0, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 0, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else if ($filearea === 'section' and $context->contextlevel == CONTEXT_COURSE) {
|
||||
require_login($course);
|
||||
@@ -4461,7 +4523,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close();
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else if ($filearea === 'activity' and $context->contextlevel == CONTEXT_MODULE) {
|
||||
require_login($course, false, $cm);
|
||||
@@ -4474,7 +4536,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close();
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else if ($filearea === 'automated' and $context->contextlevel == CONTEXT_COURSE) {
|
||||
// Backup files that were generated by the automated backup systems.
|
||||
@@ -4489,7 +4551,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 0, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 0, 0, $forcedownload, $sendfileoptions);
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -4498,7 +4560,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
// ========================================================================================================================
|
||||
} else if ($component === 'question') {
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'question', $filearea, $args, $forcedownload);
|
||||
question_pluginfile($course, $context, 'question', $filearea, $args, $forcedownload, $sendfileoptions);
|
||||
send_file_not_found();
|
||||
|
||||
// ========================================================================================================================
|
||||
@@ -4535,7 +4597,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
\core\session\manager::write_close(); // Unlock session during file serving.
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $sendfileoptions);
|
||||
}
|
||||
|
||||
// ========================================================================================================================
|
||||
@@ -4567,17 +4629,17 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, null, 0, false, array('preview' => $preview));
|
||||
send_stored_file($file, null, 0, false, $sendfileoptions);
|
||||
}
|
||||
|
||||
$filefunction = $component.'_pluginfile';
|
||||
$filefunctionold = $modname.'_pluginfile';
|
||||
if (function_exists($filefunction)) {
|
||||
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
|
||||
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
|
||||
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload, $sendfileoptions);
|
||||
} else if (function_exists($filefunctionold)) {
|
||||
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
|
||||
$filefunctionold($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
|
||||
$filefunctionold($course, $cm, $context, $filearea, $args, $forcedownload, $sendfileoptions);
|
||||
}
|
||||
|
||||
send_file_not_found();
|
||||
@@ -4618,7 +4680,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
$filefunction = $component.'_pluginfile';
|
||||
if (function_exists($filefunction)) {
|
||||
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
|
||||
$filefunction($course, $birecord, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
|
||||
$filefunction($course, $birecord, $context, $filearea, $args, $forcedownload, $sendfileoptions);
|
||||
}
|
||||
|
||||
send_file_not_found();
|
||||
@@ -4639,7 +4701,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
$filefunction = $component.'_pluginfile';
|
||||
if (function_exists($filefunction)) {
|
||||
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
|
||||
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
|
||||
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload, $sendfileoptions);
|
||||
}
|
||||
|
||||
send_file_not_found();
|
||||
|
||||
@@ -1128,9 +1128,9 @@ class file_storage {
|
||||
// creating a new file from an existing alias creates new alias implicitly.
|
||||
// here we just check the database consistency.
|
||||
if (!empty($newrecord->repositoryid)) {
|
||||
if ($newrecord->referencefileid != $this->get_referencefileid($newrecord->repositoryid, $newrecord->reference, MUST_EXIST)) {
|
||||
throw new file_reference_exception($newrecord->repositoryid, $newrecord->reference, $newrecord->referencefileid);
|
||||
}
|
||||
// It is OK if the current reference does not exist. It may have been altered by a repository plugin when the files
|
||||
// where saved from a draft area.
|
||||
$newrecord->referencefileid = $this->get_or_create_referencefileid($newrecord->repositoryid, $newrecord->reference);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -2323,4 +2323,5 @@ class file_storage {
|
||||
$data = array('id' => $referencefileid, 'lastsync' => $lastsync);
|
||||
$DB->update_record('files_reference', (object)$data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -102,6 +102,15 @@ class stored_file {
|
||||
return !empty($this->repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this is a controlled link. Note that repositories cannot support FILE_REFERENCE and FILE_CONTROLLED_LINK.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_controlled_link() {
|
||||
return $this->is_external_file() && $this->repository->supported_returntypes() & FILE_CONTROLLED_LINK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update some file record fields
|
||||
* NOTE: Must remain protected
|
||||
|
||||
+2
-2
@@ -58,8 +58,8 @@ class MoodleQuickForm_editor extends HTML_QuickForm_element implements templatab
|
||||
/** @var array options provided to initalize filepicker */
|
||||
protected $_options = array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 0, 'changeformat' => 0,
|
||||
'areamaxbytes' => FILE_AREA_MAX_BYTES_UNLIMITED, 'context' => null, 'noclean' => 0, 'trusttext' => 0,
|
||||
'return_types' => 7, 'enable_filemanagement' => true);
|
||||
// $_options['return_types'] = FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE
|
||||
'return_types' => 15, 'enable_filemanagement' => true);
|
||||
// 15 is $_options['return_types'] = FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE | FILE_CONTROLLED_LINK.
|
||||
|
||||
/** @var array values for editor */
|
||||
protected $_values = array('text'=>null, 'format'=>null, 'itemid'=>null);
|
||||
|
||||
@@ -78,7 +78,7 @@ class MoodleQuickForm_filemanager extends HTML_QuickForm_element implements temp
|
||||
$this->_options['maxbytes'] = get_user_max_upload_file_size($PAGE->context, $CFG->maxbytes, $options['maxbytes']);
|
||||
}
|
||||
if (empty($options['return_types'])) {
|
||||
$this->_options['return_types'] = (FILE_INTERNAL | FILE_REFERENCE);
|
||||
$this->_options['return_types'] = (FILE_INTERNAL | FILE_REFERENCE | FILE_CONTROLLED_LINK);
|
||||
}
|
||||
$this->_type = 'filemanager';
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
|
||||
+91
-20
@@ -383,16 +383,22 @@ class oauth_helper {
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class oauth2_client extends curl {
|
||||
/** var string client identifier issued to the client */
|
||||
/** @var string $clientid client identifier issued to the client */
|
||||
private $clientid = '';
|
||||
/** var string The client secret. */
|
||||
/** @var string $clientsecret The client secret. */
|
||||
private $clientsecret = '';
|
||||
/** var moodle_url URL to return to after authenticating */
|
||||
/** @var moodle_url $returnurl URL to return to after authenticating */
|
||||
private $returnurl = null;
|
||||
/** var string scope of the authentication request */
|
||||
private $scope = '';
|
||||
/** var stdClass access token object */
|
||||
/** @var string $scope of the authentication request */
|
||||
protected $scope = '';
|
||||
/** @var stdClass $accesstoken access token object */
|
||||
private $accesstoken = null;
|
||||
/** @var string $refreshtoken refresh token string */
|
||||
private $refreshtoken = '';
|
||||
/** @var string $mocknextresponse string */
|
||||
private $mocknextresponse = '';
|
||||
/** @var array $upgradedcodes list of upgraded codes in this request */
|
||||
private static $upgradedcodes = [];
|
||||
|
||||
/**
|
||||
* Returns the auth url for OAuth 2.0 request
|
||||
@@ -439,13 +445,28 @@ abstract class oauth2_client extends curl {
|
||||
|
||||
// We have a token so we are logged in.
|
||||
if (isset($this->accesstoken->token)) {
|
||||
return true;
|
||||
// Check that the access token has all the requested scopes.
|
||||
$scopemissing = false;
|
||||
$scopecheck = ' ' . $this->accesstoken->scope . ' ';
|
||||
|
||||
$requiredscopes = explode(' ', $this->scope);
|
||||
foreach ($requiredscopes as $requiredscope) {
|
||||
if (strpos($scopecheck, ' ' . $requiredscope . ' ') === false) {
|
||||
$scopemissing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$scopemissing) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we've been passed then authorization code generated by the
|
||||
// authorization server try and upgrade the token to an access token.
|
||||
$code = optional_param('oauth2code', null, PARAM_RAW);
|
||||
if ($code && $this->upgrade_token($code)) {
|
||||
// Note - sometimes we may call is_logged_in twice in the same request - we don't want to attempt
|
||||
// to upgrade the same token twice.
|
||||
if ($code && !in_array($code, self::$upgradedcodes) && $this->upgrade_token($code)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -463,6 +484,15 @@ abstract class oauth2_client extends curl {
|
||||
return new moodle_url('/admin/oauth2callback.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* An additional array of url params to pass with a login request.
|
||||
*
|
||||
* @return array of name value pairs.
|
||||
*/
|
||||
public function get_additional_login_parameters() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the login link for this oauth request
|
||||
*
|
||||
@@ -471,15 +501,32 @@ abstract class oauth2_client extends curl {
|
||||
public function get_login_url() {
|
||||
|
||||
$callbackurl = self::callback_url();
|
||||
$url = new moodle_url($this->auth_url(),
|
||||
array('client_id' => $this->clientid,
|
||||
'response_type' => 'code',
|
||||
'redirect_uri' => $callbackurl->out(false),
|
||||
'state' => $this->returnurl->out_as_local_url(false),
|
||||
'scope' => $this->scope,
|
||||
));
|
||||
$params = array_merge(
|
||||
[
|
||||
'client_id' => $this->clientid,
|
||||
'response_type' => 'code',
|
||||
'redirect_uri' => $callbackurl->out(false),
|
||||
'state' => $this->returnurl->out_as_local_url(false),
|
||||
'scope' => $this->scope,
|
||||
],
|
||||
$this->get_additional_login_parameters()
|
||||
);
|
||||
|
||||
return $url;
|
||||
return new moodle_url($this->auth_url(), $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of name value pairs - build a valid HTTP POST application/x-www-form-urlencoded string.
|
||||
*
|
||||
* @param array $params Name / value pairs.
|
||||
* @return string POST data.
|
||||
*/
|
||||
public function build_post_data($params) {
|
||||
$result = [];
|
||||
foreach ($params as $name => $value) {
|
||||
$result[] = str_replace('&', '%26', $name) . '=' . str_replace('&', '%26', $value);
|
||||
}
|
||||
return implode('&', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -490,10 +537,10 @@ abstract class oauth2_client extends curl {
|
||||
*/
|
||||
public function upgrade_token($code) {
|
||||
$callbackurl = self::callback_url();
|
||||
$params = array('client_id' => $this->clientid,
|
||||
$params = array('code' => $code,
|
||||
'client_id' => $this->clientid,
|
||||
'client_secret' => $this->clientsecret,
|
||||
'grant_type' => 'authorization_code',
|
||||
'code' => $code,
|
||||
'redirect_uri' => $callbackurl->out(false),
|
||||
);
|
||||
|
||||
@@ -501,7 +548,7 @@ abstract class oauth2_client extends curl {
|
||||
if ($this->use_http_get()) {
|
||||
$response = $this->get($this->token_url(), $params);
|
||||
} else {
|
||||
$response = $this->post($this->token_url(), $params);
|
||||
$response = $this->post($this->token_url(), $this->build_post_data($params));
|
||||
}
|
||||
|
||||
if (!$this->info['http_code'] === 200) {
|
||||
@@ -510,10 +557,18 @@ 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;
|
||||
}
|
||||
|
||||
if (isset($r->refresh_token)) {
|
||||
$this->refreshtoken = $r->refresh_token;
|
||||
}
|
||||
|
||||
// Store the token an expiry time.
|
||||
$accesstoken = new stdClass;
|
||||
$accesstoken->token = $r->access_token;
|
||||
@@ -521,6 +576,9 @@ abstract class oauth2_client extends curl {
|
||||
// Expires 10 seconds before actual expiry.
|
||||
$accesstoken->expires = (time() + ($r->expires_in - 10));
|
||||
}
|
||||
$accesstoken->scope = $this->scope;
|
||||
// Also add the scopes.
|
||||
self::$upgradedcodes[] = $code;
|
||||
$this->store_token($accesstoken);
|
||||
|
||||
return true;
|
||||
@@ -552,7 +610,11 @@ abstract class oauth2_client extends curl {
|
||||
}
|
||||
}
|
||||
|
||||
return parent::request($murl->out(false), $options);
|
||||
$response = parent::request($murl->out(false), $options);
|
||||
|
||||
$this->resetHeader();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -603,6 +665,15 @@ abstract class oauth2_client extends curl {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a refresh token!!!
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_refresh_token() {
|
||||
return $this->refreshtoken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a token stored.
|
||||
*
|
||||
|
||||
@@ -148,9 +148,9 @@
|
||||
{{#identityproviders}}
|
||||
<div class="potentialidp">
|
||||
<a href="{{url}}" title={{#quote}}{{name}}{{/quote}}>
|
||||
{{#icon}}
|
||||
{{>core/pix_icon}}
|
||||
{{/icon}}
|
||||
{{#iconurl}}
|
||||
<img src="{{iconurl}}" alt="" width="24" height="24"/>
|
||||
{{/iconurl}}
|
||||
{{name}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Tests for oauth2 apis (\core\oauth2\*).
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Tests for oauth2 apis (\core\oauth2\*).
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
|
||||
*/
|
||||
class core_oauth2_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Tests the crud operations on oauth2 issuers.
|
||||
*/
|
||||
public function test_create_and_delete_standard_issuers() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
\core\oauth2\api::create_standard_issuer('google');
|
||||
\core\oauth2\api::create_standard_issuer('facebook');
|
||||
\core\oauth2\api::create_standard_issuer('microsoft');
|
||||
|
||||
$issuers = \core\oauth2\api::get_all_issuers();
|
||||
|
||||
$this->assertEquals($issuers[0]->get('name'), 'Google');
|
||||
$this->assertEquals($issuers[1]->get('name'), 'Facebook');
|
||||
$this->assertEquals($issuers[2]->get('name'), 'Microsoft');
|
||||
|
||||
\core\oauth2\api::move_down_issuer($issuers[0]->get('id'));
|
||||
|
||||
$issuers = \core\oauth2\api::get_all_issuers();
|
||||
|
||||
$this->assertEquals($issuers[0]->get('name'), 'Facebook');
|
||||
$this->assertEquals($issuers[1]->get('name'), 'Google');
|
||||
$this->assertEquals($issuers[2]->get('name'), 'Microsoft');
|
||||
|
||||
\core\oauth2\api::delete_issuer($issuers[1]->get('id'));
|
||||
|
||||
$issuers = \core\oauth2\api::get_all_issuers();
|
||||
|
||||
$this->assertEquals($issuers[0]->get('name'), 'Facebook');
|
||||
$this->assertEquals($issuers[1]->get('name'), 'Microsoft');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests we can list and delete each of the persistents related to an issuer.
|
||||
*/
|
||||
public function test_getters() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$issuer = \core\oauth2\api::create_standard_issuer('microsoft');
|
||||
|
||||
$same = \core\oauth2\api::get_issuer($issuer->get('id'));
|
||||
|
||||
foreach ($same->properties_definition() as $name => $def) {
|
||||
$this->assertTrue($issuer->get($name) == $same->get($name));
|
||||
}
|
||||
|
||||
$endpoints = \core\oauth2\api::get_endpoints($issuer);
|
||||
$same = \core\oauth2\api::get_endpoint($endpoints[0]->get('id'));
|
||||
$this->assertEquals($endpoints[0]->get('id'), $same->get('id'));
|
||||
$this->assertEquals($endpoints[0]->get('name'), $same->get('name'));
|
||||
|
||||
$todelete = $endpoints[0];
|
||||
\core\oauth2\api::delete_endpoint($todelete->get('id'));
|
||||
$endpoints = \core\oauth2\api::get_endpoints($issuer);
|
||||
$this->assertNotEquals($endpoints[0]->get('id'), $todelete->get('id'));
|
||||
|
||||
$userfields = \core\oauth2\api::get_user_field_mappings($issuer);
|
||||
$same = \core\oauth2\api::get_user_field_mapping($userfields[0]->get('id'));
|
||||
$this->assertEquals($userfields[0]->get('id'), $same->get('id'));
|
||||
|
||||
$todelete = $userfields[0];
|
||||
\core\oauth2\api::delete_user_field_mapping($todelete->get('id'));
|
||||
$userfields = \core\oauth2\api::get_user_field_mappings($issuer);
|
||||
$this->assertNotEquals($userfields[0]->get('id'), $todelete->get('id'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests we can get a logged in oauth client for a system account.
|
||||
*/
|
||||
public function test_get_system_oauth_client() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$issuer = \core\oauth2\api::create_standard_issuer('microsoft');
|
||||
|
||||
$requiredscopes = \core\oauth2\api::get_system_scopes_for_issuer($issuer);
|
||||
// Fake a system account.
|
||||
$data = (object) [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'refreshtoken' => 'abc',
|
||||
'grantedscopes' => $requiredscopes,
|
||||
'email' => '[email protected]',
|
||||
'username' => 'sys'
|
||||
];
|
||||
$sys = new \core\oauth2\system_account(0, $data);
|
||||
$sys->create();
|
||||
|
||||
// Fake a response with an access token.
|
||||
$response = json_encode(
|
||||
(object) [
|
||||
'access_token' => 'fdas...',
|
||||
'token_type' => 'Bearer',
|
||||
'expires_in' => '3600',
|
||||
'id_token' => 'llfsd..',
|
||||
]
|
||||
);
|
||||
curl::mock_response($response);
|
||||
$client = \core\oauth2\api::get_system_oauth_client($issuer);
|
||||
$this->assertTrue($client->is_logged_in());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests we can enable and disable an issuer.
|
||||
*/
|
||||
public function test_enable_disable_issuer() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$issuer = \core\oauth2\api::create_standard_issuer('microsoft');
|
||||
|
||||
$issuerid = $issuer->get('id');
|
||||
|
||||
\core\oauth2\api::enable_issuer($issuerid);
|
||||
$check = \core\oauth2\api::get_issuer($issuer->get('id'));
|
||||
$this->assertTrue((boolean)$check->get('enabled'));
|
||||
|
||||
\core\oauth2\api::enable_issuer($issuerid);
|
||||
$check = \core\oauth2\api::get_issuer($issuer->get('id'));
|
||||
$this->assertTrue((boolean)$check->get('enabled'));
|
||||
|
||||
\core\oauth2\api::disable_issuer($issuerid);
|
||||
$check = \core\oauth2\api::get_issuer($issuer->get('id'));
|
||||
$this->assertFalse((boolean)$check->get('enabled'));
|
||||
|
||||
\core\oauth2\api::enable_issuer($issuerid);
|
||||
$check = \core\oauth2\api::get_issuer($issuer->get('id'));
|
||||
$this->assertTrue((boolean)$check->get('enabled'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the alloweddomains for an issuer.
|
||||
*/
|
||||
public function test_issuer_alloweddomains() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$issuer = \core\oauth2\api::create_standard_issuer('microsoft');
|
||||
|
||||
$issuer->set('alloweddomains', '');
|
||||
|
||||
// Anything is allowed when domain is empty.
|
||||
$this->assertTrue($issuer->is_valid_login_domain(''));
|
||||
$this->assertTrue($issuer->is_valid_login_domain('a@b'));
|
||||
$this->assertTrue($issuer->is_valid_login_domain('[email protected]'));
|
||||
|
||||
$issuer->set('alloweddomains', 'example.com');
|
||||
|
||||
// One domain - must match exactly - no substrings etc.
|
||||
$this->assertFalse($issuer->is_valid_login_domain(''));
|
||||
$this->assertFalse($issuer->is_valid_login_domain('a@b'));
|
||||
$this->assertFalse($issuer->is_valid_login_domain('longer.example@example'));
|
||||
$this->assertTrue($issuer->is_valid_login_domain('[email protected]'));
|
||||
|
||||
$issuer->set('alloweddomains', 'example.com,example.net');
|
||||
// Multiple domains - must match any exactly - no substrings etc.
|
||||
$this->assertFalse($issuer->is_valid_login_domain(''));
|
||||
$this->assertFalse($issuer->is_valid_login_domain('a@b'));
|
||||
$this->assertFalse($issuer->is_valid_login_domain('longer.example@example'));
|
||||
$this->assertFalse($issuer->is_valid_login_domain('invalid@[email protected]'));
|
||||
$this->assertTrue($issuer->is_valid_login_domain('[email protected]'));
|
||||
$this->assertTrue($issuer->is_valid_login_domain('[email protected]'));
|
||||
|
||||
$issuer->set('alloweddomains', '*.example.com');
|
||||
// Wildcard.
|
||||
$this->assertFalse($issuer->is_valid_login_domain(''));
|
||||
$this->assertFalse($issuer->is_valid_login_domain('a@b'));
|
||||
$this->assertFalse($issuer->is_valid_login_domain('longer.example@example'));
|
||||
$this->assertFalse($issuer->is_valid_login_domain('[email protected]'));
|
||||
$this->assertTrue($issuer->is_valid_login_domain('[email protected]'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
This files describes API changes in core libraries and APIs,
|
||||
information provided here is intended especially for developers.
|
||||
=== 3.3 ===
|
||||
* The information returned by the idp list has changed. This is usually only rendered by the login page and login block.
|
||||
The icon attribute is removed and an iconurl attribute has been added.
|
||||
* Support added for a new type of external file: FILE_CONTROLLED_LINK. This is an external file that Moodle can control
|
||||
the permissions. Moodle makes files read-only but can grant temporary write access.
|
||||
When accessing a URL, the info from file_browser::get_file_info will be checked to determine if the user has write access,
|
||||
if they do - the remote file will have access controls set to allow editing.
|
||||
* The method moodleform::after_definition() has been added and can now be used to add some logic
|
||||
to be performed after the form's definition was set. This is useful for intermediate subclasses.
|
||||
* Moodle has support for font-awesome icons. Plugins should use the xxx_get_fontawesome_icon_map callback
|
||||
|
||||
@@ -580,17 +580,30 @@ abstract class assign_plugin {
|
||||
public function get_file_info($browser, $filearea, $itemid, $filepath, $filename) {
|
||||
global $CFG, $DB, $USER;
|
||||
$urlbase = $CFG->wwwroot.'/pluginfile.php';
|
||||
|
||||
$writeaccess = false;
|
||||
// Permission check on the itemid.
|
||||
$assignment = $this->assignment;
|
||||
|
||||
if ($this->get_subtype() == 'assignsubmission') {
|
||||
if ($itemid) {
|
||||
$record = $DB->get_record('assign_submission', array('id'=>$itemid), 'userid', IGNORE_MISSING);
|
||||
$record = $DB->get_record('assign_submission', array('id' => $itemid), 'userid,groupid', IGNORE_MISSING);
|
||||
if (!$record) {
|
||||
return null;
|
||||
}
|
||||
if (!$this->assignment->can_view_submission($record->userid)) {
|
||||
return null;
|
||||
if (!empty($record->userid)) {
|
||||
if (!$assignment->can_view_submission($record->userid)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// We only report write access for teachers.
|
||||
$writeaccess = $assignment->can_grade() && $assignment->can_edit_submission($record->userid);
|
||||
} else {
|
||||
// Must be a team submission with a group.
|
||||
if (!$assignment->can_view_group_submission($record->groupid)) {
|
||||
return null;
|
||||
}
|
||||
// We only report write access for teachers.
|
||||
$writeaccess = $assignment->can_grade() && $assignment->can_edit_group_submission($record->groupid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -601,7 +614,7 @@ abstract class assign_plugin {
|
||||
$fs = get_file_storage();
|
||||
$filepath = is_null($filepath) ? '/' : $filepath;
|
||||
$filename = is_null($filename) ? '.' : $filename;
|
||||
if (!($storedfile = $fs->get_file($this->assignment->get_context()->id,
|
||||
if (!($storedfile = $fs->get_file($assignment->get_context()->id,
|
||||
$this->get_subtype() . '_' . $this->get_type(),
|
||||
$filearea,
|
||||
$itemid,
|
||||
@@ -609,14 +622,15 @@ abstract class assign_plugin {
|
||||
$filename))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new file_info_stored($browser,
|
||||
$this->assignment->get_context(),
|
||||
$assignment->get_context(),
|
||||
$storedfile,
|
||||
$urlbase,
|
||||
$filearea,
|
||||
$itemid,
|
||||
true,
|
||||
true,
|
||||
$writeaccess,
|
||||
false);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,6 +155,7 @@ $string['submissionmodifiedgroup'] = 'The submission has been modified by somebo
|
||||
$string['duedatereached'] = 'The due date for this assignment has now passed';
|
||||
$string['duedatevalidation'] = 'Due date must be after the allow submissions from date.';
|
||||
$string['editattemptfeedback'] = 'Edit the grade and feedback for attempt number {$a}.';
|
||||
$string['editonline'] = 'Edit online';
|
||||
$string['editingpreviousfeedbackwarning'] = 'You are editing the feedback for a previous attempt. This is attempt {$a->attemptnumber} out of {$a->totalattempts}.';
|
||||
$string['editoverride'] = 'Edit override';
|
||||
$string['editsubmission'] = 'Edit submission';
|
||||
|
||||
@@ -4360,6 +4360,25 @@ class assign {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an access check to see if the current $USER can edit this group submission.
|
||||
*
|
||||
* @param int $groupid
|
||||
* @return bool
|
||||
*/
|
||||
public function can_edit_group_submission($groupid) {
|
||||
global $USER;
|
||||
|
||||
$members = $this->get_submission_group_members($groupid, true);
|
||||
foreach ($members as $member) {
|
||||
// If we can edit any members submission, we can edit the submission for the group.
|
||||
if ($this->can_edit_submission($member->id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an access check to see if the current $USER can view this group submission.
|
||||
*
|
||||
|
||||
@@ -911,6 +911,7 @@ class assign_files implements renderable {
|
||||
*/
|
||||
public function preprocess($dir, $filearea, $component) {
|
||||
global $CFG;
|
||||
|
||||
foreach ($dir['subdirs'] as $subdir) {
|
||||
$this->preprocess($subdir, $filearea, $component);
|
||||
}
|
||||
|
||||
@@ -1420,7 +1420,7 @@ class mod_assign_renderer extends plugin_renderer_base {
|
||||
$result .= '<li yuiConfig=\'' . json_encode($yuiconfig) . '\'>' .
|
||||
'<div>' . $image . ' ' .
|
||||
$file->fileurl . ' ' .
|
||||
$plagiarismlinks .
|
||||
$plagiarismlinks . ' ' .
|
||||
$file->portfoliobutton . '</div>' .
|
||||
'</li>';
|
||||
}
|
||||
|
||||
@@ -125,11 +125,11 @@ class assign_submission_file extends assign_submission_plugin {
|
||||
* @return array
|
||||
*/
|
||||
private function get_file_options() {
|
||||
$fileoptions = array('subdirs'=>1,
|
||||
'maxbytes'=>$this->get_config('maxsubmissionsizebytes'),
|
||||
'maxfiles'=>$this->get_config('maxfilesubmissions'),
|
||||
'accepted_types'=>'*',
|
||||
'return_types'=>FILE_INTERNAL);
|
||||
$fileoptions = array('subdirs' => 1,
|
||||
'maxbytes' => $this->get_config('maxsubmissionsizebytes'),
|
||||
'maxfiles' => $this->get_config('maxfilesubmissions'),
|
||||
'accepted_types' => '*',
|
||||
'return_types' => (FILE_INTERNAL | FILE_CONTROLLED_LINK));
|
||||
if ($fileoptions['maxbytes'] == 0) {
|
||||
// Use module default.
|
||||
$fileoptions['maxbytes'] = get_config('assignsubmission_file', 'maxbytes');
|
||||
@@ -174,7 +174,6 @@ class assign_submission_file extends assign_submission_plugin {
|
||||
* @return int
|
||||
*/
|
||||
private function count_files($submissionid, $area) {
|
||||
|
||||
$fs = get_file_storage();
|
||||
$files = $fs->get_area_files($this->assignment->get_context()->id,
|
||||
'assignsubmission_file',
|
||||
|
||||
@@ -174,7 +174,7 @@ class assign_submission_onlinetext extends assign_submission_plugin {
|
||||
'maxfiles' => EDITOR_UNLIMITED_FILES,
|
||||
'maxbytes' => $this->assignment->get_course()->maxbytes,
|
||||
'context' => $this->assignment->get_context(),
|
||||
'return_types' => FILE_INTERNAL | FILE_EXTERNAL
|
||||
'return_types' => (FILE_INTERNAL | FILE_EXTERNAL | FILE_CONTROLLED_LINK)
|
||||
);
|
||||
return $editoroptions;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ class data_field_file extends data_field_base {
|
||||
$options->maxfiles = 1; // Limit to one file for the moment, this may be changed if requested as a feature in the future.
|
||||
$options->itemid = $itemid;
|
||||
$options->accepted_types = '*';
|
||||
$options->return_types = FILE_INTERNAL;
|
||||
$options->return_types = FILE_INTERNAL | FILE_CONTROLLED_LINK;
|
||||
$options->context = $PAGE->context;
|
||||
|
||||
$fm = new form_filemanager($options);
|
||||
|
||||
@@ -50,7 +50,7 @@ class mod_forum_post_form extends moodleform {
|
||||
'maxbytes' => $maxbytes,
|
||||
'maxfiles' => $forum->maxattachments,
|
||||
'accepted_types' => '*',
|
||||
'return_types' => FILE_INTERNAL
|
||||
'return_types' => FILE_INTERNAL | FILE_CONTROLLED_LINK
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -559,13 +559,14 @@ function forum_cron() {
|
||||
}
|
||||
}
|
||||
|
||||
$modcontext = context_module::instance($coursemodules[$forumid]->id);
|
||||
|
||||
// Save the Inbound Message datakey here to reduce DB queries later.
|
||||
$messageinboundgenerator->set_data($pid);
|
||||
$messageinboundhandlers[$pid] = $messageinboundgenerator->fetch_data_key();
|
||||
|
||||
// Caching subscribed users of each forum.
|
||||
if (!isset($subscribedusers[$forumid])) {
|
||||
$modcontext = context_module::instance($coursemodules[$forumid]->id);
|
||||
if ($subusers = \mod_forum\subscriptions::fetch_subscribed_users($forums[$forumid], 0, $modcontext, 'u.*', true)) {
|
||||
|
||||
foreach ($subusers as $postuser) {
|
||||
|
||||
@@ -83,7 +83,8 @@ $data = new stdClass();
|
||||
$data->returnurl = $returnurl;
|
||||
$data->subwikiid = $subwiki->id;
|
||||
$maxbytes = get_max_upload_file_size($CFG->maxbytes, $COURSE->maxbytes);
|
||||
$options = array('subdirs'=>0, 'maxbytes'=>$maxbytes, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL | FILE_REFERENCE);
|
||||
$types = FILE_INTERNAL | FILE_REFERENCE | FILE_CONTROLLED_LINK;
|
||||
$options = array('subdirs' => 0, 'maxbytes' => $maxbytes, 'maxfiles' => -1, 'accepted_types' => '*', 'return_types' => $types);
|
||||
file_prepare_standard_filemanager($data, 'files', $options, $context, 'mod_wiki', 'attachments', $subwiki->id);
|
||||
|
||||
$mform = new mod_wiki_filesedit_form(null, array('data'=>$data, 'options'=>$options));
|
||||
|
||||
@@ -2512,7 +2512,7 @@ class workshop {
|
||||
'subdirs' => true,
|
||||
'maxfiles' => $this->nattachments,
|
||||
'maxbytes' => $this->maxbytes,
|
||||
'return_types' => FILE_INTERNAL,
|
||||
'return_types' => FILE_INTERNAL | FILE_CONTROLLED_LINK,
|
||||
);
|
||||
|
||||
if ($acceptedtypes = self::normalize_file_extensions($this->submissionfiletypes)) {
|
||||
@@ -2554,7 +2554,7 @@ class workshop {
|
||||
'subdirs' => 1,
|
||||
'maxbytes' => $this->overallfeedbackmaxbytes,
|
||||
'maxfiles' => $this->overallfeedbackfiles,
|
||||
'return_types' => FILE_INTERNAL,
|
||||
'return_types' => FILE_INTERNAL | FILE_CONTROLLED_LINK,
|
||||
);
|
||||
|
||||
if ($acceptedtypes = self::normalize_file_extensions($this->overallfeedbackfiletypes)) {
|
||||
|
||||
+4
-1
@@ -33,5 +33,8 @@ require_once('lib/filelib.php');
|
||||
$relativepath = get_file_argument();
|
||||
$forcedownload = optional_param('forcedownload', 0, PARAM_BOOL);
|
||||
$preview = optional_param('preview', null, PARAM_ALPHANUM);
|
||||
// Offline means download the file from the repository and serve it, even if it was an external link.
|
||||
// The repository may have to export the file to an offline format.
|
||||
$offline = optional_param('offline', 0, PARAM_BOOL);
|
||||
|
||||
file_pluginfile($relativepath, $forcedownload, $preview);
|
||||
file_pluginfile($relativepath, $forcedownload, $preview, $offline);
|
||||
|
||||
@@ -115,7 +115,7 @@ class qtype_essay_renderer extends qtype_renderer {
|
||||
$pickeroptions->itemid = $qa->prepare_response_files_draft_itemid(
|
||||
'attachments', $options->context->id);
|
||||
$pickeroptions->context = $options->context;
|
||||
$pickeroptions->return_types = FILE_INTERNAL;
|
||||
$pickeroptions->return_types = FILE_INTERNAL | FILE_CONTROLLED_LINK;
|
||||
|
||||
$pickeroptions->itemid = $qa->prepare_response_files_draft_itemid(
|
||||
'attachments', $options->context->id);
|
||||
|
||||
@@ -106,6 +106,7 @@ class repository_areafiles extends repository {
|
||||
'author' => $file->get_author(),
|
||||
'license' => $file->get_license(),
|
||||
'isref' => $file->is_external_file(),
|
||||
'iscontrolledlink' => $file->is_controlled_link(),
|
||||
'icon' => $OUTPUT->image_url(file_file_icon($file, 24))->out(false),
|
||||
'thumbnail' => $OUTPUT->image_url(file_file_icon($file, 90))->out(false)
|
||||
);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
* Active repository options
|
||||
* =====
|
||||
* this.active_repo.id
|
||||
* this.active_repo.defaultreturntype
|
||||
* this.active_repo.nosearch
|
||||
* this.active_repo.norefresh
|
||||
* this.active_repo.nologin
|
||||
@@ -895,6 +896,9 @@ M.core_filepicker.init = function(Y, options) {
|
||||
if (node.isref) {
|
||||
classname = classname + ' fp-isreference';
|
||||
}
|
||||
if (node.iscontrolledlink) {
|
||||
classname = classname + ' fp-iscontrolledlink';
|
||||
}
|
||||
if (node.refcount) {
|
||||
classname = classname + ' fp-hasreferences';
|
||||
}
|
||||
@@ -1080,7 +1084,7 @@ M.core_filepicker.init = function(Y, options) {
|
||||
selectnode.one('.fp-thumbnail').setContent('').appendChild(imgnode);
|
||||
|
||||
// filelink is the array of file-link-types available for this repository in this env
|
||||
var filelinktypes = [2/*FILE_INTERNAL*/,1/*FILE_EXTERNAL*/,4/*FILE_REFERENCE*/];
|
||||
var filelinktypes = [2/*FILE_INTERNAL*/,1/*FILE_EXTERNAL*/,4/*FILE_REFERENCE*/,8/*FILE_CONTROLLED_LINK*/];
|
||||
var filelink = {}, firstfilelink = null, filelinkcount = 0;
|
||||
for (var i in filelinktypes) {
|
||||
var allowed = (return_types & filelinktypes[i]) &&
|
||||
@@ -1094,6 +1098,12 @@ M.core_filepicker.init = function(Y, options) {
|
||||
firstfilelink = (firstfilelink==null && allowed) ? filelinktypes[i] : firstfilelink;
|
||||
filelinkcount += allowed ? 1 : 0;
|
||||
}
|
||||
var defaultreturntype = this.options.repositories[this.active_repo.id].defaultreturntype;
|
||||
if (defaultreturntype) {
|
||||
if (filelink[defaultreturntype]) {
|
||||
firstfilelink = defaultreturntype;
|
||||
}
|
||||
}
|
||||
// make radio buttons enabled if this file-link-type is available and only if there are more than one file-link-type option
|
||||
// check the first available file-link-type option
|
||||
for (var linktype in filelink) {
|
||||
@@ -1122,12 +1132,13 @@ M.core_filepicker.init = function(Y, options) {
|
||||
var selectnode = this.selectnode;
|
||||
var getfile = selectnode.one('.fp-select-confirm');
|
||||
// bind labels with corresponding inputs
|
||||
selectnode.all('.fp-saveas,.fp-linktype-2,.fp-linktype-1,.fp-linktype-4,.fp-setauthor,.fp-setlicense').each(function (node) {
|
||||
selectnode.all('.fp-saveas,.fp-linktype-2,.fp-linktype-1,.fp-linktype-4,fp-linktype-8,.fp-setauthor,.fp-setlicense').each(function (node) {
|
||||
node.all('label').set('for', node.one('input,select').generateID());
|
||||
});
|
||||
selectnode.one('.fp-linktype-2 input').setAttrs({value: 2, name: 'linktype'});
|
||||
selectnode.one('.fp-linktype-1 input').setAttrs({value: 1, name: 'linktype'});
|
||||
selectnode.one('.fp-linktype-4 input').setAttrs({value: 4, name: 'linktype'});
|
||||
selectnode.one('.fp-linktype-8 input').setAttrs({value: 8, name: 'linktype'});
|
||||
var changelinktype = function(e) {
|
||||
if (e.currentTarget.get('checked')) {
|
||||
var allowinputs = e.currentTarget.get('value') != 1/*FILE_EXTERNAL*/;
|
||||
@@ -1137,7 +1148,7 @@ M.core_filepicker.init = function(Y, options) {
|
||||
});
|
||||
}
|
||||
};
|
||||
selectnode.all('.fp-linktype-2,.fp-linktype-1,.fp-linktype-4').each(function (node) {
|
||||
selectnode.all('.fp-linktype-2,.fp-linktype-1,.fp-linktype-4,.fp-linktype-8').each(function (node) {
|
||||
node.one('input').on('change', changelinktype, this);
|
||||
});
|
||||
this.populate_licenses_select(selectnode.one('.fp-setlicense select'));
|
||||
@@ -1175,6 +1186,10 @@ M.core_filepicker.init = function(Y, options) {
|
||||
(this.options.return_types & 4/*FILE_REFERENCE*/) &&
|
||||
selectnode.one('.fp-linktype-4 input').get('checked')) {
|
||||
params['usefilereference'] = '1';
|
||||
} else if ((return_types & 8/*FILE_CONTROLLED_LINK*/) &&
|
||||
(this.options.return_types & 8/*FILE_CONTROLLED_LINK*/) &&
|
||||
selectnode.one('.fp-linktype-8 input').get('checked')) {
|
||||
params['usecontrolledlink'] = '1';
|
||||
}
|
||||
|
||||
selectnode.addClass('loading');
|
||||
@@ -1415,6 +1430,7 @@ M.core_filepicker.init = function(Y, options) {
|
||||
this.objecttag = data.object?data.object:null;
|
||||
this.active_repo = {};
|
||||
this.active_repo.issearchresult = data.issearchresult ? true : false;
|
||||
this.active_repo.defaultreturntype = data.defaultreturntype?data.defaultreturntype:null;
|
||||
this.active_repo.dynload = data.dynload?data.dynload:false;
|
||||
this.active_repo.pages = Number(data.pages?data.pages:null);
|
||||
this.active_repo.page = Number(data.page?data.page:null);
|
||||
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* Google Drive Rest API.
|
||||
*
|
||||
* @package repository_googledocs
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace repository_googledocs;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Google Drive Rest API.
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class rest extends \core\oauth2\rest {
|
||||
|
||||
/**
|
||||
* Define the functions of the rest API.
|
||||
*
|
||||
* @return array Example:
|
||||
* [ 'listFiles' => [ 'method' => 'get', 'endpoint' => 'http://...', 'args' => [ 'folder' => PARAM_STRING ] ] ]
|
||||
*/
|
||||
public function get_api_functions() {
|
||||
return [
|
||||
'list' => [
|
||||
'endpoint' => 'https://www.googleapis.com/drive/v3/files',
|
||||
'method' => 'get',
|
||||
'args' => [
|
||||
'corpus' => PARAM_RAW,
|
||||
'orderBy' => PARAM_RAW,
|
||||
'fields' => PARAM_RAW,
|
||||
'pageSize' => PARAM_INT,
|
||||
'pageToken' => PARAM_RAW,
|
||||
'q' => PARAM_RAW,
|
||||
'spaces' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'get' => [
|
||||
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}',
|
||||
'method' => 'get',
|
||||
'args' => [
|
||||
'fields' => PARAM_RAW,
|
||||
'fileid' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'copy' => [
|
||||
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}/copy',
|
||||
'method' => 'post',
|
||||
'args' => [
|
||||
'fields' => PARAM_RAW,
|
||||
'fileid' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'delete' => [
|
||||
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}',
|
||||
'method' => 'delete',
|
||||
'args' => [
|
||||
'fileid' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'create' => [
|
||||
'endpoint' => 'https://www.googleapis.com/drive/v3/files',
|
||||
'method' => 'post',
|
||||
'args' => [
|
||||
'fields' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'update' => [
|
||||
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}',
|
||||
'method' => 'patch',
|
||||
'args' => [
|
||||
'fileid' => PARAM_RAW,
|
||||
'fields' => PARAM_RAW,
|
||||
'addParents' => PARAM_RAW,
|
||||
'removeParents' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'create_permission' => [
|
||||
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}/permissions',
|
||||
'method' => 'post',
|
||||
'args' => [
|
||||
'fileid' => PARAM_RAW,
|
||||
'emailMessage' => PARAM_RAW,
|
||||
'sendNotificationEmail' => PARAM_RAW,
|
||||
'transferOwnership' => PARAM_RAW,
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'update_permission' => [
|
||||
'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}/permissions/{permissionid}',
|
||||
'method' => 'patch',
|
||||
'args' => [
|
||||
'fileid' => PARAM_RAW,
|
||||
'permissionid' => PARAM_RAW,
|
||||
'emailMessage' => PARAM_RAW,
|
||||
'sendNotificationEmail' => PARAM_RAW,
|
||||
'transferOwnership' => PARAM_RAW,
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Googledocs repository cache definitions.
|
||||
*
|
||||
* This file is part of Moodle's cache API, affectionately called MUC.
|
||||
* It contains the components that are requried in order to use caching.
|
||||
*
|
||||
* @package repository_googledocs
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$definitions = array(
|
||||
|
||||
// Used to store file ids for folders.
|
||||
// The keys used are full path to the folder, the values are the id in google drive.
|
||||
// The static acceleration size has been based upon the depths of a single path.
|
||||
'folder' => array(
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'simplekeys' => false,
|
||||
'simpledata' => true,
|
||||
'staticacceleration' => true,
|
||||
'staticaccelerationsize' => 10,
|
||||
'canuselocalstore' => true
|
||||
),
|
||||
);
|
||||
@@ -48,6 +48,27 @@ function xmldb_repository_googledocs_upgrade($oldversion) {
|
||||
// Plugin savepoint reached.
|
||||
upgrade_plugin_savepoint(true, 2017011100, 'repository', 'googledocs');
|
||||
}
|
||||
if ($oldversion < 2017030500) {
|
||||
$clientid = get_config('clientid', 'googledocs');
|
||||
$secret = get_config('secret', 'googledocs');
|
||||
|
||||
// Update from repo config to use an OAuth service.
|
||||
if (!empty($clientid) && !empty($secret)) {
|
||||
$issuer = \core\oauth2\api::create_standard_issuer('google');
|
||||
|
||||
$issuer->set('clientid', $clientid);
|
||||
$issuer->set('secret', $secret);
|
||||
|
||||
$issuer->update();
|
||||
|
||||
set_config('issuerid', $issuer->get('id'), 'googledocs');
|
||||
}
|
||||
upgrade_plugin_savepoint(true, 2017030500, 'repository', 'googledocs');
|
||||
}
|
||||
if ($oldversion < 2017030600) {
|
||||
set_config('supportedfiles', 'both', 'googledocs');
|
||||
upgrade_plugin_savepoint(true, 2017030600, 'repository', 'googledocs');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -22,15 +22,29 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['clientid'] = 'Client ID';
|
||||
$string['configplugin'] = 'Configure Google Drive plugin';
|
||||
$string['docsformat'] = 'Default document import format';
|
||||
$string['drawingformat'] = 'Default drawing import format';
|
||||
$string['googledocs:view'] = 'View Google Drive repository';
|
||||
$string['importformat'] = 'Configure the default import formats from google';
|
||||
$string['oauthinfo'] = '<p>To use this plugin, you must register your site with Google, as described in the documentation <a href="{$a->docsurl}">Google OAuth 2.0 setup</a>.</p><p>As part of the registration process, you will need to enter the following URL as \'Authorized Redirect URIs\':</p><p>{$a->callbackurl}</p><p>Once registered, you will be provided with a client ID and secret which can be used to configure all Google Drive and Picasa plugins.</p><p>Please also note that you will have to enable the service \'Drive API\'.</p>';
|
||||
$string['pluginname'] = 'Google Drive';
|
||||
$string['presentationformat'] = 'Default presentation import format';
|
||||
$string['secret'] = 'Secret';
|
||||
$string['servicenotenabled'] = 'Access not configured. Make sure the service \'Drive API\' is enabled.';
|
||||
$string['spreadsheetformat'] = 'Default spreadsheet import format';
|
||||
$string['issuer'] = 'OAuth 2 service';
|
||||
$string['issuer_help'] = 'Select the OAuth 2 service that is configured to talk to the Google Drive API. If the services does not exist yet, you might need to create it.';
|
||||
$string['servicenotenabled'] = 'Access not configured. Make sure the service \'Drive API\' is enabled.';
|
||||
$string['oauth2serviceslink'] = '<a href="{$a}" title="Link to OAuth Services configuration">OAuth 2 Services Configuration</a>';
|
||||
$string['searchfor'] = 'Search for {$a}';
|
||||
$string['internal'] = 'Internal (files stored in Moodle)';
|
||||
$string['external'] = 'External (only links stored in Moodle)';
|
||||
$string['both'] = 'Internal and External';
|
||||
$string['supportedreturntypes'] = 'Supported files';
|
||||
$string['defaultreturntype'] = 'Default return type';
|
||||
$string['fileoptions'] = 'The types and defaults for returned files is configurable here. Note that all files linked externally will be updated so that the owner is the Moodle system account.';
|
||||
$string['owner'] = 'Owned by: {$a}';
|
||||
$string['cachedef_folder'] = 'Google File IDs for folders in the system account';
|
||||
|
||||
// Deprecated since Moodle 3.3.
|
||||
$string['oauthinfo'] = '<p>To use this plugin, you must register your site with Google, as described in the documentation <a href="{$a->docsurl}">Google OAuth 2.0 setup</a>.</p><p>As part of the registration process, you will need to enter the following URL as \'Authorized Redirect URIs\':</p><p>{$a->callbackurl}</p><p>Once registered, you will be provided with a client ID and secret which can be used to configure all Google Drive and Picasa plugins.</p><p>Please also note that you will have to enable the service \'Drive API\'.</p>';
|
||||
$string['secret'] = 'Secret';
|
||||
$string['clientid'] = 'Client ID';
|
||||
|
||||
+691
-171
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use \core\oauth2\issuer;
|
||||
use \core\oauth2\endpoint;
|
||||
|
||||
/**
|
||||
* Google Docs repository data generator class
|
||||
*
|
||||
@@ -41,11 +44,33 @@ class repository_googledocs_generator extends testing_repository_generator {
|
||||
*/
|
||||
protected function prepare_type_record(array $record) {
|
||||
$record = parent::prepare_type_record($record);
|
||||
if (!isset($record['clientid'])) {
|
||||
$record['clientid'] = 'clientid';
|
||||
$issuerrecord = (object) [
|
||||
'name' => 'Google',
|
||||
'image' => 'https://accounts.google.com/favicon.ico',
|
||||
'baseurl' => 'http://accounts.google.com/',
|
||||
'loginparamsoffline' => 'access_type=offline&prompt=consent',
|
||||
'showonloginpage' => true
|
||||
];
|
||||
|
||||
$issuer = new issuer(0, $issuerrecord);
|
||||
$issuer->create();
|
||||
|
||||
$endpointrecord = (object) [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'name' => 'discovery_endpoint',
|
||||
'url' => 'https://accounts.google.com/.well-known/openid-configuration'
|
||||
];
|
||||
$endpoint = new endpoint(0, $endpointrecord);
|
||||
$endpoint->create();
|
||||
|
||||
if (!isset($record['issuerid'])) {
|
||||
$record['issuerid'] = $issuer->get('id');
|
||||
}
|
||||
if (!isset($record['secret'])) {
|
||||
$record['secret'] = 'secret';
|
||||
if (!isset($record['defaultreturntype'])) {
|
||||
$record['defaultreturntype'] = FILE_INTERNAL;
|
||||
}
|
||||
if (!isset($record['supportedreturntypes'])) {
|
||||
$record['supportedreturntypes'] = 'both';
|
||||
}
|
||||
if (!isset($record['documentformat'])) {
|
||||
$record['documentformat'] = 'pdf';
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017011100; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2017031001; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2016112900; // Requires this Moodle version.
|
||||
$plugin->component = 'repository_googledocs'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
+37
-1
@@ -30,6 +30,8 @@ require_once($CFG->libdir . '/formslib.php');
|
||||
define('FILE_EXTERNAL', 1);
|
||||
define('FILE_INTERNAL', 2);
|
||||
define('FILE_REFERENCE', 4);
|
||||
define('FILE_CONTROLLED_LINK', 8);
|
||||
|
||||
define('RENAME_SUFFIX', '_2');
|
||||
|
||||
/**
|
||||
@@ -1000,7 +1002,7 @@ abstract class repository implements cacheable_object {
|
||||
* onlyvisible : bool (default true)
|
||||
* type : string return instances of this type only
|
||||
* accepted_types : string|array return instances that contain files of those types (*, web_image, .pdf, ...)
|
||||
* return_types : int combination of FILE_INTERNAL & FILE_EXTERNAL & FILE_REFERENCE.
|
||||
* return_types : int combination of FILE_INTERNAL & FILE_EXTERNAL & FILE_REFERENCE & FILE_CONTROLLED_LINK.
|
||||
* 0 means every type. The default is FILE_INTERNAL | FILE_EXTERNAL.
|
||||
* userid : int if specified, instances belonging to other users will not be returned
|
||||
*
|
||||
@@ -1281,6 +1283,28 @@ abstract class repository implements cacheable_object {
|
||||
public function cache_file_by_reference($reference, $storedfile) {
|
||||
}
|
||||
|
||||
/**
|
||||
* reference_file_selected
|
||||
*
|
||||
* This function is called when a controlled link file is selected in a file picker and the form is
|
||||
* saved. The expected behaviour for repositories supporting controlled links is to
|
||||
* - copy the file to the moodle system account
|
||||
* - put it in a folder that reflects the context it is being used
|
||||
* - make sure the sharing permissions are correct (read-only with the link)
|
||||
* - return a new reference string pointing to the newly copied file.
|
||||
*
|
||||
* @param string $reference this reference is generated by
|
||||
* repository::get_file_reference()
|
||||
* @param context $context the target context for this new file.
|
||||
* @param string $component the target component for this new file.
|
||||
* @param string $filearea the target filearea for this new file.
|
||||
* @param string $itemid the target itemid for this new file.
|
||||
* @return string updated reference (final one before it's saved to db).
|
||||
*/
|
||||
public function reference_file_selected($reference, $context, $component, $filearea, $itemid) {
|
||||
return $reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the source information
|
||||
*
|
||||
@@ -1890,6 +1914,17 @@ abstract class repository implements cacheable_object {
|
||||
return (FILE_INTERNAL | FILE_EXTERNAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells how the file can be picked from this repository
|
||||
*
|
||||
* Maximum value is FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function default_returntype() {
|
||||
return FILE_INTERNAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide repository instance information for Ajax
|
||||
*
|
||||
@@ -1904,6 +1939,7 @@ abstract class repository implements cacheable_object {
|
||||
$meta->icon = $OUTPUT->image_url('icon', 'repository_'.$meta->type)->out(false);
|
||||
$meta->supported_types = file_get_typegroup('extension', $this->supported_filetypes());
|
||||
$meta->return_types = $this->supported_returntypes();
|
||||
$meta->defaultreturntype = $this->default_returntype();
|
||||
$meta->sortorder = $this->options['sortorder'];
|
||||
return $meta;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<?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 access records from the DB.
|
||||
*
|
||||
* @package repository_onedrive
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace repository_onedrive;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\persistent;
|
||||
|
||||
/**
|
||||
* Class for loading/storing issuer from the DB
|
||||
*
|
||||
* @package repository_onedrive
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class access extends persistent {
|
||||
|
||||
const TABLE = 'repository_onedrive_access';
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return array(
|
||||
'permissionid' => array(
|
||||
'type' => PARAM_RAW
|
||||
),
|
||||
'itemid' => array(
|
||||
'type' => PARAM_RAW
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* A scheduled task.
|
||||
*
|
||||
* @package repository_onedrive
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace repository_onedrive;
|
||||
|
||||
use \core\task\scheduled_task;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Simple task to delete temporary permission records.
|
||||
* @package repository_onedrive
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class remove_temp_access_task extends scheduled_task {
|
||||
|
||||
/**
|
||||
* Get a descriptive name for this task (shown to admins).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return get_string('removetempaccesstask', 'repository_onedrive');
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the job.
|
||||
* Throw exceptions on errors (the job will be retried).
|
||||
*/
|
||||
public function execute() {
|
||||
$accessrecords = access::get_records();
|
||||
$expires = new DateTime();
|
||||
$expires->sub(new DateInterval("P7D"));
|
||||
$timestamp = $expires->getTimestamp();
|
||||
|
||||
$issuerid = get_config('repository_onedrive', 'issuerid');
|
||||
$issuer = \core\oauth2\api::get_issuer_by_id($issuerid);
|
||||
|
||||
// Add the current user as an OAuth writer.
|
||||
$systemauth = \core\oauth2\api::get_system_oauth_client($issuer);
|
||||
|
||||
if ($systemauth === false) {
|
||||
$details = 'Cannot connect as system user';
|
||||
throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details);
|
||||
}
|
||||
$systemservice = new repository_onedrive\rest($systemauth);
|
||||
|
||||
foreach ($accessrecords as $access) {
|
||||
if ($access->get('timemodified') < $timestamp) {
|
||||
$params = ['permissionid' => $access->get('permissionid'), 'itemid' => $access->get('itemid')];
|
||||
$systemservice->call('delete_permission', $params);
|
||||
$access->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Microsoft Graph API Rest Interface.
|
||||
*
|
||||
* @package repository_onedrive
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace repository_onedrive;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Microsoft Graph API Rest Interface.
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class rest extends \core\oauth2\rest {
|
||||
|
||||
/**
|
||||
* Define the functions of the rest API.
|
||||
*
|
||||
* @return array Example:
|
||||
* [ 'listFiles' => [ 'method' => 'get', 'endpoint' => 'http://...', 'args' => [ 'folder' => PARAM_STRING ] ] ]
|
||||
*/
|
||||
public function get_api_functions() {
|
||||
return [
|
||||
'list' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/{parent}/children',
|
||||
'method' => 'get',
|
||||
'args' => [
|
||||
'$select' => PARAM_RAW,
|
||||
'$expand' => PARAM_RAW,
|
||||
'parent' => PARAM_RAW,
|
||||
'$skip' => PARAM_INT,
|
||||
'$skipToken' => PARAM_RAW,
|
||||
'$count' => PARAM_INT
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'search' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/{parent}/search(q=\'{search}\')',
|
||||
'method' => 'get',
|
||||
'args' => [
|
||||
'search' => PARAM_NOTAGS,
|
||||
'$select' => PARAM_RAW,
|
||||
'parent' => PARAM_RAW,
|
||||
'$skip' => PARAM_INT,
|
||||
'$skipToken' => PARAM_RAW,
|
||||
'$count' => PARAM_INT
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'get' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{fileid}',
|
||||
'method' => 'get',
|
||||
'args' => [
|
||||
'fileid' => PARAM_RAW,
|
||||
'$select' => PARAM_RAW,
|
||||
'$expand' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'list_permissions' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{fileid}/permissions',
|
||||
'method' => 'get',
|
||||
'args' => [
|
||||
'$select' => PARAM_RAW,
|
||||
'$expand' => PARAM_RAW,
|
||||
'fileid' => PARAM_RAW,
|
||||
'$skip' => PARAM_INT,
|
||||
'$skipToken' => PARAM_RAW,
|
||||
'$count' => PARAM_INT
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'create_permission' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{fileid}/invite',
|
||||
'method' => 'post',
|
||||
'args' => [
|
||||
'fileid' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'get_file_by_path' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/root:/{fullpath}',
|
||||
'method' => 'get',
|
||||
'args' => [
|
||||
'fullpath' => PARAM_RAW,
|
||||
'$select' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'create_folder' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{parentid}/children',
|
||||
'method' => 'post',
|
||||
'args' => [
|
||||
'parentid' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'create_link' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{fileid}/createLink',
|
||||
'method' => 'post',
|
||||
'args' => [
|
||||
'fileid' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'get_drive' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive',
|
||||
'method' => 'get',
|
||||
'args' => [],
|
||||
'response' => 'json'
|
||||
],
|
||||
'delete_file_by_path' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/root:/{fullpath}',
|
||||
'method' => 'delete',
|
||||
'args' => [
|
||||
'fullpath' => PARAM_RAW,
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'copy_share' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/shares/{sharetoken}/root/copy',
|
||||
'method' => 'post',
|
||||
'args' => [
|
||||
'sharetoken' => PARAM_RAW,
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
'delete_permission' => [
|
||||
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{fileid}/permissions/{permissionid}',
|
||||
'method' => 'delete',
|
||||
'args' => [
|
||||
'fileid' => PARAM_RAW,
|
||||
'permissionid' => PARAM_RAW
|
||||
],
|
||||
'response' => 'json'
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Capability definitions for onedrive repository
|
||||
*
|
||||
* @package repository_onedrive
|
||||
* @copyright 2012 Lancaster University Network Services Ltd
|
||||
* @author Dan Poltawski <dan.poltawski@luns.net.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
$capabilities = array(
|
||||
'repository/onedrive:view' => array(
|
||||
'captype' => 'read',
|
||||
'contextlevel' => CONTEXT_MODULE,
|
||||
'archetypes' => array(
|
||||
'user' => CAP_ALLOW
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -0,0 +1,39 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Cache definitions.
|
||||
*
|
||||
* @package repository_onedrive
|
||||
* @copyright 2013 Dan Poltawski <dan@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$definitions = array(
|
||||
// Used to store file ids for folders.
|
||||
// The keys used are full path to the folder, the values are the id in office 365.
|
||||
// The static acceleration size has been based upon the depths of a single path.
|
||||
'folder' => array(
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'simplekeys' => false,
|
||||
'simpledata' => true,
|
||||
'staticacceleration' => true,
|
||||
'staticaccelerationsize' => 10,
|
||||
'canuselocalstore' => true
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="repository/onedrive/db" VERSION="20170314" COMMENT="XMLDB file for Moodle repository/onedrive"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
<TABLES>
|
||||
<TABLE NAME="repository_onedrive_access" COMMENT="List of temporary access grants.">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
|
||||
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
|
||||
<FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
|
||||
<FIELD NAME="permissionid" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The permission id in OneDrive."/>
|
||||
<FIELD NAME="itemid" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The item id in OneDrive."/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="usermodifiedkey" TYPE="foreign" FIELDS="usermodified" REFTABLE="user" REFFIELDS="id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
</XMLDB>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Definition of repository_onedrive scheduled tasks.
|
||||
*
|
||||
* The handlers defined on this file are processed and registered into
|
||||
* the Moodle DB after any install or upgrade operation. All plugins
|
||||
* support this.
|
||||
*
|
||||
* @package repository_onedrive
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/* List of handlers */
|
||||
|
||||
$tasks = array(
|
||||
array(
|
||||
'classname' => 'repository_onedrive\remove_temp_access_task',
|
||||
'blocking' => 0,
|
||||
'minute' => 'R',
|
||||
'hour' => 'R',
|
||||
'day' => '*',
|
||||
'dayofweek' => 'R',
|
||||
'month' => '*'
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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/>.
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Upgrade this plugin.
|
||||
*
|
||||
* @param int $oldversion the version we are upgrading from
|
||||
* @package repository_onedrive
|
||||
* @return bool result
|
||||
*/
|
||||
function xmldb_repository_onedrive_upgrade($oldversion) {
|
||||
global $DB;
|
||||
|
||||
$dbman = $DB->get_manager();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Import files from skydrive.
|
||||
*
|
||||
* @package repository_onedrive
|
||||
* @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');
|
||||
|
||||
$PAGE->set_url('/repository/onedrive/importskydrive.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$strheading = get_string('importskydrivefiles', 'repository_onedrive');
|
||||
$PAGE->set_title($strheading);
|
||||
$PAGE->set_heading($strheading);
|
||||
|
||||
require_login();
|
||||
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$confirm = optional_param('confirm', false, PARAM_BOOL);
|
||||
|
||||
if ($confirm) {
|
||||
require_sesskey();
|
||||
require_once($CFG->dirroot . '/repository/lib.php');
|
||||
require_once($CFG->dirroot . '/repository/onedrive/lib.php');
|
||||
|
||||
if (repository_onedrive::import_skydrive_files()) {
|
||||
$mesg = get_string('skydrivefilesimported', 'repository_onedrive');
|
||||
redirect(new moodle_url('/admin/repository.php'), $mesg, null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
} else {
|
||||
$mesg = get_string('skydrivefilesnotimported', 'repository_onedrive');
|
||||
redirect(new moodle_url('/admin/repository.php'), $mesg, null, \core\output\notification::NOTIFY_ERROR);
|
||||
}
|
||||
} else {
|
||||
$continueurl = new moodle_url('/repository/onedrive/importskydrive.php', ['confirm' => true]);
|
||||
$cancelurl = new moodle_url('/admin/repository.php');
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->confirm(get_string('confirmimportskydrive', 'repository_onedrive'), $continueurl, $cancelurl);
|
||||
echo $OUTPUT->footer();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Language file definitions for skydrive repository
|
||||
*
|
||||
* @package repository_skydrive
|
||||
* @copyright 2012 Lancaster University Network Services Ltd
|
||||
* @author Dan Poltawski <dan.poltawski@luns.net.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
$string['configplugin'] = 'Configure OneDrive plugin';
|
||||
$string['skydrive:view'] = 'View OneDrive repository';
|
||||
$string['pluginname'] = 'Microsoft OneDrive';
|
||||
$string['importskydrivefiles'] = 'Import files from Microsoft SkyDrive repository';
|
||||
$string['issuer'] = 'OAuth 2 service';
|
||||
$string['issuer_help'] = 'Select the OAuth 2 service that is configured to talk to the OneDrive API. If the services does not exist yet, you might need to create it.';
|
||||
$string['servicenotenabled'] = 'Access not configured.';
|
||||
$string['oauth2serviceslink'] = '<a href="{$a}" title="Link to OAuth Services configuration">OAuth 2 Services Configuration</a>';
|
||||
$string['searchfor'] = 'Search for {$a}';
|
||||
$string['internal'] = 'Internal (files stored in Moodle)';
|
||||
$string['external'] = 'External (only links stored in Moodle)';
|
||||
$string['both'] = 'Internal and External';
|
||||
$string['skydrivefilesexist'] = 'Files found in the Microsoft SkyDrive repository. This repository is deprecated by Microsoft - the files can be automatically imported to this Microsoft OneDrive repository.';
|
||||
$string['supportedreturntypes'] = 'Supported files';
|
||||
$string['defaultreturntype'] = 'Default return type';
|
||||
$string['fileoptions'] = 'The types and defaults for returned files is configurable here. Note that all files linked externally will be updated so that the owner is the Moodle system account.';
|
||||
$string['owner'] = 'Owned by: {$a}';
|
||||
$string['cachedef_folder'] = 'OneDrive File IDs for folders in the system account';
|
||||
$string['confirmimportskydrive'] = 'Are you sure you want to import all files from the "Microsoft SkyDrive" repository to the "Microsoft OneDrive" repository? As long as the Microsoft OneDrive repository is already configured and working - all imported files will continue working as before. There is no way to undo these changes.';
|
||||
$string['skydrivefilesimported'] = 'All files were imported from the Microsoft SkyDrive repository.';
|
||||
$string['skydrivefilesnotimported'] = 'Some files could not be imported from the Microsoft SkyDrive repository.';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user