MDL-37304 cleanup auth_db and use progress_trace
[moodle.git] / auth / db / tests / db_test.php
CommitLineData
e7aeaa65
PS
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/**
18 * External database auth sync tests, this also tests adodb drivers
19 * that are matching our four supported Moodle database drivers.
20 *
21 * @package auth_db
22 * @category phpunit
23 * @copyright 2012 Petr Skoda {@link http://skodak.org}
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
27defined('MOODLE_INTERNAL') || die();
28
29
30class auth_db_testcase extends advanced_testcase {
31
32 protected function init_auth_database() {
33 global $DB, $CFG;
34 require_once("$CFG->dirroot/auth/db/auth.php");
35
36 $dbman = $DB->get_manager();
37
38 set_config('extencoding', 'utf-8', 'auth/db');
39
40 set_config('host', $CFG->dbhost, 'auth/db');
41 set_config('user', $CFG->dbuser, 'auth/db');
42 set_config('pass', $CFG->dbpass, 'auth/db');
43 set_config('name', $CFG->dbname, 'auth/db');
44
45 if (!empty($CFG->dboptions['dbport'])) {
46 set_config('host', $CFG->dbhost.':'.$CFG->dboptions['dbport'], 'auth/db');
47 }
48
49 switch (get_class($DB)) {
50 case 'mssql_native_moodle_database':
51 set_config('type', 'mssql_n', 'auth/db');
52 set_config('sybasequoting', '1', 'auth/db');
53 break;
54
55 case 'mysqli_native_moodle_database':
56 set_config('type', 'mysqli', 'auth/db');
57 set_config('setupsql', "SET NAMES 'UTF-8'", 'auth/db');
58 set_config('sybasequoting', '0', 'auth/db');
59 if (!empty($CFG->dboptions['dbsocket'])) {
60 $dbsocket = $CFG->dboptions['dbsocket'];
61 if ((strpos($dbsocket, '/') === false and strpos($dbsocket, '\\') === false)) {
62 $dbsocket = ini_get('mysqli.default_socket');
63 }
64 set_config('type', 'mysqli://'.rawurlencode($CFG->dbuser).':'.rawurlencode($CFG->dbpass).'@'.rawurlencode($CFG->dbhost).'/'.rawurlencode($CFG->dbname).'?socket='.rawurlencode($dbsocket), 'auth/db');
65 }
66 break;
67
68 case 'oci_native_moodle_database':
69 set_config('type', 'oci8po', 'auth/db');
70 set_config('sybasequoting', '1', 'auth/db');
71 break;
72
73 case 'pgsql_native_moodle_database':
74 set_config('type', 'postgres7', 'auth/db');
75 set_config('setupsql', "SET NAMES 'UTF-8'", 'auth/db');
76 set_config('sybasequoting', '0', 'auth/db');
77 if (!empty($CFG->dboptions['dbsocket']) and ($CFG->dbhost === 'localhost' or $CFG->dbhost === '127.0.0.1')) {
78 if (strpos($CFG->dboptions['dbsocket'], '/') !== false) {
79 set_config('host', $CFG->dboptions['dbsocket'], 'auth/db');
80 } else {
81 set_config('host', '', 'auth/db');
82 }
83 }
84 break;
85
86 case 'sqlsrv_native_moodle_database':
87 set_config('type', 'mssqlnative', 'auth/db');
88 set_config('sybasequoting', '1', 'auth/db');
89 break;
90
91 default:
92 throw new exception('Unknown database driver '.get_class($DB));
93 }
94
95 $table = new xmldb_table('auth_db_users');
96 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
97 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null);
98 $table->add_field('pass', XMLDB_TYPE_CHAR, '255', null, null, null);
99 $table->add_field('email', XMLDB_TYPE_CHAR, '255', null, null, null);
100 $table->add_field('firstname', XMLDB_TYPE_CHAR, '255', null, null, null);
101 $table->add_field('lastname', XMLDB_TYPE_CHAR, '255', null, null, null);
102 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
103 if ($dbman->table_exists($table)) {
104 $dbman->drop_table($table);
105 }
106 $dbman->create_table($table);
107 set_config('table', $CFG->prefix.'auth_db_users', 'auth/db');
108 set_config('fielduser', 'name', 'auth/db');
109 set_config('fieldpass', 'pass', 'auth/db');
110
111 // Setu up field mappings.
112
113 set_config('field_map_email', 'email', 'auth/db');
114 set_config('field_updatelocal_email', 'oncreate', 'auth/db');
115 set_config('field_updateremote_email', '0', 'auth/db');
116 set_config('field_lock_email', 'unlocked', 'auth/db');
117
118 // Init the rest of settings.
119 set_config('passtype', 'plaintext', 'auth/db');
120 set_config('changepasswordurl', '', 'auth/db');
121 set_config('debugauthdb', 0, 'auth/db');
122 set_config('removeuser', AUTH_REMOVEUSER_KEEP, 'auth/db');
123 }
124
125 protected function cleanup_auth_database() {
126 global $DB;
127
128 $dbman = $DB->get_manager();
129 $table = new xmldb_table('auth_db_users');
130 $dbman->drop_table($table);
131 }
132
133 public function test_plugin() {
134 global $DB, $CFG;
135
136 $this->resetAfterTest(false);
137
138 // NOTE: It is strongly discouraged to create new tables in advanced_testcase classes,
139 // but there is no other simple way to test ext database enrol sync, so let's
140 // disable transactions are try to cleanup after the tests.
141
142 $this->preventResetByRollback();
143
144 $this->init_auth_database();
145
146 /** @var auth_plugin_db $auth */
147 $auth = get_auth_plugin('db');
148
149 $authdb = $auth->db_init();
150
151
152 // Test adodb may access the table.
153
154 $user1 = (object)array('name'=>'u1', 'pass'=>'heslo', 'email'=>'u1@example.com');
155 $user1->id = $DB->insert_record('auth_db_users', $user1);
156
157
158 $sql = "SELECT * FROM {$auth->config->table}";
159 $rs = $authdb->Execute($sql);
160 $this->assertInstanceOf('ADORecordSet', $rs);
161 $this->assertFalse($rs->EOF);
162 $fields = $rs->FetchRow();
163 $this->assertTrue(is_array($fields));
164 $this->assertTrue($rs->EOF);
165 $rs->Close();
166
167 $authdb->Close();
168
169
170 // Test bulk user account creation.
171
172 $user2 = (object)array('name'=>'u2', 'pass'=>'heslo', 'email'=>'u2@example.com');
173 $user2->id = $DB->insert_record('auth_db_users', $user2);
174
175 $user3 = (object)array('name'=>'admin', 'pass'=>'heslo', 'email'=>'admin@example.com'); // Should be skipped.
176 $user3->id = $DB->insert_record('auth_db_users', $user3);
177
178 $this->assertCount(2, $DB->get_records('user'));
179
180 $trace = new null_progress_trace();
181 $auth->sync_users($trace, false);
182
183 $this->assertEquals(4, $DB->count_records('user'));
184 $u1 = $DB->get_record('user', array('username'=>$user1->name, 'auth'=>'db'));
185 $this->assertSame($user1->email, $u1->email);
186 $u2 = $DB->get_record('user', array('username'=>$user2->name, 'auth'=>'db'));
187 $this->assertSame($user2->email, $u2->email);
188 $admin = $DB->get_record('user', array('username'=>'admin', 'auth'=>'manual'));
189 $this->assertNotEmpty($admin);
190
191
192 // Test sync updates.
193
194 $user2b = clone($user2);
195 $user2b->email = 'u2b@example.com';
196 $DB->update_record('auth_db_users', $user2b);
197
198 $auth->sync_users($trace, false);
199 $this->assertEquals(4, $DB->count_records('user'));
200 $u2 = $DB->get_record('user', array('username'=>$user2->name));
201 $this->assertSame($user2->email, $u2->email);
202
203 $auth->sync_users($trace, true);
204 $this->assertEquals(4, $DB->count_records('user'));
205 $u2 = $DB->get_record('user', array('username'=>$user2->name));
206 $this->assertSame($user2->email, $u2->email);
207
208 set_config('field_updatelocal_email', 'onlogin', 'auth/db');
209 $auth->config->field_updatelocal_email = 'onlogin';
210
211 $auth->sync_users($trace, false);
212 $this->assertEquals(4, $DB->count_records('user'));
213 $u2 = $DB->get_record('user', array('username'=>$user2->name));
214 $this->assertSame($user2->email, $u2->email);
215
216 $auth->sync_users($trace, true);
217 $this->assertEquals(4, $DB->count_records('user'));
218 $u2 = $DB->get_record('user', array('username'=>$user2->name));
219 $this->assertSame($user2b->email, $u2->email);
220
221
222 // Test sync deletes and suspends.
223
224 $DB->delete_records('auth_db_users', array('id'=>$user2->id));
225 $this->assertCount(2, $DB->get_records('auth_db_users'));
226 unset($user2);
227 unset($user2b);
228
229 $auth->sync_users($trace, false);
230 $this->assertEquals(4, $DB->count_records('user'));
231 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
232 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
233
234 set_config('removeuser', AUTH_REMOVEUSER_SUSPEND, 'auth/db');
235 $auth->config->removeuser = AUTH_REMOVEUSER_SUSPEND;
236
237 $auth->sync_users($trace, false);
238 $this->assertEquals(4, $DB->count_records('user'));
239 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
240 $this->assertEquals(1, $DB->count_records('user', array('suspended'=>1)));
241
242 $user2 = (object)array('name'=>'u2', 'pass'=>'heslo', 'email'=>'u2@example.com');
243 $user2->id = $DB->insert_record('auth_db_users', $user2);
244
245 $auth->sync_users($trace, false);
246 $this->assertEquals(4, $DB->count_records('user'));
247 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
248 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
249
250 $DB->delete_records('auth_db_users', array('id'=>$user2->id));
251
252 set_config('removeuser', AUTH_REMOVEUSER_FULLDELETE, 'auth/db');
253 $auth->config->removeuser = AUTH_REMOVEUSER_FULLDELETE;
254
255 $auth->sync_users($trace, false);
256 $this->assertEquals(4, $DB->count_records('user'));
257 $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1)));
258 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
259
260 $user2 = (object)array('name'=>'u2', 'pass'=>'heslo', 'email'=>'u2@example.com');
261 $user2->id = $DB->insert_record('auth_db_users', $user2);
262
263 $auth->sync_users($trace, false);
264 $this->assertEquals(5, $DB->count_records('user'));
265 $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1)));
266 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
267
268
269 // Test user_login().
270
271 $user3 = (object)array('name'=>'u3', 'pass'=>'heslo', 'email'=>'u3@example.com');
272 $user3->id = $DB->insert_record('auth_db_users', $user3);
273
274 $this->assertFalse($auth->user_login('u4', 'heslo'));
275 $this->assertTrue($auth->user_login('u1', 'heslo'));
276
277 $this->assertFalse($DB->record_exists('user', array('username'=>'u3', 'auth'=>'db')));
278 $this->assertTrue($auth->user_login('u3', 'heslo'));
279 $this->assertFalse($DB->record_exists('user', array('username'=>'u3', 'auth'=>'db')));
280
281 set_config('passtype', 'md5', 'auth/db');
282 $auth->config->passtype = 'md5';
283 $user3->pass = md5('heslo');
284 $DB->update_record('auth_db_users', $user3);
285 $this->assertTrue($auth->user_login('u3', 'heslo'));
286
287 set_config('passtype', 'sh1', 'auth/db');
288 $auth->config->passtype = 'sha1';
289 $user3->pass = sha1('heslo');
290 $DB->update_record('auth_db_users', $user3);
291 $this->assertTrue($auth->user_login('u3', 'heslo'));
292
293 set_config('passtype', 'internal', 'auth/db');
294 $auth->config->passtype = 'internal';
295 create_user_record('u3', 'heslo', 'db');
296 $this->assertTrue($auth->user_login('u3', 'heslo'));
297
298
299 $DB->delete_records('auth_db_users', array('id'=>$user3->id));
300
301 set_config('removeuser', AUTH_REMOVEUSER_KEEP, 'auth/db');
302 $auth->config->removeuser = AUTH_REMOVEUSER_KEEP;
303 $this->assertTrue($auth->user_login('u3', 'heslo'));
304
305 set_config('removeuser', AUTH_REMOVEUSER_SUSPEND, 'auth/db');
306 $auth->config->removeuser = AUTH_REMOVEUSER_SUSPEND;
307 $this->assertFalse($auth->user_login('u3', 'heslo'));
308
309 set_config('removeuser', AUTH_REMOVEUSER_FULLDELETE, 'auth/db');
310 $auth->config->removeuser = AUTH_REMOVEUSER_FULLDELETE;
311 $this->assertFalse($auth->user_login('u3', 'heslo'));
312
313 set_config('passtype', 'sh1', 'auth/db');
314 $auth->config->passtype = 'sha1';
315 $this->assertFalse($auth->user_login('u3', 'heslo'));
316
317
318 // Test login create and update.
319
320 $user4 = (object)array('name'=>'u4', 'pass'=>'heslo', 'email'=>'u4@example.com');
321 $user4->id = $DB->insert_record('auth_db_users', $user4);
322
323 set_config('passtype', 'plaintext', 'auth/db');
324 $auth->config->passtype = 'plaintext';
325
326 $iuser4 = create_user_record('u4', 'heslo', 'db');
327 $this->assertNotEmpty($iuser4);
328 $this->assertSame($user4->name, $iuser4->username);
329 $this->assertSame($user4->email, $iuser4->email);
330 $this->assertSame('db', $iuser4->auth);
331 $this->assertSame($CFG->mnet_localhost_id, $iuser4->mnethostid);
332
333 $user4b = clone($user4);
334 $user4b->email = 'u4b@example.com';
335 $DB->update_record('auth_db_users', $user4b);
336
337 set_config('field_updatelocal_email', 'oncreate', 'auth/db');
338 $auth->config->field_updatelocal_email = 'oncreate';
339
340 update_user_record('u4');
341 $iuser4 = $DB->get_record('user', array('id'=>$iuser4->id));
342 $this->assertSame($user4->email, $iuser4->email);
343
344 set_config('field_updatelocal_email', 'onlogin', 'auth/db');
345 $auth->config->field_updatelocal_email = 'onlogin';
346
347 update_user_record('u4');
348 $iuser4 = $DB->get_record('user', array('id'=>$iuser4->id));
349 $this->assertSame($user4b->email, $iuser4->email);
350
351
352 // Test user_exists()
353
354 $this->assertTrue($auth->user_exists('u1'));
355 $this->assertTrue($auth->user_exists('admin'));
356 $this->assertFalse($auth->user_exists('u3'));
357 $this->assertTrue($auth->user_exists('u4'));
358
359 $this->cleanup_auth_database();
360 }
361}