See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 39 and 401]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace auth_db; 18 19 /** 20 * External database auth sync tests, this also tests adodb drivers 21 * that are matching our four supported Moodle database drivers. 22 * 23 * @package auth_db 24 * @category phpunit 25 * @copyright 2012 Petr Skoda {@link http://skodak.org} 26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 */ 28 class db_test extends \advanced_testcase { 29 /** @var string Original error log */ 30 protected $oldlog; 31 32 /** @var int The amount of users to create for the large user set deletion test */ 33 protected $largedeletionsetsize = 128; 34 35 public static function tearDownAfterClass(): void { 36 global $DB; 37 // Apply sqlsrv native driver error and logging default 38 // settings while finishing the AdoDB tests. 39 if ($DB->get_dbfamily() === 'mssql') { 40 sqlsrv_configure("WarningsReturnAsErrors", false); 41 sqlsrv_configure("LogSubsystems", SQLSRV_LOG_SYSTEM_OFF); 42 sqlsrv_configure("LogSeverity", SQLSRV_LOG_SEVERITY_ERROR); 43 } 44 } 45 46 protected function init_auth_database() { 47 global $DB, $CFG; 48 require_once("$CFG->dirroot/auth/db/auth.php"); 49 50 // Discard error logs from AdoDB. 51 $this->oldlog = ini_get('error_log'); 52 ini_set('error_log', "$CFG->dataroot/testlog.log"); 53 54 $dbman = $DB->get_manager(); 55 56 set_config('extencoding', 'utf-8', 'auth_db'); 57 58 set_config('host', $CFG->dbhost, 'auth_db'); 59 set_config('user', $CFG->dbuser, 'auth_db'); 60 set_config('pass', $CFG->dbpass, 'auth_db'); 61 set_config('name', $CFG->dbname, 'auth_db'); 62 63 if (!empty($CFG->dboptions['dbport'])) { 64 set_config('host', $CFG->dbhost.':'.$CFG->dboptions['dbport'], 'auth_db'); 65 } 66 67 switch ($DB->get_dbfamily()) { 68 69 case 'mysql': 70 set_config('type', 'mysqli', 'auth_db'); 71 set_config('setupsql', "SET NAMES 'UTF-8'", 'auth_db'); 72 set_config('sybasequoting', '0', 'auth_db'); 73 if (!empty($CFG->dboptions['dbsocket'])) { 74 $dbsocket = $CFG->dboptions['dbsocket']; 75 if ((strpos($dbsocket, '/') === false and strpos($dbsocket, '\\') === false)) { 76 $dbsocket = ini_get('mysqli.default_socket'); 77 } 78 set_config('type', 'mysqli://'.rawurlencode($CFG->dbuser).':'.rawurlencode($CFG->dbpass).'@'.rawurlencode($CFG->dbhost).'/'.rawurlencode($CFG->dbname).'?socket='.rawurlencode($dbsocket), 'auth_db'); 79 } 80 break; 81 82 case 'oracle': 83 set_config('type', 'oci8po', 'auth_db'); 84 set_config('sybasequoting', '1', 'auth_db'); 85 break; 86 87 case 'postgres': 88 set_config('type', 'postgres7', 'auth_db'); 89 $setupsql = "SET NAMES 'UTF-8'"; 90 if (!empty($CFG->dboptions['dbschema'])) { 91 $setupsql .= "; SET search_path = '".$CFG->dboptions['dbschema']."'"; 92 } 93 set_config('setupsql', $setupsql, 'auth_db'); 94 set_config('sybasequoting', '0', 'auth_db'); 95 if (!empty($CFG->dboptions['dbsocket']) and ($CFG->dbhost === 'localhost' or $CFG->dbhost === '127.0.0.1')) { 96 if (strpos($CFG->dboptions['dbsocket'], '/') !== false) { 97 $socket = $CFG->dboptions['dbsocket']; 98 if (!empty($CFG->dboptions['dbport'])) { 99 $socket .= ':' . $CFG->dboptions['dbport']; 100 } 101 set_config('host', $socket, 'auth_db'); 102 } else { 103 set_config('host', '', 'auth_db'); 104 } 105 } 106 break; 107 108 case 'mssql': 109 set_config('type', 'mssqlnative', 'auth_db'); 110 set_config('sybasequoting', '1', 'auth_db'); 111 112 // The native sqlsrv driver uses a comma as separator between host and port. 113 $dbhost = $CFG->dbhost; 114 if (!empty($dboptions['dbport'])) { 115 $dbhost .= ',' . $dboptions['dbport']; 116 } 117 set_config('host', $dbhost, 'auth_db'); 118 break; 119 120 default: 121 throw new exception('Unknown database family ' . $DB->get_dbfamily()); 122 } 123 124 $table = new \xmldb_table('auth_db_users'); 125 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 126 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null); 127 $table->add_field('pass', XMLDB_TYPE_CHAR, '255', null, null, null); 128 $table->add_field('email', XMLDB_TYPE_CHAR, '255', null, null, null); 129 $table->add_field('firstname', XMLDB_TYPE_CHAR, '255', null, null, null); 130 $table->add_field('lastname', XMLDB_TYPE_CHAR, '255', null, null, null); 131 $table->add_field('animal', XMLDB_TYPE_CHAR, '255', null, null, null); 132 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 133 if ($dbman->table_exists($table)) { 134 $dbman->drop_table($table); 135 } 136 $dbman->create_table($table); 137 set_config('table', $CFG->prefix.'auth_db_users', 'auth_db'); 138 set_config('fielduser', 'name', 'auth_db'); 139 set_config('fieldpass', 'pass', 'auth_db'); 140 set_config('field_map_lastname', 'lastname', 'auth_db'); 141 set_config('field_updatelocal_lastname', 'oncreate', 'auth_db'); 142 set_config('field_lock_lastname', 'unlocked', 'auth_db'); 143 // Setu up field mappings. 144 145 set_config('field_map_email', 'email', 'auth_db'); 146 set_config('field_updatelocal_email', 'oncreate', 'auth_db'); 147 set_config('field_updateremote_email', '0', 'auth_db'); 148 set_config('field_lock_email', 'unlocked', 'auth_db'); 149 150 // Create a user profile field and add mapping to it. 151 $this->getDataGenerator()->create_custom_profile_field(['shortname' => 'pet', 'name' => 'Pet', 'datatype' => 'text']); 152 153 set_config('field_map_profile_field_pet', 'animal', 'auth_db'); 154 set_config('field_updatelocal_profile_field_pet', 'oncreate', 'auth_db'); 155 set_config('field_updateremote_profile_field_pet', '0', 'auth_db'); 156 set_config('field_lock_profile_field_pet', 'unlocked', 'auth_db'); 157 158 // Init the rest of settings. 159 set_config('passtype', 'plaintext', 'auth_db'); 160 set_config('changepasswordurl', '', 'auth_db'); 161 set_config('debugauthdb', 0, 'auth_db'); 162 set_config('removeuser', AUTH_REMOVEUSER_KEEP, 'auth_db'); 163 } 164 165 protected function cleanup_auth_database() { 166 global $DB; 167 168 $dbman = $DB->get_manager(); 169 $table = new \xmldb_table('auth_db_users'); 170 $dbman->drop_table($table); 171 172 ini_set('error_log', $this->oldlog); 173 } 174 175 public function test_plugin() { 176 global $DB, $CFG; 177 require_once($CFG->dirroot . '/user/profile/lib.php'); 178 179 $this->resetAfterTest(true); 180 181 // NOTE: It is strongly discouraged to create new tables in advanced_testcase classes, 182 // but there is no other simple way to test ext database enrol sync, so let's 183 // disable transactions are try to cleanup after the tests. 184 185 $this->preventResetByRollback(); 186 187 $this->init_auth_database(); 188 189 /** @var auth_plugin_db $auth */ 190 $auth = get_auth_plugin('db'); 191 192 $authdb = $auth->db_init(); 193 194 195 // Test adodb may access the table. 196 197 $user1 = (object)array('name'=>'u1', 'pass'=>'heslo', 'email'=>'u1@example.com'); 198 $user1->id = $DB->insert_record('auth_db_users', $user1); 199 200 201 $sql = "SELECT * FROM {$auth->config->table}"; 202 $rs = $authdb->Execute($sql); 203 $this->assertInstanceOf('ADORecordSet', $rs); 204 $this->assertFalse($rs->EOF); 205 $fields = $rs->FetchRow(); 206 $this->assertTrue(is_array($fields)); 207 $this->assertTrue($rs->EOF); 208 $rs->Close(); 209 210 $authdb->Close(); 211 212 213 // Test bulk user account creation. 214 215 $user2 = (object)['name' => 'u2', 'pass' => 'heslo', 'email' => 'u2@example.com', 'animal' => 'cat']; 216 $user2->id = $DB->insert_record('auth_db_users', $user2); 217 218 $user3 = (object)array('name'=>'admin', 'pass'=>'heslo', 'email'=>'admin@example.com'); // Should be skipped. 219 $user3->id = $DB->insert_record('auth_db_users', $user3); 220 221 $this->assertCount(2, $DB->get_records('user')); 222 223 $trace = new \null_progress_trace(); 224 225 // Sync users and make sure that two events user_created werer triggered. 226 $sink = $this->redirectEvents(); 227 $auth->sync_users($trace, false); 228 $events = $sink->get_events(); 229 $sink->close(); 230 $this->assertCount(2, $events); 231 $this->assertTrue($events[0] instanceof \core\event\user_created); 232 $this->assertTrue($events[1] instanceof \core\event\user_created); 233 234 // Assert the two users were created. 235 $this->assertEquals(4, $DB->count_records('user')); 236 $u1 = $DB->get_record('user', array('username'=>$user1->name, 'auth'=>'db')); 237 $this->assertSame($user1->email, $u1->email); 238 $this->assertEmpty(profile_user_record($u1->id)->pet); 239 $u2 = $DB->get_record('user', array('username'=>$user2->name, 'auth'=>'db')); 240 $this->assertSame($user2->email, $u2->email); 241 $this->assertSame($user2->animal, profile_user_record($u2->id)->pet); 242 $admin = $DB->get_record('user', array('username'=>'admin', 'auth'=>'manual')); 243 $this->assertNotEmpty($admin); 244 245 246 // Test sync updates. 247 248 $user2b = clone($user2); 249 $user2b->email = 'u2b@example.com'; 250 $user2b->animal = 'dog'; 251 $DB->update_record('auth_db_users', $user2b); 252 253 $auth->sync_users($trace, false); 254 $this->assertEquals(4, $DB->count_records('user')); 255 $u2 = $DB->get_record('user', array('username'=>$user2->name)); 256 $this->assertSame($user2->email, $u2->email); 257 $this->assertSame($user2->animal, profile_user_record($u2->id)->pet); 258 259 $auth->sync_users($trace, true); 260 $this->assertEquals(4, $DB->count_records('user')); 261 $u2 = $DB->get_record('user', array('username'=>$user2->name)); 262 $this->assertSame($user2->email, $u2->email); 263 264 set_config('field_updatelocal_email', 'onlogin', 'auth_db'); 265 $auth->config->field_updatelocal_email = 'onlogin'; 266 set_config('field_updatelocal_profile_field_pet', 'onlogin', 'auth_db'); 267 $auth->config->field_updatelocal_profile_field_pet = 'onlogin'; 268 269 $auth->sync_users($trace, false); 270 $this->assertEquals(4, $DB->count_records('user')); 271 $u2 = $DB->get_record('user', array('username'=>$user2->name)); 272 $this->assertSame($user2->email, $u2->email); 273 274 $auth->sync_users($trace, true); 275 $this->assertEquals(4, $DB->count_records('user')); 276 $u2 = $DB->get_record('user', array('username'=>$user2->name)); 277 $this->assertSame($user2b->email, $u2->email); 278 $this->assertSame($user2b->animal, profile_user_record($u2->id)->pet); 279 280 281 // Test sync deletes and suspends. 282 283 $DB->delete_records('auth_db_users', array('id'=>$user2->id)); 284 $this->assertCount(2, $DB->get_records('auth_db_users')); 285 unset($user2); 286 unset($user2b); 287 288 $auth->sync_users($trace, false); 289 $this->assertEquals(4, $DB->count_records('user')); 290 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1))); 291 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); 292 293 set_config('removeuser', AUTH_REMOVEUSER_SUSPEND, 'auth_db'); 294 $auth->config->removeuser = AUTH_REMOVEUSER_SUSPEND; 295 296 $auth->sync_users($trace, false); 297 $this->assertEquals(4, $DB->count_records('user')); 298 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1))); 299 $this->assertEquals(1, $DB->count_records('user', array('suspended'=>1))); 300 301 $user2 = (object)array('name'=>'u2', 'pass'=>'heslo', 'email'=>'u2@example.com'); 302 $user2->id = $DB->insert_record('auth_db_users', $user2); 303 304 $auth->sync_users($trace, false); 305 $this->assertEquals(4, $DB->count_records('user')); 306 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1))); 307 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); 308 309 $DB->delete_records('auth_db_users', array('id'=>$user2->id)); 310 311 set_config('removeuser', AUTH_REMOVEUSER_FULLDELETE, 'auth_db'); 312 $auth->config->removeuser = AUTH_REMOVEUSER_FULLDELETE; 313 314 $auth->sync_users($trace, false); 315 $this->assertEquals(4, $DB->count_records('user')); 316 $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1))); 317 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); 318 319 $user2 = (object)array('name'=>'u2', 'pass'=>'heslo', 'email'=>'u2@example.com'); 320 $user2->id = $DB->insert_record('auth_db_users', $user2); 321 322 $auth->sync_users($trace, false); 323 $this->assertEquals(5, $DB->count_records('user')); 324 $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1))); 325 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); 326 327 328 // Test user_login(). 329 330 $user3 = (object)array('name'=>'u3', 'pass'=>'heslo', 'email'=>'u3@example.com'); 331 $user3->id = $DB->insert_record('auth_db_users', $user3); 332 333 $this->assertFalse($auth->user_login('u4', 'heslo')); 334 $this->assertTrue($auth->user_login('u1', 'heslo')); 335 336 $this->assertFalse($DB->record_exists('user', array('username'=>'u3', 'auth'=>'db'))); 337 $this->assertTrue($auth->user_login('u3', 'heslo')); 338 $this->assertFalse($DB->record_exists('user', array('username'=>'u3', 'auth'=>'db'))); 339 340 set_config('passtype', 'md5', 'auth_db'); 341 $auth->config->passtype = 'md5'; 342 $user3->pass = md5('heslo'); 343 $DB->update_record('auth_db_users', $user3); 344 $this->assertTrue($auth->user_login('u3', 'heslo')); 345 346 // Test user created to see if the checking happens strictly. 347 $usermd5 = (object)['name' => 'usermd5', 'pass' => '0e462097431906509019562988736854']; 348 $usermd5->id = $DB->insert_record('auth_db_users', $usermd5); 349 350 // md5('240610708') === '0e462097431906509019562988736854'. 351 $this->assertTrue($auth->user_login('usermd5', '240610708')); 352 $this->assertFalse($auth->user_login('usermd5', 'QNKCDZO')); 353 354 set_config('passtype', 'sh1', 'auth_db'); 355 $auth->config->passtype = 'sha1'; 356 $user3->pass = sha1('heslo'); 357 $DB->update_record('auth_db_users', $user3); 358 $this->assertTrue($auth->user_login('u3', 'heslo')); 359 360 // Test user created to see if the checking happens strictly. 361 $usersha1 = (object)['name' => 'usersha1', 'pass' => '0e66507019969427134894567494305185566735']; 362 $usersha1->id = $DB->insert_record('auth_db_users', $usersha1); 363 364 // sha1('aaroZmOk') === '0e66507019969427134894567494305185566735'. 365 $this->assertTrue($auth->user_login('usersha1', 'aaroZmOk')); 366 $this->assertFalse($auth->user_login('usersha1', 'aaK1STfY')); 367 368 set_config('passtype', 'saltedcrypt', 'auth_db'); 369 $auth->config->passtype = 'saltedcrypt'; 370 $user3->pass = password_hash('heslo', PASSWORD_BCRYPT); 371 $DB->update_record('auth_db_users', $user3); 372 $this->assertTrue($auth->user_login('u3', 'heslo')); 373 374 set_config('passtype', 'internal', 'auth_db'); 375 $auth->config->passtype = 'internal'; 376 create_user_record('u3', 'heslo', 'db'); 377 $this->assertTrue($auth->user_login('u3', 'heslo')); 378 379 380 $DB->delete_records('auth_db_users', array('id'=>$user3->id)); 381 382 set_config('removeuser', AUTH_REMOVEUSER_KEEP, 'auth_db'); 383 $auth->config->removeuser = AUTH_REMOVEUSER_KEEP; 384 $this->assertTrue($auth->user_login('u3', 'heslo')); 385 386 set_config('removeuser', AUTH_REMOVEUSER_SUSPEND, 'auth_db'); 387 $auth->config->removeuser = AUTH_REMOVEUSER_SUSPEND; 388 $this->assertFalse($auth->user_login('u3', 'heslo')); 389 390 set_config('removeuser', AUTH_REMOVEUSER_FULLDELETE, 'auth_db'); 391 $auth->config->removeuser = AUTH_REMOVEUSER_FULLDELETE; 392 $this->assertFalse($auth->user_login('u3', 'heslo')); 393 394 set_config('passtype', 'sh1', 'auth_db'); 395 $auth->config->passtype = 'sha1'; 396 $this->assertFalse($auth->user_login('u3', 'heslo')); 397 398 399 // Test login create and update. 400 401 $user4 = (object)array('name'=>'u4', 'pass'=>'heslo', 'email'=>'u4@example.com'); 402 $user4->id = $DB->insert_record('auth_db_users', $user4); 403 404 set_config('passtype', 'plaintext', 'auth_db'); 405 $auth->config->passtype = 'plaintext'; 406 407 $iuser4 = create_user_record('u4', 'heslo', 'db'); 408 $this->assertNotEmpty($iuser4); 409 $this->assertSame($user4->name, $iuser4->username); 410 $this->assertSame($user4->email, $iuser4->email); 411 $this->assertSame('db', $iuser4->auth); 412 $this->assertSame($CFG->mnet_localhost_id, $iuser4->mnethostid); 413 414 $user4b = clone($user4); 415 $user4b->email = 'u4b@example.com'; 416 $DB->update_record('auth_db_users', $user4b); 417 418 set_config('field_updatelocal_email', 'oncreate', 'auth_db'); 419 $auth->config->field_updatelocal_email = 'oncreate'; 420 421 update_user_record('u4'); 422 $iuser4 = $DB->get_record('user', array('id'=>$iuser4->id)); 423 $this->assertSame($user4->email, $iuser4->email); 424 425 set_config('field_updatelocal_email', 'onlogin', 'auth_db'); 426 $auth->config->field_updatelocal_email = 'onlogin'; 427 428 update_user_record('u4'); 429 $iuser4 = $DB->get_record('user', array('id'=>$iuser4->id)); 430 $this->assertSame($user4b->email, $iuser4->email); 431 432 433 // Test user_exists() 434 435 $this->assertTrue($auth->user_exists('u1')); 436 $this->assertTrue($auth->user_exists('admin')); 437 $this->assertFalse($auth->user_exists('u3')); 438 $this->assertTrue($auth->user_exists('u4')); 439 440 $this->cleanup_auth_database(); 441 } 442 443 /** 444 * Testing the function _colonscope() from ADOdb. 445 */ 446 public function test_adodb_colonscope() { 447 global $CFG; 448 require_once($CFG->libdir.'/adodb/adodb.inc.php'); 449 require_once($CFG->libdir.'/adodb/drivers/adodb-odbc.inc.php'); 450 require_once($CFG->libdir.'/adodb/drivers/adodb-db2ora.inc.php'); 451 452 $this->resetAfterTest(false); 453 454 $sql = "select * from table WHERE column=:1 AND anothercolumn > :0"; 455 $arr = array('b', 1); 456 list($sqlout, $arrout) = _colonscope($sql,$arr); 457 $this->assertEquals("select * from table WHERE column=? AND anothercolumn > ?", $sqlout); 458 $this->assertEquals(array(1, 'b'), $arrout); 459 } 460 461 /** 462 * Testing the clean_data() method. 463 */ 464 public function test_clean_data() { 465 global $DB; 466 467 $this->resetAfterTest(false); 468 $this->preventResetByRollback(); 469 $this->init_auth_database(); 470 $auth = get_auth_plugin('db'); 471 $auth->db_init(); 472 473 // Create users on external table. 474 $extdbuser1 = (object)array('name'=>'u1', 'pass'=>'heslo', 'email'=>'u1@example.com'); 475 $extdbuser1->id = $DB->insert_record('auth_db_users', $extdbuser1); 476 477 // User with malicious data on the name (won't be imported). 478 $extdbuser2 = (object)array('name'=>'user<script>alert(1);</script>xss', 'pass'=>'heslo', 'email'=>'xssuser@example.com'); 479 $extdbuser2->id = $DB->insert_record('auth_db_users', $extdbuser2); 480 481 $extdbuser3 = (object)array('name'=>'u3', 'pass'=>'heslo', 'email'=>'u3@example.com', 482 'lastname' => 'user<script>alert(1);</script>xss'); 483 $extdbuser3->id = $DB->insert_record('auth_db_users', $extdbuser3); 484 $trace = new \null_progress_trace(); 485 486 // Let's test user sync make sure still works as expected.. 487 $auth->sync_users($trace, true); 488 $this->assertDebuggingCalled("The property 'lastname' has invalid data and has been cleaned."); 489 // User with correct data, should be equal to external db. 490 $user1 = $DB->get_record('user', array('email'=> $extdbuser1->email, 'auth'=>'db')); 491 $this->assertEquals($extdbuser1->name, $user1->username); 492 $this->assertEquals($extdbuser1->email, $user1->email); 493 494 // Get the user on moodle user table. 495 $user2 = $DB->get_record('user', array('email'=> $extdbuser2->email, 'auth'=>'db')); 496 $user3 = $DB->get_record('user', array('email'=> $extdbuser3->email, 'auth'=>'db')); 497 498 $this->assertEmpty($user2); 499 $this->assertEquals($extdbuser3->name, $user3->username); 500 $this->assertEquals('useralert(1);xss', $user3->lastname); 501 502 $this->cleanup_auth_database(); 503 } 504 505 /** 506 * Testing the deletion of a user when there are many users in the external DB. 507 */ 508 public function test_deleting_with_many_users() { 509 global $DB; 510 511 $this->resetAfterTest(true); 512 $this->preventResetByRollback(); 513 $this->init_auth_database(); 514 $auth = get_auth_plugin('db'); 515 $auth->db_init(); 516 517 // Set to delete from moodle when missing from DB. 518 set_config('removeuser', AUTH_REMOVEUSER_FULLDELETE, 'auth_db'); 519 $auth->config->removeuser = AUTH_REMOVEUSER_FULLDELETE; 520 521 // Create users. 522 $users = []; 523 for ($i = 0; $i < $this->largedeletionsetsize; $i++) { 524 $user = (object)array('username' => "u$i", 'name' => "u$i", 'pass' => 'heslo', 'email' => "u$i@example.com"); 525 $user->id = $DB->insert_record('auth_db_users', $user); 526 $users[] = $user; 527 } 528 529 // Sync to moodle. 530 $trace = new \null_progress_trace(); 531 $auth->sync_users($trace, true); 532 533 // Check user is there. 534 $user = array_shift($users); 535 $moodleuser = $DB->get_record('user', array('email' => $user->email, 'auth' => 'db')); 536 $this->assertNotNull($moodleuser); 537 $this->assertEquals($user->username, $moodleuser->username); 538 539 // Delete a user. 540 $DB->delete_records('auth_db_users', array('id' => $user->id)); 541 542 // Sync again. 543 $auth->sync_users($trace, true); 544 545 // Check user is no longer there. 546 $moodleuser = $DB->get_record('user', array('id' => $moodleuser->id)); 547 $this->assertFalse($auth->user_login($user->username, 'heslo')); 548 $this->assertEquals(1, $moodleuser->deleted); 549 550 // Make sure it was the only user deleted. 551 $numberdeleted = $DB->count_records('user', array('deleted' => 1, 'auth' => 'db')); 552 $this->assertEquals(1, $numberdeleted); 553 554 $this->cleanup_auth_database(); 555 } 556 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body