MDL-65959 core_badges: Unrestricted user's badger account

* Restructure the email to be backpack specific
* Amended table defintion and functions
This commit is contained in:
Peter 2019-09-25 12:38:53 +08:00 committed by Peter Dias
parent 6594c54b2e
commit 6f7fe5df9c
8 changed files with 187 additions and 68 deletions

View file

@ -54,15 +54,15 @@ if (!is_null($storedsecret)) {
null, \core\output\notification::NOTIFY_ERROR); null, \core\output\notification::NOTIFY_ERROR);
} }
$obj = new stdClass(); $values = [
$obj->userid = $USER->id; 'userid' => $USER->id,
$obj->email = $data->email; 'backpackemail' => $data->email,
$obj->externalbackpackid = $backpackid; 'externalbackpackid' => $backpackid,
$obj->backpackuid = $backpackuid; 'backpackuid' => $backpackuid,
$obj->autosync = 0; 'autosync' => 0,
$obj->password = $password; 'password' => $password
];
$DB->insert_record('badge_backpack', $obj); badges_save_backpack_credentials((object) $values);
// Remove the verification vars and redirect to the mypackpack page. // Remove the verification vars and redirect to the mypackpack page.
unset_user_preference('badges_email_verify_secret'); unset_user_preference('badges_email_verify_secret');

View file

