From: Eloy Lafuente Date: Sun, 29 Nov 2009 21:24:05 +0000 (+0000) Subject: MDL-16658 restore users pre-check. Reviewed logic with latest discussions. Continues... X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=5d9ab024ac9c311c84716628cce9a124173a2e8b;p=moodle.git MDL-16658 restore users pre-check. Reviewed logic with latest discussions. Continues disabled. Merged from 19_STABLE --- diff --git a/backup/restorelib.php b/backup/restorelib.php index ed4c63317f..585b88b529 100644 --- a/backup/restorelib.php +++ b/backup/restorelib.php @@ -701,22 +701,34 @@ define('RESTORE_GROUPS_GROUPINGS', 3); * Here it's the logic applied, keep it updated: * * If restoring users from same site backup: - * 1A - If match by id and username and mnethost => ok, return target user - * 1B - If match by id and mnethost and user is deleted in DB and - * match by email LIKE 'backup_email%' => ok, return target user - * 1C - If match by id and mnethost and user is deleted in backup file + * 1A - Normal check: If match by id and username and mnethost => ok, return target user + * 1B - Handle users deleted in DB and "alive" in backup file: + * If match by id and mnethost and user is deleted in DB and + * (match by username LIKE 'backup_email.%' or by non empty email = md5(username)) => ok, return target user + * 1C - Handle users deleted in backup file and "alive" in DB: + * If match by id and mnethost and user is deleted in backup file * and match by email = email_without_time(backup_email) => ok, return target user - * 1D - If match by username and mnethost and doesn't match by id => conflict, return false - * 1E - else => user needs to be created, return true + * 1D - Conflict: If match by username and mnethost and doesn't match by id => conflict, return false + * 1E - None of the above, return true => User needs to be created * - * if restoring from another site backup: - * 2A - If match by username and mnethost and - * (email or non-zero firstaccess) => ok, return target user - * 2B - Note: we cannot handle "deleted" situations here as far - * as username gets modified and id cannot be used here - * 2C - If match by username and mnethost and not - * by (email or non-zero firstaccess) => conflict, return false - * 2D - else => user needs to be created, return true + * if restoring from another site backup (cannot match by id here, replace it by email/firstaccess combination): + * 2A - Normal check: If match by username and mnethost and (email or non-zero firstaccess) => ok, return target user + * 2B - Handle users deleted in DB and "alive" in backup file: + * 2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and + * (username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user + * 2B2 - If match by mnethost and user is deleted in DB and + * username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user + * (to cover situations were md5(username) wasn't implemented on delete we requiere both) + * 2C - Handle users deleted in backup file and "alive" in DB: + * If match mnethost and user is deleted in backup file + * and by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user + * 2D - Conflict: If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false + * 1E - None of the above, return true => User needs to be created + * + * Note: for DB deleted users email is stored in username field, hence we + * are looking there for emails. See delete_user() + * Note: for DB deleted users md5(username) is stored *sometimes* in the email field, + * hence we are looking there for usernames if not empty. See delete_user() */ function restore_check_user($restore, $user) { global $CFG, $DB; @@ -738,27 +750,35 @@ define('RESTORE_GROUPS_GROUPINGS', 3); } // 1B - Handle users deleted in DB and "alive" in backup file - // 1B1- If match by id and mnethost and user is deleted in DB and - // match by email LIKE 'backup_email.%' => ok, return target user - // Note: for deleted users email is stored in username field, hence we - // are looking there for emails in the query below. See delete_user() + // Note: for DB deleted users email is stored in username field, hence we + // are looking there for emails. See delete_user() + // Note: for DB deleted users md5(username) is stored *sometimes* in the email field, + // hence we are looking there for usernames if not empty. See delete_user() + // If match by id and mnethost and user is deleted in DB and + // match by username LIKE 'backup_email.%' or by non empty email = md5(username) => ok, return target user if ($rec = $DB->get_record_sql("SELECT * FROM {user} u WHERE id = ? AND mnethostid = ? AND deleted = 1 - AND username LIKE ?", - array($user->id, $user->mnethostid, $user->email.'.%')) { + AND ( + username LIKE ? + OR ( + ".$DB->sql_isnotempty('user', 'email', false, false)." + AND email = ? + ) + )", + array($user->id, $user->mnethostid, $user->email.'.%', md5($user->username)))) { return $rec; // Matching user, deleted in DB found, return it } // 1C - Handle users deleted in backup file and "alive" in DB - // 1C1- If match by id and mnethost and user is deleted in backup file - // and match by email = email_without_time(backup_email) => ok, return target user + // If match by id and mnethost and user is deleted in backup file + // and match by email = email_without_time(backup_email) => ok, return target user if ($user->deleted) { + // Note: for DB deleted users email is stored in username field, hence we + // are looking there for emails. See delete_user() // Trim time() from email - // Note: for deleted users email is stored in username field, hece - // we are trimming the username field to get the email. See delete_user() $trimemail = preg_replace('/(.*?)\.[0-9]+.?$/', '\\1', $user->username); if ($rec = $DB->get_record_sql("SELECT * FROM {user} u @@ -794,23 +814,68 @@ define('RESTORE_GROUPS_GROUPINGS', 3); ) )", array($user->username, $user->mnethostid, $user->email, $user->firstaccess))) { - return $rec; // Matching user + return $rec; // Matching user found, return it } // 2B - Handle users deleted in DB and "alive" in backup file - // Note: for deleted users email is stored in username field, hence we - // are looking there for emails in the query below. See delete_user() - // Note: for deleted users md5(username) is stored *sometimes* in the - // email field, hence we are looking there for usernames in the query below - // 2B - Note: we cannot handle "deleted" situations here as far - // as username gets modified and id cannot be used either - // 2B1-deleted = 1 AND email = md5(username) AND mnsethostid AND (username like $user->email.% OR firstaccess) - // 2B2 deleted and mnsethostid AND username like $user->email.% AND firstaccess + // Note: for DB deleted users email is stored in username field, hence we + // are looking there for emails. See delete_user() + // Note: for DB deleted users md5(username) is stored *sometimes* in the email field, + // hence we are looking there for usernames if not empty. See delete_user() + // 2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and + // (by username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user + if ($rec = $DB->get_record_sql("SELECT * + FROM {user} u + WHERE mnethostid = ? + AND deleted = 1 + AND ".$DB->sql_isnotempty('user', 'email', false, false)." + AND email = ? + AND ( + username LIKE ? + OR ( + firstaccess != 0 + AND firstaccess = ? + ) + )", + array($user->mnethostid, md5($user->username), $user->email.'.%', $user->firstaccess))) { + return $rec; // Matching user found, return it + } + + // 2B2 - If match by mnethost and user is deleted in DB and + // username LIKE 'backup_email.%' and non-zero firstaccess) => ok, return target user + // (this covers situations where md5(username) wasn't being stored so we require both + // the email & non-zero firstaccess to match) + if ($rec = $DB->get_record_sql("SELECT * + FROM {user} u + WHERE mnethostid = ? + AND deleted = 1 + AND username LIKE ? + AND firstaccess != 0 + AND firstaccess = ?", + array($user->mnethostid, $user->email.'.%', $user->firstaccess))) { + return $rec; // Matching user found, return it + } // 2C - Handle users deleted in backup file and "alive" in DB + // If match mnethost and user is deleted in backup file + // and match by email = email_without_time(backup_email) and non-zero firstaccess=> ok, return target user + if ($user->deleted) { + // Note: for DB deleted users email is stored in username field, hence we + // are looking there for emails. See delete_user() + // Trim time() from email + $trimemail = preg_replace('/(.*?)\.[0-9]+.?$/', '\\1', $user->username); + if ($rec = $DB->get_record_sql("SELECT * + FROM {user} u + WHERE mnethostid = ? + AND email = ? + AND firstaccess != 0 + AND firstaccess = ?", + array($user->mnethostid, $trimemail, $user->firstaccess))) { + return $rec; // Matching user, deleted in backup file found, return it + } + } - // 2D - If match by username and mnethost and not - // by (email or non-zero firstaccess) => conflict, return false + // 2D - If match by username and mnethost and not by (email or non-zero firstaccess) => conflict, return false if ($rec = $DB->get_record_sql("SELECT * FROM {user} u WHERE username = ? @@ -830,7 +895,7 @@ define('RESTORE_GROUPS_GROUPINGS', 3); // Arrived here, return true as the user will need to be created and no // conflicts have been found in the logic above. This covers: // 1E - else => user needs to be created, return true - // 2D - else => user needs to be created, return true + // 2E - else => user needs to be created, return true return true; }