in auth/oidc/classes/loginflow/base.php [240:385]
public function disconnect($justremovetokens = false, $donotremovetokens = false, \moodle_url $redirect = null,
\moodle_url $selfurl = null, $userid = null) {
global $USER, $DB, $CFG;
if ($redirect === null) {
$redirect = new \moodle_url('/auth/oidc/ucp.php');
}
if ($selfurl === null) {
$selfurl = new \moodle_url('/auth/oidc/ucp.php', ['action' => 'disconnectlogin']);
}
// Get the record of the user involved. Current user if no ID received.
if (empty($userid)) {
$userid = $USER->id;
}
$userrec = $DB->get_record('user', ['id' => $userid]);
if (empty($userrec)) {
redirect($redirect);
die();
}
if ($justremovetokens === true) {
// Delete token data.
$DB->delete_records('auth_oidc_token', ['userid' => $userrec->id]);
$eventdata = ['objectid' => $userrec->id, 'userid' => $userrec->id];
$event = \auth_oidc\event\user_disconnected::create($eventdata);
$event->trigger();
redirect($redirect);
} else {
global $OUTPUT, $PAGE;
require_once($CFG->dirroot.'/user/lib.php');
$PAGE->set_url($selfurl->out());
$PAGE->set_context(\context_system::instance());
$PAGE->set_pagelayout('standard');
$USER->editing = false;
$ucptitle = get_string('ucp_disconnect_title', 'auth_oidc', $this->config->opname);
$PAGE->navbar->add($ucptitle, $PAGE->url);
$PAGE->set_title($ucptitle);
// Check if we have recorded the user's previous login method.
$prevmethodrec = $DB->get_record('auth_oidc_prevlogin', ['userid' => $userrec->id]);
$prevauthmethod = null;
if (!empty($prevmethodrec) && is_enabled_auth($prevmethodrec->method) === true) {
$prevauthmethod = $prevmethodrec->method;
}
// Manual is always available, we don't need it twice.
if ($prevauthmethod === 'manual') {
$prevauthmethod = null;
}
// We need either the user's previous method or the manual login plugin to be enabled for disconnection.
if (empty($prevauthmethod) && is_enabled_auth('manual') !== true) {
throw new \moodle_exception('errornodisconnectionauthmethod', 'auth_oidc');
}
// Check to see if the user has a username created by OIDC, or a self-created username.
// OIDC-created usernames are usually very verbose, so we'll allow them to choose a sensible one.
// Otherwise, keep their existing username.
$oidctoken = $DB->get_record('auth_oidc_token', ['userid' => $userrec->id]);
$ccun = (isset($oidctoken->oidcuniqid) && strtolower($oidctoken->oidcuniqid) === $userrec->username) ? true : false;
$customdata = [
'canchooseusername' => $ccun,
'prevmethod' => $prevauthmethod,
'donotremovetokens' => $donotremovetokens,
'redirect' => $redirect,
'userid' => $userrec->id,
];
$mform = new \auth_oidc\form\disconnect($selfurl, $customdata);
if ($mform->is_cancelled()) {
redirect($redirect);
} else if ($fromform = $mform->get_data()) {
if (empty($fromform->newmethod) || ($fromform->newmethod !== $prevauthmethod &&
$fromform->newmethod !== 'manual')) {
throw new \moodle_exception('errorauthdisconnectinvalidmethod', 'auth_oidc');
}
$updateduser = new \stdClass;
if ($fromform->newmethod === 'manual') {
if (empty($fromform->password)) {
throw new \moodle_exception('errorauthdisconnectemptypassword', 'auth_oidc');
}
if ($customdata['canchooseusername'] === true) {
if (empty($fromform->username)) {
throw new \moodle_exception('errorauthdisconnectemptyusername', 'auth_oidc');
}
if (strtolower($fromform->username) !== $userrec->username) {
$newusername = strtolower($fromform->username);
$usercheck = ['username' => $newusername, 'mnethostid' => $CFG->mnet_localhost_id];
if ($DB->record_exists('user', $usercheck) === false) {
$updateduser->username = $newusername;
} else {
throw new \moodle_exception('errorauthdisconnectusernameexists', 'auth_oidc');
}
}
}
$updateduser->auth = 'manual';
$updateduser->password = $fromform->password;
} else if ($fromform->newmethod === $prevauthmethod) {
$updateduser->auth = $prevauthmethod;
// We can't use user_update_user as it will rehash the value.
if (!empty($prevmethodrec->password)) {
$manualuserupdate = new \stdClass;
$manualuserupdate->id = $userrec->id;
$manualuserupdate->password = $prevmethodrec->password;
$DB->update_record('user', $manualuserupdate);
}
}
// Update user.
$updateduser->id = $userrec->id;
try {
user_update_user($updateduser);
} catch (\Exception $e) {
throw new \moodle_exception($e->errorcode, '', $selfurl);
}
// Delete token data.
if (empty($fromform->donotremovetokens)) {
$DB->delete_records('auth_oidc_token', ['userid' => $userrec->id]);
$eventdata = ['objectid' => $userrec->id, 'userid' => $userrec->id];
$event = \auth_oidc\event\user_disconnected::create($eventdata);
$event->trigger();
}
// If we're dealing with the current user, refresh the object.
if ($userrec->id == $USER->id) {
$USER = $DB->get_record('user', ['id' => $USER->id]);
}
if (!empty($fromform->redirect)) {
redirect($fromform->redirect);
} else {
redirect($redirect);
}
}
echo $OUTPUT->header();
$mform->display();
echo $OUTPUT->footer();
}
}