@ -570,9 +570,10 @@ class backpack_api {
* *
* @param integer $userid The user in Moodle * @param integer $userid The user in Moodle
* @param integer $backpackid The backpack to disconnect * @param integer $backpackid The backpack to disconnect
* @param integer $externalbackupid The external backpack to disconnect
* @return boolean * @return boolean
*/ */
public function disconnect_backpack($userid, $backpackid) { public function disconnect_backpack($userid, $backpackid, $externalbackupid) {
global $DB, $USER; global $DB, $USER;
if (\core\session\manager::is_loggedinas() || $userid != $USER->id) { if (\core\session\manager::is_loggedinas() || $userid != $USER->id) {
@ -584,6 +585,7 @@ class backpack_api {
$DB->delete_records('badge_external', array('backpackid' => $backpackid)); $DB->delete_records('badge_external', array('backpackid' => $backpackid));
$DB->delete_records('badge_backpack', array('userid' => $userid)); $DB->delete_records('badge_backpack', array('userid' => $userid));
$DB->delete_records('badge_external_backpack', array('id' => $externalbackupid));
$badgescache->delete($userid); $badgescache->delete($userid);
return true; return true;
} }

View file

@ -39,7 +39,7 @@ use stdClass;
* Form to edit backpack initial details. * Form to edit backpack initial details.
* *
*/ */
class backpack extends moodleform { class backpack extends external_backpack {
/** /**
* Defines the form * Defines the form
@ -53,24 +53,36 @@ class backpack extends moodleform {
$mform->addHelpButton('backpackheader', 'backpackconnection', 'badges'); $mform->addHelpButton('backpackheader', 'backpackconnection', 'badges');
$mform->addElement('hidden', 'userid', $USER->id); $mform->addElement('hidden', 'userid', $USER->id);
$mform->setType('userid', PARAM_INT); $mform->setType('userid', PARAM_INT);
$sitebackpack = badges_get_site_backpack($CFG->badges_site_backpack); $mform->addElement('hidden', 'externalbackpackid');
$mform->setType('externalbackpackid', PARAM_INT);
if (isset($this->_customdata['email'])) { if (isset($this->_customdata['email'])) {
// Email will be passed in when we're in the process of verifying the user's email address, // Email will be passed in when we're in the process of verifying the user's email address,
// so set the connection status, lock the email field, and provide options to resend the verification // so set the connection status, lock the email field, and provide options to resend the verification
// email or cancel the verification process entirely and start over. // email or cancel the verification process entirely and start over.
$mform->addElement('hidden', 'backpackid', $sitebackpack->id); $mform->hardFreeze();
$mform->setType('backpackid', PARAM_INT);
$status = html_writer::tag('span', get_string('backpackemailverificationpending', 'badges'), $status = html_writer::tag('span', get_string('backpackemailverificationpending', 'badges'),
array('class' => 'notconnected', 'id' => 'connection-status')); array('class' => 'notconnected', 'id' => 'connection-status'));
$mform->addElement('static', 'status', get_string('status'), $status); } else {
$mform->addElement('hidden', 'email', $this->_customdata['email']); $status = html_writer::tag('span', get_string('notconnected', 'badges'),
$mform->setType('email', PARAM_EMAIL); array('class' => 'notconnected', 'id' => 'connection-status'));
$mform->hardFreeze(['email']); }
$emailverify = html_writer::tag('span', s($this->_customdata['email']), []); $mform->addElement('static', 'status', get_string('status'), $status);
$mform->addElement('static', 'emailverify', get_string('email'), $emailverify);
$mform->addElement('hidden', 'backpackpassword', $this->_customdata['backpackpassword']); parent::definition();
$mform->setType('backpackpassword', PARAM_RAW);
$mform->setDefault('backpackemail', $USER->email);
$mform->setDisableShortforms(false);
}
/**
* Override add_action_buttons
*
* @param bool $cancel
* @param null|text $submitlabel
*/
public function add_action_buttons($cancel = true, $submitlabel = null) {
if ($this->_customdata['email']) {
$mform = $this->_form;
$buttonarray = []; $buttonarray = [];
$buttonarray[] = &$mform->createElement('submit', 'submitbutton', $buttonarray[] = &$mform->createElement('submit', 'submitbutton',
get_string('backpackconnectionresendemail', 'badges')); get_string('backpackconnectionresendemail', 'badges'));
@ -101,7 +113,7 @@ class backpack extends moodleform {
$mform->setType('backpackpassword', PARAM_RAW); $mform->setType('backpackpassword', PARAM_RAW);
} }
} }
$this->add_action_buttons(false, get_string('backpackconnectionconnect', 'badges')); parent::add_action_buttons(false, get_string('backpackconnectionconnect', 'badges'));
} }
} }
@ -118,19 +130,18 @@ class backpack extends moodleform {
// We don't need to verify the email address if we're clearing a pending email verification attempt. // We don't need to verify the email address if we're clearing a pending email verification attempt.
if (!isset($data['revertbutton'])) { if (!isset($data['revertbutton'])) {
$check = new stdClass(); $check = new stdClass();
$backpack = badges_get_site_backpack($data['backpackid']); $check->email = $data['backpackemail'];
$check->email = $data['email']; $check->password = $data['password'];
$check->password = $data['backpackpassword']; $check->externalbackpackid = $data['externalbackpackid'];
$check->externalbackpackid = $backpack->id;
$bp = new \core_badges\backpack_api($backpack, $check); $bp = new \core_badges\backpack_api((object) $data, $check);
$result = $bp->authenticate(); $result = $bp->authenticate();
if ($result === false || !empty($result->error)) { if ($result === false || !empty($result->error)) {
$errors['email'] = get_string('backpackconnectionunexpectedresult', 'badges'); $errors['backpackemail'] = get_string('backpackconnectionunexpectedresult', 'badges');
$msg = $bp->get_authentication_error(); $msg = $bp->get_authentication_error();
if (!empty($msg)) { if (!empty($msg)) {
$errors['email'] .= '<br/><br/>'; $errors['backpackemail'] .= '<br/><br/>';
$errors['email'] .= get_string('backpackconnectionunexpectedmessage', 'badges', $msg); $errors['backpackemail'] .= get_string('backpackconnectionunexpectedmessage', 'badges', $msg);
} }
} }
} }

View file

@ -53,11 +53,6 @@ class external_backpack extends \moodleform {
$mform->addElement('hidden', 'action', 'edit'); $mform->addElement('hidden', 'action', 'edit');
$mform->setType('action', PARAM_ALPHA); $mform->setType('action', PARAM_ALPHA);
if ($backpack) {
$mform->addElement('hidden', 'id', $backpack->id);
$mform->setType('id', PARAM_INTEGER);
}
$mform->addElement('text', 'backpackapiurl', get_string('backpackapiurl', 'core_badges')); $mform->addElement('text', 'backpackapiurl', get_string('backpackapiurl', 'core_badges'));
$mform->setType('backpackapiurl', PARAM_URL); $mform->setType('backpackapiurl', PARAM_URL);
$mform->addRule('backpackapiurl', null, 'required', null, 'client'); $mform->addRule('backpackapiurl', null, 'required', null, 'client');
@ -74,11 +69,24 @@ class external_backpack extends \moodleform {
$mform->setDefault('apiversion', OPEN_BADGES_V2P1); $mform->setDefault('apiversion', OPEN_BADGES_V2P1);
$mform->addRule('apiversion', null, 'required', null, 'client'); $mform->addRule('apiversion', null, 'required', null, 'client');
$issuername = $CFG->badges_defaultissuername; $mform->addElement('hidden', 'id', ($backpack->id ?? null));
$mform->addElement('static', 'issuerinfo', get_string('defaultissuername', 'core_badges'), $issuername); $mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'badgebackpack', 0);
$mform->setType('badgebackpack', PARAM_INTEGER);
$mform->addElement('hidden', 'userid', 0);
$mform->setType('userid', PARAM_INTEGER);
$mform->addElement('hidden', 'backpackuid', 0);
$mform->setType('backpackuid', PARAM_INTEGER);
$mform->addElement('advcheckbox', 'includeauthdetails', null, get_string('includeauthdetails', 'core_badges'));
if (!empty($backpack->backpackemail) || !empty($backpack->password)) {
$mform->setDefault('includeauthdetails', 1);
}
$issuercontact = $CFG->badges_defaultissuercontact; $issuercontact = $CFG->badges_defaultissuercontact;
$mform->addElement('static', 'issuerinfo', get_string('defaultissuercontact', 'core_badges'), $issuercontact); $mform->addElement('text', 'backpackemail', get_string('defaultissuercontact', 'core_badges'));
$mform->setType('backpackemail', PARAM_EMAIL);
$mform->setDefault('backpackemail', $issuercontact);
$mform->addElement('passwordunmask', 'password', get_string('defaultissuerpassword', 'core_badges')); $mform->addElement('passwordunmask', 'password', get_string('defaultissuerpassword', 'core_badges'));
$mform->setType('password', PARAM_RAW); $mform->setType('password', PARAM_RAW);
@ -120,4 +128,27 @@ class external_backpack extends \moodleform {
return $errors; return $errors;
} }
/**
* Return submitted data if properly submitted or returns NULL if validation fails or
* if there is no submitted data.
*
* @return object|void
*/
public function get_data() {
$data = parent::get_data();
if ($data ) {
if ((isset($data->includeauthdetails) && !$data->includeauthdetails)
|| (isset($data->apiversion) && $data->apiversion == 2.1)) {
$data->backpackemail = "";
$data->password = "";
}
if ((isset($data->apiversion) && $data->apiversion == 1)) {
$data->password = "";
}
}
return $data;
}
} }

