From 5e934890c9fbe28bf89362d3eb6140208b5e3464 Mon Sep 17 00:00:00 2001 From: Eloy Lafuente Date: Wed, 30 Dec 2009 17:35:36 +0000 Subject: [PATCH] MDL-16658 restore - new restore:createuser cap + pre-check users before restoring; merged from 19_STABLE --- backup/restorelib.php | 94 +++++++++++++++-------------------------- config-dist.php | 15 +++++++ lang/en_utf8/moodle.php | 4 ++ lang/en_utf8/role.php | 1 + lib/db/access.php | 11 +++++ version.php | 2 +- 6 files changed, 66 insertions(+), 61 deletions(-) diff --git a/backup/restorelib.php b/backup/restorelib.php index 7908e3422d..aac97521ed 100644 --- a/backup/restorelib.php +++ b/backup/restorelib.php @@ -742,7 +742,7 @@ define('RESTORE_GROUPS_GROUPINGS', 3); } // Handle checks from same site backups - if (backup_is_same_site($restore)) { + if (backup_is_same_site($restore) && empty($CFG->forcedifferentsitecheckingusersonrestore)) { // 1A - If match by id and username and mnethost => ok, return target user if ($rec = $DB->get_record('user', array('id'=>$user->id, 'username'=>$user->username, 'mnethostid'=>$user->mnethostid))) { @@ -950,7 +950,7 @@ define('RESTORE_GROUPS_GROUPINGS', 3); $user = $rec->info; // Find the correct mnethostid for user before performing any further check - if (empty($user->mnethosturl) || $user->mnethosturl===$CFG->wwwroot) { + if (empty($user->mnethosturl) || $user->mnethosturl === $CFG->wwwroot) { $user->mnethostid = $CFG->mnet_localhost_id; } else { // fast url-to-id lookups @@ -965,13 +965,18 @@ define('RESTORE_GROUPS_GROUPINGS', 3); $usercheck = restore_check_user($restore, $user); if (is_object($usercheck)) { // No problem, we have found one user in DB to be mapped to + // Annotate it, for later process by restore_create_users(). Set new_id to mapping user->id + backup_putid($restore->backup_unique_code, 'user', $userid, $usercheck->id, $user); } else if ($usercheck === false) { // Found conflict, report it as problem $problems[] = get_string('restoreuserconflict', '', $user->username); $status = false; } else if ($usercheck === true) { // User needs to be created, check if we are able - if (!$cancreateuser) { // Cannot create, report as problem + if ($cancreateuser) { // Can create user, annotate it, for later process by restore_create_users(). Set new_id to 0 + backup_putid($restore->backup_unique_code, 'user', $userid, 0, $user); + + } else { // Cannot create user, report it as problem $problems[] = get_string('restorecannotcreateuser', '', $user->username); $status = false; @@ -2830,25 +2835,17 @@ define('RESTORE_GROUPS_GROUPINGS', 3); $authcache = array(); // Cache to get some bits from authentication plugins $status = true; - //Check it exists - if (!file_exists($xml_file)) { - $status = false; - } - //Get info from xml - if ($status) { - //info will contain the old_id of every user - //in backup_ids->info will be the real info (serialized) - $info = restore_read_xml_users($restore,$xml_file); - } - //Now, get evey user_id from $info and user data from $backup_ids - //and create the necessary db structures + // Users have already been checked by restore_precheck_users() so they are loaded + // in backup_ids table. They don't need to be loaded (parsed) from XML again. Also, note + // the same function has performed the needed modifications in the $user->mnethostid field + // so we don't need to do it again here at all. Just some checks. - if (!empty($info->users)) { + // Get users ids from backup_ids table + $userids = $DB->get_fieldset_select('backup_ids', 'old_id', 'backup_code = ? AND table_name = ?', array($restore->backup_unique_code, 'user')); - /// Grab mnethosts keyed by wwwroot, to map to id - $mnethosts = $DB->get_records('mnet_host', null, - 'wwwroot', 'wwwroot, id'); + // Have users to process, proceed with them + if (!empty($userids)) { /// Get languages for quick search later $languages = get_list_of_languages(); @@ -2858,9 +2855,22 @@ define('RESTORE_GROUPS_GROUPINGS', 3); /// Init trailing messages $messages = array(); - foreach ($info->users as $userid) { - $rec = backup_getid($restore->backup_unique_code,"user",$userid); - $user = $rec->info; + foreach ($userids as $userid) { + // Defaults + $user_exists = false; // By default user does not exist + $newid = null; // By default, there is not newid + + // Get record from backup_ids + $useridsdbrec = backup_getid($restore->backup_unique_code, 'user', $userid); + + // Based in restore_precheck_users() calculations, if the user exists + // new_id must contain the id of the matching user + if (!empty($useridsdbrec->new_id)) { + $user_exists = true; + $newid = $useridsdbrec->new_id; + } + + $user = $useridsdbrec->info; foreach (array_keys(get_object_vars($user)) as $field) { if (!is_array($user->$field)) { $user->$field = backup_todb($user->$field); @@ -2908,31 +2918,12 @@ define('RESTORE_GROUPS_GROUPINGS', 3); //Has role teacher or student or needed $is_course_user = ($is_teacher or $is_student or $is_needed); - // in case we are restoring to same server, look for user by id and username - // it should return record always, but in sites rebuilt from scratch - // and being reconstructed using course backups - $user_data = false; - if (backup_is_same_site($restore)) { - $user_data = $DB->get_record('user', array('id'=>$user->id, 'username'=>$user->username)); - } - // Only try to perform mnethost/auth modifications if restoring to another server // or if, while restoring to same server, the user doesn't exists yet (rebuilt site) // // So existing user data in same server *won't be modified by restore anymore*, // under any circumpstance. If somehting is wrong with existing data, it's server fault. - if (!backup_is_same_site($restore) || (backup_is_same_site($restore) && !$user_data)) { - //Calculate mnethostid - if (empty($user->mnethosturl) || $user->mnethosturl===$CFG->wwwroot) { - $user->mnethostid = $CFG->mnet_localhost_id; - } else { - // fast url-to-id lookups - if (isset($mnethosts[$user->mnethosturl])) { - $user->mnethostid = $mnethosts[$user->mnethosturl]->id; - } else { - $user->mnethostid = $CFG->mnet_localhost_id; - } - } + if (!backup_is_same_site($restore) || (backup_is_same_site($restore) && !$user_exists)) { //Arriving here, any user with mnet auth and using $CFG->mnet_localhost_id is wrong //as own server cannot be accesed over mnet. Change auth to manual and inform about the switch if ($user->auth == 'mnet' && $user->mnethostid == $CFG->mnet_localhost_id) { @@ -2951,21 +2942,6 @@ define('RESTORE_GROUPS_GROUPINGS', 3); } unset($user->mnethosturl); - //To store user->id along all the iteration - $newid=null; - //check if it exists (by username) and get its id - $user_exists = true; - if (!backup_is_same_site($restore) || !$user_data) { /// Restoring to another server, or rebuilding site (failed id& - /// login search above), look for existing user based on fields - $user_data = $DB->get_record('user', array('username'=>$user->username, 'mnethostid'=>$user->mnethostid)); - } - - if (!$user_data) { - $user_exists = false; - } else { - $newid = $user_data->id; - } - //Flags to see what parts are we going to restore $create_user = true; $create_roles = true; @@ -3245,7 +3221,7 @@ define('RESTORE_GROUPS_GROUPINGS', 3); } backup_flush(300); } - } /// End of loop over all the users loaded from xml + } /// End of loop over all the users loaded from backup_ids table /// Inform about all the messages geerated while restoring users if (!defined('RESTORE_SILENTLY')) { @@ -8487,7 +8463,6 @@ define('RESTORE_GROUPS_GROUPINGS', 3); // Precheck the users section, detecting various situations that can lead to problems, so // we stop restore before performing any further action - /* if (!defined('RESTORE_SILENTLY')) { echo '
  • '.get_string('restoreusersprecheck').'
  • '; } @@ -8501,7 +8476,6 @@ define('RESTORE_GROUPS_GROUPINGS', 3); } return false; } - */ //If we've selected to restore into new course //create it (course) diff --git a/config-dist.php b/config-dist.php index 94d8ab0310..5ad939e961 100644 --- a/config-dist.php +++ b/config-dist.php @@ -180,6 +180,21 @@ $CFG->admin = 'admin'; // shared out from your site/institution! // $CFG->includeuserpasswordsinbackup = true; // +// Completely disable user creation on restore, bypassing any right granted +// via roles/capabilities. By enabling this setting any restore process +// requiring users to be created will be stopped before any further action. +// $CFG->disableusercreationonrestore = true; +// +// Modify the restore process in order to force the "user checks" to assume +// that the backup was originated in a different site so detection of matching +// users is performed with some different (more "relaxed") rules. *Only* useful +// if the backup file has been generated with Moodle < 1.9.4 and the site has +// been rebuilt from scratch using backup files (not the best way, btw). If you +// are getting user conflicts on restore, try to restore the backup to a different +// site, backup it again and then restore on target server instead of enabling this +// setting permanently! +// $CFG->forcedifferentsitecheckingusersonrestore = true; +// // Prevent stats processing and hide the GUI // $CFG->disablestatsprocessing = true; // diff --git a/lang/en_utf8/moodle.php b/lang/en_utf8/moodle.php index 638ff34da3..7e4a3a14da 100644 --- a/lang/en_utf8/moodle.php +++ b/lang/en_utf8/moodle.php @@ -1369,6 +1369,7 @@ $string['resource'] = 'Resource'; $string['resources'] = 'Resources'; $string['restore'] = 'Restore'; $string['restorecancelled'] = 'Restore canceled'; +$string['restorecannotcreateuser'] = 'restore needs to create user \'$a\' from backup file and you are not allowed to do that'; $string['restorecoursenow'] = 'Restore this course now!'; $string['restoredaccount'] = 'Restored account'; $string['restoredaccountinfo'] = 'This account was imported from another server and the password has been lost. To set a new password by email, please click \"Continue\"'; @@ -1376,7 +1377,10 @@ $string['restorefinished'] = 'Restore completed successfully'; $string['restoreto'] = 'Restore to'; $string['restoretositeadding'] = 'Warning: You are about to restore to the site front page, adding data to it!'; $string['restoretositedeleting'] = 'Warning: You are about to restore to the site front page, deleting data from it first!'; +$string['restoreuserconflict'] = 'trying to restore user \'$a\' from backup file will cause conflict'; $string['restoreuserinfofailed'] = 'The restore process has stopped because you don\'t have permission to restore user data.'; +$string['restoreusersprecheck'] = 'Checking user information'; +$string['restoreusersprecheckerror'] = 'Some problems were detected checking user information'; $string['restricted'] = 'Restricted'; $string['restrictmodules'] = 'Restrict activity modules?'; $string['returntooriginaluser'] = 'Return to $a'; diff --git a/lang/en_utf8/role.php b/lang/en_utf8/role.php index 094f02c7fb..7a6b3ebe3f 100644 --- a/lang/en_utf8/role.php +++ b/lang/en_utf8/role.php @@ -200,6 +200,7 @@ $string['resetrolenolegacy'] = 'Clear permissions'; $string['resetrolesure'] = 'Are you sure that you want to reset role \"$a->name ($a->shortname)\" to defaults?

    The defaults are taken from the selected legacy capability ($a->legacytype).'; $string['resetrolesurenolegacy'] = 'Are you sure that you want to clear all permissions defined in this role \"$a->name ($a->shortname)\"?'; $string['restore:rolldates'] = 'Allowed to roll activity configuration dates on restore'; +$string['restore:createuser'] = 'Create users on restore'; $string['restore:userinfo'] = 'Restore user data'; $string['risks'] = 'Risks'; $string['role:assign'] = 'Assign roles to users'; diff --git a/lib/db/access.php b/lib/db/access.php index fad8f7c161..db1548f32a 100644 --- a/lib/db/access.php +++ b/lib/db/access.php @@ -216,6 +216,17 @@ $capabilities = array( ) ), + 'moodle/restore:createuser' => array( + + 'riskbitmask' => RISK_SPAM | RISK_PERSONAL, + + 'captype' => 'write', + 'contextlevel' => CONTEXT_SYSTEM, + 'legacy' => array( + 'admin' => CAP_ALLOW + ) + ), + 'moodle/restore:userinfo' => array( 'riskbitmask' => RISK_SPAM | RISK_PERSONAL | RISK_XSS | RISK_CONFIG, diff --git a/version.php b/version.php index d624093448..7bb4d335c5 100644 --- a/version.php +++ b/version.php @@ -6,7 +6,7 @@ // This is compared against the values stored in the database to determine // whether upgrades should be performed (see lib/db/*.php) - $version = 2009122500; // YYYYMMDD = date of the last version bump + $version = 2009123000; // YYYYMMDD = date of the last version bump // XX = daily increments $release = '2.0 dev (Build: 20091230)'; // Human-friendly version name -- 2.39.5