diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 22c1ca3afba..01695551d5d 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -1708,6 +1708,8 @@ $string['showsettings'] = 'Show settings'; $string['showtheselogs'] = 'Show these logs'; $string['showthishelpinlanguage'] = 'Show this help in language: {$a}'; $string['schedule'] = 'Schedule'; +$string['signoutofotherservices'] = 'Sign out everywhere'; +$string['signoutofotherservices_help'] = 'If ticked, the account will be signed out of all devices and systems which use web services, such as the mobile app.'; $string['since'] = 'Since'; $string['sincelast'] = 'since last login'; $string['site'] = 'Site'; diff --git a/lang/en/webservice.php b/lang/en/webservice.php index 6eeb775bc6d..06cb7d15037 100644 --- a/lang/en/webservice.php +++ b/lang/en/webservice.php @@ -204,6 +204,7 @@ $string['usernameorid_help'] = 'Enter a username or a user id.'; $string['usernameoridnousererror'] = 'No users were found with this username/user id.'; $string['usernameoridoccurenceerror'] = 'More than one user was found with this username. Please enter the user id.'; $string['usernotallowed'] = 'The user is not allowed for this service. First you need to allow this user on the {$a}\'s allowed users administration page.'; +$string['userservices'] = 'User services: {$a}'; $string['usersettingssaved'] = 'User settings saved'; $string['validuntil'] = 'Valid until'; $string['validuntil_help'] = 'If set, the service will be inactivated after this date for this user.'; diff --git a/login/change_password.php b/login/change_password.php index 5efce2c8116..ccc1cab82da 100644 --- a/login/change_password.php +++ b/login/change_password.php @@ -28,6 +28,7 @@ require('../config.php'); require_once($CFG->dirroot.'/user/lib.php'); require_once('change_password_form.php'); require_once($CFG->libdir.'/authlib.php'); +require_once($CFG->dirroot.'/webservice/lib.php'); $id = optional_param('id', SITEID, PARAM_INT); // current course $return = optional_param('return', 0, PARAM_BOOL); // redirect after password change @@ -122,6 +123,10 @@ if ($mform->is_cancelled()) { \core\session\manager::kill_user_sessions($USER->id, session_id()); } + if (!empty($data->signoutofotherservices)) { + webservice::delete_user_ws_tokens($USER->id); + } + // Reset login lockout - we want to prevent any accidental confusion here. login_unlock_account($USER); diff --git a/login/change_password_form.php b/login/change_password_form.php index 589b45b668d..66654f30775 100644 --- a/login/change_password_form.php +++ b/login/change_password_form.php @@ -63,6 +63,11 @@ class login_change_password_form extends moodleform { $mform->addRule('newpassword2', get_string('required'), 'required', null, 'client'); $mform->setType('newpassword2', PARAM_RAW); + if (empty($CFG->passwordchangetokendeletion) and !empty(webservice::get_active_tokens($USER->id))) { + $mform->addElement('advcheckbox', 'signoutofotherservices', get_string('signoutofotherservices')); + $mform->addHelpButton('signoutofotherservices', 'signoutofotherservices'); + $mform->setDefault('signoutofotherservices', 1); + } // hidden optional params $mform->addElement('hidden', 'id', 0); diff --git a/user/editadvanced.php b/user/editadvanced.php index 91788b390ca..176311d9e12 100644 --- a/user/editadvanced.php +++ b/user/editadvanced.php @@ -29,6 +29,7 @@ require_once($CFG->dirroot.'/user/editadvanced_form.php'); require_once($CFG->dirroot.'/user/editlib.php'); require_once($CFG->dirroot.'/user/profile/lib.php'); require_once($CFG->dirroot.'/user/lib.php'); +require_once($CFG->dirroot.'/webservice/lib.php'); // HTTPS is required in this page when $CFG->loginhttps enabled. $PAGE->https_required(); @@ -218,6 +219,9 @@ if ($usernew = $userform->get_data()) { // the problem here is we do not want to logout admin here when changing own password. \core\session\manager::kill_user_sessions($usernew->id, session_id()); } + if (!empty($usernew->signoutofotherservices)) { + webservice::delete_user_ws_tokens($usernew->id); + } } } diff --git a/user/editadvanced_form.php b/user/editadvanced_form.php index 8814be11f10..d2bd16a96cf 100644 --- a/user/editadvanced_form.php +++ b/user/editadvanced_form.php @@ -123,6 +123,21 @@ class user_editadvanced_form extends moodleform { $mform->disabledIf('newpassword', 'auth', 'in', $cannotchangepass); + // Check if the user has active external tokens. + if ($userid and empty($CFG->passwordchangetokendeletion)) { + if ($tokens = webservice::get_active_tokens($userid)) { + $services = ''; + foreach ($tokens as $token) { + $services .= format_string($token->servicename) . ','; + } + $services = get_string('userservices', 'webservice', rtrim($services, ',')); + $mform->addElement('advcheckbox', 'signoutofotherservices', get_string('signoutofotherservices'), $services); + $mform->addHelpButton('signoutofotherservices', 'signoutofotherservices'); + $mform->disabledIf('signoutofotherservices', 'newpassword', 'eq', ''); + $mform->setDefault('signoutofotherservices', 1); + } + } + $mform->addElement('advcheckbox', 'preference_auth_forcepasswordchange', get_string('forcepasswordchange')); $mform->addHelpButton('preference_auth_forcepasswordchange', 'forcepasswordchange'); $mform->disabledIf('preference_auth_forcepasswordchange', 'createpassword', 'checked'); diff --git a/webservice/lib.php b/webservice/lib.php index 36cb6c9e87f..8ddca420a8b 100644 --- a/webservice/lib.php +++ b/webservice/lib.php @@ -736,7 +736,22 @@ class webservice { } + /** + * Return a list with all the valid user tokens for the given user, it only excludes expired tokens. + * + * @param string $userid user id to retrieve tokens from + * @return array array of token entries + * @since Moodle 3.2 + */ + public static function get_active_tokens($userid) { + global $DB; + $sql = 'SELECT t.*, s.name as servicename FROM {external_tokens} t JOIN + {external_services} s ON t.externalserviceid = s.id WHERE + t.userid = :userid AND (t.validuntil IS NULL OR t.validuntil > :now)'; + $params = array('userid' => $userid, 'now' => time()); + return $DB->get_records_sql($sql, $params); + } } /**