View file

@ -64,7 +64,7 @@ if ($disconnect && $backpack) {
} else { } else {
// If backpack is connected, need to select collections. // If backpack is connected, need to select collections.
$bp = new \core_badges\backpack_api($sitebackpack, $backpack); $bp = new \core_badges\backpack_api($sitebackpack, $backpack);
$bp->disconnect_backpack($USER->id, $backpack->id); $bp->disconnect_backpack($USER->id, $backpack->id, $sitebackpack->id);
redirect(new moodle_url('/badges/mybackpack.php')); redirect(new moodle_url('/badges/mybackpack.php'));
} }
} }
@ -73,10 +73,6 @@ if ($backpack) {
$sitebackpack = badges_get_site_backpack($backpack->externalbackpackid); $sitebackpack = badges_get_site_backpack($backpack->externalbackpackid);
if ($sitebackpack->id != $CFG->badges_site_backpack) {
$warning = $OUTPUT->notification(get_string('backpackneedsupdate', 'badges'), 'warning');
}
// If backpack is connected, need to select collections. // If backpack is connected, need to select collections.
$bp = new \core_badges\backpack_api($sitebackpack, $backpack); $bp = new \core_badges\backpack_api($sitebackpack, $backpack);
$request = $bp->get_collections(); $request = $bp->get_collections();
@ -145,11 +141,12 @@ if ($backpack) {
if (isset($data->revertbutton)) { if (isset($data->revertbutton)) {
badges_disconnect_user_backpack($USER->id); badges_disconnect_user_backpack($USER->id);
redirect(new moodle_url('/badges/mybackpack.php')); redirect(new moodle_url('/badges/mybackpack.php'));
} else if (isset($data->email)) { } else if (isset($data->backpackemail)) {
if (badges_send_verification_email($data->email, $data->backpackid, $data->backpackpassword)) { $newid = badges_create_site_backpack($data, true);
if (badges_send_verification_email($data->backpackemail, $newid, $data->password)) {
$a = get_user_preferences('badges_email_verify_backpackid'); $a = get_user_preferences('badges_email_verify_backpackid');
redirect(new moodle_url('/badges/mybackpack.php'), redirect(new moodle_url('/badges/mybackpack.php'),
get_string('backpackemailverifypending', 'badges', $data->email), get_string('backpackemailverifypending', 'badges', $data->backpackemail),
null, \core\output\notification::NOTIFY_INFO); null, \core\output\notification::NOTIFY_INFO);
} else { } else {
print_error ('backpackcannotsendverification', 'badges'); print_error ('backpackcannotsendverification', 'badges');

View file

@ -762,7 +762,7 @@ function badges_local_backpack_js($checksite = false) {
} }
/** /**
* Create the backpack with this data. * Create the site backpack with this data.
* *
* @param stdClass $data The new backpack data. * @param stdClass $data The new backpack data.
* @return boolean * @return boolean
@ -773,14 +773,8 @@ function badges_create_site_backpack($data) {
require_capability('moodle/badges:manageglobalsettings', $context); require_capability('moodle/badges:manageglobalsettings', $context);
$count = $DB->count_records('badge_external_backpack'); $count = $DB->count_records('badge_external_backpack');
$data->sortorder = $count;
$backpack = new stdClass(); return badges_save_external_backpack($data);
$backpack->apiversion = $data->apiversion;
$backpack->backpackapiurl = $data->backpackapiurl;
$backpack->backpackweburl = $data->backpackweburl;
$backpack->sortorder = $count;
$DB->insert_record('badge_external_backpack', $backpack);
return true;
} }
/** /**
@ -796,15 +790,8 @@ function badges_update_site_backpack($id, $data) {
require_capability('moodle/badges:manageglobalsettings', $context); require_capability('moodle/badges:manageglobalsettings', $context);
if ($backpack = badges_get_site_backpack($id)) { if ($backpack = badges_get_site_backpack($id)) {
$backpack = new stdClass(); $data->id = $id;
$backpack->id = $id; return badges_save_external_backpack($data);
$backpack->apiversion = $data->apiversion;
$backpack->backpackweburl = $data->backpackweburl;
$backpack->backpackapiurl = $data->backpackapiurl;
$backpack->password = !empty($data->password) ? $data->password : '';
$backpack->oauth2_issuerid = !empty($data->oauth2_issuerid) ? $data->oauth2_issuerid : '';
$DB->update_record('badge_external_backpack', $backpack);
return true;
} }
return false; return false;
} }
@ -850,6 +837,79 @@ function badges_delete_site_backpack($id) {
return false; return false;
} }
/**
* Perform the actual create/update of external bakpacks. Any checks on the validity of the id will need to be
* performed before it reaches this function.
*
* @param stdClass $data The backpack data we are updating/inserting
* @return int Returns the id of the new/updated record
*/
function badges_save_external_backpack(stdClass $data) {
global $DB;
$backpack = new stdClass();
$backpack->apiversion = $data->apiversion;
$backpack->backpackweburl = $data->backpackweburl;
$backpack->backpackapiurl = $data->backpackapiurl;
$backpack->backpackemail = $data->backpackemail;
$backpack->password = !empty($data->password) ? $data->password : '';
$backpack->oauth2_issuerid = !empty($data->oauth2_issuerid) ? $data->oauth2_issuerid : '';
if (isset($data->sortorder)) {
$backpack->sortorder = $data->sortorder;
}
$method = 'insert_record';
if (isset($data->id) && $data->id) {
$backpack->id = $data->id;
$method = 'update_record';
}
$record = $DB->$method('badge_external_backpack', $backpack, true);
$data->externalbackpackid = $data->id ?? $record;
unset($data->id);
badges_save_backpack_credentials($data);
return $data->externalbackpackid;
}
/**
* Create a backpack with the provided details. Stores the auth details of the backpack
*
* @param stdClass $data Backpack specific data.
* @return int The id of the external backpack that the credentials correspond to
*/
function badges_save_backpack_credentials(stdClass $data) {
global $DB;
if (isset($data->backpackemail) && isset($data->password)) {
$backpack = new stdClass();
$backpack->email = $data->backpackemail;
$backpack->password = !empty($data->password) ? $data->password : '';
$backpack->externalbackpackid = $data->externalbackpackid;
$backpack->userid = $data->userid ?? 0;
$backpack->backpackuid = $data->backpackuid ?? 0;
$backpack->autosync = $data->autosync ?? 0;
$id = null;
if (isset($data->badgebackpack) && $data->badgebackpack) {
$id = $data->badgebackpack;
} else if (isset($data->id) && $data->id) {
$id = $data->id;
}
$method = $id ? 'update_record' : 'insert_record';
if ($id) {
$backpack->id = $id;
}
$DB->$method('badge_backpack', $backpack);
return $backpack->externalbackpackid;
}
return $data->externalbackpackid ?? 0;
}
/** /**
* Is any backpack enabled that supports open badges V1? * Is any backpack enabled that supports open badges V1?
* @return boolean * @return boolean
@ -884,7 +944,11 @@ function badges_get_site_backpack($id) {
function badges_get_site_backpacks() { function badges_get_site_backpacks() {
global $DB, $CFG; global $DB, $CFG;
$all = $DB->get_records('badge_external_backpack'); $sql = "SELECT beb.*
FROM {badge_external_backpack} beb
LEFT JOIN {badge_backpack} bb ON bb.externalbackpackid = beb.id
WHERE bb.id IS NULL";
$all = $DB->get_records_sql($sql);
foreach ($all as $key => $bp) { foreach ($all as $key => $bp) {
if ($bp->id == $CFG->badges_site_backpack) { if ($bp->id == $CFG->badges_site_backpack) {

View file

@ -2862,5 +2862,19 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2020102100.02); upgrade_main_savepoint(true, 2020102100.02);
} }
if ($oldversion < 2020102300.01) {
$table = new xmldb_table('badge_external_backpack');
$field = new xmldb_field('backpackemail', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
$table->deleteKey('backpackapiurlkey');
$table->deleteKey('backpackweburlkey');
$table->add_key('backpackapiurlkey', XMLDB_KEY_UNIQUE, ['backpackapiurl', 'backpackemail']);
// Main savepoint reached.
upgrade_main_savepoint(true, 2020102300.01);
}
return true; return true;
} }

View file

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
$version = 2020102300.00; // YYYYMMDD = weekly release date of this DEV branch. $version = 2020102300.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches. // RR = release increments - 00 in DEV branches.
// .XX = incremental changes. // .XX = incremental changes.
$release = '3.10dev+ (Build: 20201023)';// Human-friendly version name $release = '3.10dev+ (Build: 20201023)';// Human-friendly version name