$this->assertSame('Table "backup_ids_temp" does not exist', $e->getMessage());
}
}
+
+ /**
+ * Data provider for {@link test_precheck_user()}
+ */
+ public function precheck_user_provider() {
+
+ $emailmultiplier = [
+ 'shortmail' => 'normalusername@example.com',
+ //'longmail' => str_repeat('a', 100) // It's not validated, hence any string is ok.
+ ];
+
+ $providercases = [];
+
+ foreach ($emailmultiplier as $emailk => $email) {
+ // Get the related cases.
+ $cases = $this->precheck_user_cases($email);
+ // Rename them (keys).
+ foreach ($cases as $key => $case) {
+ $providercases[$key . ' - ' . $emailk] = $case;
+ }
+ }
+
+ return $providercases;
+ }
+
+ /**
+ * Get all the cases implemented in {@link restore_dbops::precheck_users()}
+ */
+ private function precheck_user_cases($email) {
+ global $CFG;
+
+ $baseuserarr = [
+ 'username' => 'normalusername',
+ 'email' => $email,
+ 'mnethostid' => $CFG->mnet_localhost_id,
+ 'firstaccess'=> 123456789,
+ 'deleted' => 0,
+ 'forceemailcleanup' => false, // Hack to force the DB record to have empty mail.
+ 'forceduplicateadminallowed' => false]; // Hack to enable import_general_duplicate_admin_allowed.
+
+ return [
+ // Cases with samesite = true.
+ 'samesite match existing (1A)' => [
+ 'dbuser' => $baseuserarr,
+ 'backupuser' => $baseuserarr,
+ 'samesite' => true,
+ 'outcome' => 'match'
+ ],
+ 'samesite match existing anon (1B)' => [
+ 'dbuser' => array_merge($baseuserarr, [
+ 'username' => 'anon01']),
+ 'backupuser' => array_merge($baseuserarr, [
+ 'id' => -1, 'username' => 'anon01', 'firstname' => 'anonfirstname01',
+ 'lastname' => 'anonlastname01', 'email' => 'anon01@doesntexist.invalid']),
+ 'samesite' => true,
+ 'outcome' => 'match'
+ ],
+ 'samesite match existing deleted in db, alive in backup, by db username (1C)' => [
+ 'dbuser' => array_merge($baseuserarr, [
+ 'deleted' => 1]),
+ 'backupuser' => array_merge($baseuserarr, [
+ 'username' => 'this_wont_match']),
+ 'samesite' => true,
+ 'outcome' => 'match'
+ ],
+ 'samesite match existing deleted in db, alive in backup, by db email (1C)' => [
+ 'dbuser' => array_merge($baseuserarr, [
+ 'deleted' => 1]),
+ 'backupuser' => array_merge($baseuserarr, [
+ 'email' => 'this_wont_match']),
+ 'samesite' => true,
+ 'outcome' => 'match'
+ ],
+ 'samesite match existing alive in db, deleted in backup (1D)' => [
+ 'dbuser' => $baseuserarr,
+ 'backupuser' => array_merge($baseuserarr, [
+ 'deleted' => 1]),
+ 'samesite' => true,
+ 'outcome' => 'match'
+ ],
+ 'samesite conflict (1E)' => [
+ 'dbuser' => $baseuserarr,
+ 'backupuser' => array_merge($baseuserarr, ['id' => -1]),
+ 'samesite' => true,
+ 'outcome' => false
+ ],
+ 'samesite create user (1F)' => [
+ 'dbuser' => $baseuserarr,
+ 'backupuser' => array_merge($baseuserarr,[
+ 'username' => 'newusername']),
+ 'samesite' => false,
+ 'outcome' => true
+ ],
+
+ // Cases with samesite = false.
+ 'no samesite match existing, by db email (2A1)' => [
+ 'dbuser' => $baseuserarr,
+ 'backupuser' => array_merge($baseuserarr,[
+ 'firstaccess' => 0]),
+ 'samesite' => false,
+ 'outcome' => 'match'
+ ],
+ 'no samesite match existing, by db firstaccess (2A1)' => [
+ 'dbuser' => $baseuserarr,
+ 'backupuser' => array_merge($baseuserarr,[
+ 'email' => 'this_wont_match@example.con']),
+ 'samesite' => false,
+ 'outcome' => 'match'
+ ],
+ 'no samesite match existing anon (2A1 too)' => [
+ 'dbuser' => array_merge($baseuserarr, [
+ 'username' => 'anon01']),
+ 'backupuser' => array_merge($baseuserarr, [
+ 'id' => -1, 'username' => 'anon01', 'firstname' => 'anonfirstname01',
+ 'lastname' => 'anonlastname01', 'email' => 'anon01@doesntexist.invalid']),
+ 'samesite' => false,
+ 'outcome' => 'match'
+ ],
+ 'no samesite match dupe admin (2A2)' => [
+ 'dbuser' => array_merge($baseuserarr, [
+ 'username' => 'admin_old_site_id',
+ 'forceduplicateadminallowed' => true]),
+ 'backupuser' => array_merge($baseuserarr, [
+ 'username' => 'admin']),
+ 'samesite' => false,
+ 'outcome' => 'match'
+ ],
+ 'no samesite match existing deleted in db, alive in backup, by db username (2B1)' => [
+ 'dbuser' => array_merge($baseuserarr, [
+ 'deleted' => 1]),
+ 'backupuser' => array_merge($baseuserarr, [
+ 'firstaccess' => 0]),
+ 'samesite' => false,
+ 'outcome' => 'match'
+ ],
+ 'no samesite match existing deleted in db, alive in backup, by db firstaccess (2B1)' => [
+ 'dbuser' => array_merge($baseuserarr, [
+ 'deleted' => 1]),
+ 'backupuser' => array_merge($baseuserarr, [
+ 'mail' => 'this_wont_match']),
+ 'samesite' => false,
+ 'outcome' => 'match'
+ ],
+ 'no samesite match existing deleted in db, alive in backup (2B2)' => [
+ 'dbuser' => array_merge($baseuserarr, [
+ 'deleted' => 1,
+ 'forceemailcleanup' => true]),
+ 'backupuser' => $baseuserarr,
+ 'samesite' => false,
+ 'outcome' => 'match'
+ ],
+ 'no samesite match existing alive in db, deleted in backup (2C)' => [
+ 'dbuser' => $baseuserarr,
+ 'backupuser' => array_merge($baseuserarr, [
+ 'deleted' => 1]),
+ 'samesite' => false,
+ 'outcome' => 'match'
+ ],
+ 'no samesite conflict (2D)' => [
+ 'dbuser' => $baseuserarr,
+ 'backupuser' => array_merge($baseuserarr,[
+ 'email' => 'anotheruser@example.com', 'firstaccess' => 0]),
+ 'samesite' => false,
+ 'outcome' => false
+ ],
+ 'no samesite create user (2E)' => [
+ 'dbuser' => $baseuserarr,
+ 'backupuser' => array_merge($baseuserarr,[
+ 'username' => 'newusername']),
+ 'samesite' => false,
+ 'outcome' => true
+ ],
+
+ ];
+ }
+
+ /**
+ * @dataProvider precheck_user_provider
+ * @covers restore_dbops::precheck_user()
+ * */
+ public function test_precheck_user($dbuser, $backupuser, $samesite, $outcome) {
+ global $DB;
+
+ $this->resetAfterTest();
+
+ $dbuser = (object)$dbuser;
+ $backupuser = (object)$backupuser;
+
+ $siteid = null;
+
+ // If the backup user must be deleted, simulate it (by temp inserting to DB, deleting and fetching it back).
+ if ($backupuser->deleted) {
+ $backupuser->id = $DB->insert_record('user', array_merge((array)$backupuser, ['deleted' => 0]));
+ delete_user($backupuser);
+ $backupuser = $DB->get_record('user', ['id' => $backupuser->id]);
+ $DB->delete_records('user', ['id' => $backupuser->id]);
+ unset($backupuser->id);
+ }
+
+ // Create the db user, normally.
+ $dbuser->id = $DB->insert_record('user', array_merge((array)$dbuser, ['deleted' => 0]));
+ $backupuser->id = $backupuser->id ?? $dbuser->id;
+
+ // We may want to enable the import_general_duplicate_admin_allowed setting and look for old admin records.
+ if ($dbuser->forceduplicateadminallowed) {
+ set_config('import_general_duplicate_admin_allowed', true, 'backup');
+ $siteid = 'old_site_id';
+ }
+
+ // If the DB user must be deleted, do it and fetch it back.
+ if ($dbuser->deleted) {
+ delete_user($dbuser);
+ // We may want to clean the mail field (old behavior, not containing the current md5(username)
+ if ($dbuser->forceemailcleanup) {
+ $DB->set_field('user', 'email', '', ['id' => $dbuser->id]);
+ }
+ }
+
+ // Get the dbuser record, because we may have changed it above.
+ $dbuser = $DB->get_record('user', ['id' => $dbuser->id]);
+
+ $method = (new ReflectionClass('restore_dbops'))->getMethod('precheck_user');
+ $method->setAccessible(true);
+ $result = $method->invoke(null, $backupuser, $samesite, $siteid);
+
+ if (is_bool($result)) {
+ $this->assertSame($outcome, $result);
+ } else {
+ $outcome = $dbuser; // Outcome is not bool, matching found, so it must be the dbuser,
+ // Just check ids, it means the expected match has been found in database.
+ $this->assertSame($outcome->id, $result->id);
+ }
+ }
}