Commit | Line | Data |
---|---|---|
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 | ||
27 | defined('MOODLE_INTERNAL') || die(); | |
28 | ||
29 | ||
30 | class 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 | } |