Differences Between: [Versions 401 and 402]
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 core\task; 18 19 use moodle_url; 20 21 /** 22 * Contains tests for login related notifications. 23 * 24 * @package core 25 * @copyright 2021 Juan Leyva <juan@moodle.com> 26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 * @covers \core\task\send_login_notifications 28 */ 29 class send_login_notifications_test extends \advanced_testcase { 30 31 /** 32 * Test new login notification. 33 */ 34 public function test_login_notification() { 35 global $SESSION; 36 37 $this->resetAfterTest(); 38 39 $loginuser = self::getDataGenerator()->create_user(); 40 $this->setUser(0); 41 42 // Mock data for test. 43 $loginuser->lastip = '1.2.3.4.6'; // Different ip that current. 44 $SESSION->isnewsessioncookie = true; // New session cookie. 45 @complete_user_login($loginuser); 46 47 // Redirect messages to sink and stop buffer output from CLI task. 48 $sink = $this->redirectMessages(); 49 ob_start(); 50 $this->runAdhocTasks('\core\task\send_login_notifications'); 51 $output = ob_get_contents(); 52 ob_end_clean(); 53 $messages = $sink->get_messages(); 54 $sink->close(); 55 56 // Send notification, new IP and new session. 57 $this->assertCount(1, $messages); 58 $this->assertEquals($loginuser->id, $messages[0]->useridto); 59 $this->assertEquals('newlogin', $messages[0]->eventtype); 60 } 61 62 /** 63 * Test new login notification is skipped because of same IP from last login. 64 */ 65 public function test_login_notification_skip_same_ip() { 66 global $SESSION; 67 68 $this->resetAfterTest(); 69 70 $loginuser = self::getDataGenerator()->create_user(); 71 $this->setUser(0); 72 73 // Mock data for test. 74 $SESSION->isnewsessioncookie = true; // New session cookie. 75 @complete_user_login($loginuser); 76 77 // Redirect messages to sink and stop buffer output from CLI task. 78 $sink = $this->redirectMessages(); 79 ob_start(); 80 $this->runAdhocTasks('\core\task\send_login_notifications'); 81 $output = ob_get_contents(); 82 ob_end_clean(); 83 $messages = $sink->get_messages(); 84 $sink->close(); 85 86 // Skip notification when we have the same previous IP even if the browser used to connect is new. 87 $this->assertCount(0, $messages); 88 } 89 90 /** 91 * Test new login notification is skipped because of same browser from last login. 92 */ 93 public function test_login_notification_skip_same_browser() { 94 global $SESSION; 95 96 $this->resetAfterTest(); 97 98 $loginuser = self::getDataGenerator()->create_user(); 99 $this->setUser(0); 100 101 // Mock data for test. 102 $loginuser->lastip = '1.2.3.4.6'; // Different ip that current. 103 $SESSION->isnewsessioncookie = false; 104 @complete_user_login($loginuser); 105 106 // Redirect messages to sink and stop buffer output from CLI task. 107 $sink = $this->redirectMessages(); 108 ob_start(); 109 $this->runAdhocTasks('\core\task\send_login_notifications'); 110 $output = ob_get_contents(); 111 ob_end_clean(); 112 $messages = $sink->get_messages(); 113 $sink->close(); 114 115 // Skip notification, different ip but same browser (probably, mobile phone browser). 116 $this->assertCount(0, $messages); 117 } 118 119 /** 120 * Test new login notification is skipped because of auto-login from the mobile app (skip duplicated notifications). 121 */ 122 public function test_login_notification_skip_mobileapp() { 123 global $SESSION; 124 125 $this->resetAfterTest(); 126 127 $loginuser = self::getDataGenerator()->create_user(); 128 $this->setUser(0); 129 130 // Mock data for test. 131 $loginuser->lastip = '1.2.3.4.6'; // Different ip that current. 132 $SESSION->isnewsessioncookie = true; // New session cookie. 133 \core_useragent::instance(true, 'MoodleMobile'); // Force fake mobile app user agent. 134 @complete_user_login($loginuser); 135 136 // Redirect messages to sink and stop buffer output from CLI task. 137 $sink = $this->redirectMessages(); 138 ob_start(); 139 $this->runAdhocTasks('\core\task\send_login_notifications'); 140 $output = ob_get_contents(); 141 ob_end_clean(); 142 $messages = $sink->get_messages(); 143 $sink->close(); 144 145 $this->assertCount(0, $messages); 146 } 147 148 /** 149 * Test new login notification where the user auth method provides a custom change password URL 150 */ 151 public function test_login_notification_custom_change_password_url(): void { 152 global $SESSION; 153 154 $this->resetAfterTest(); 155 $this->setUser(0); 156 157 // Set LDAP auth change password URL. 158 $changepasswordurl = (new moodle_url('/changepassword.php'))->out(false); 159 set_config('changepasswordurl', $changepasswordurl, 'auth_ldap'); 160 161 $ldapuser = $this->getDataGenerator()->create_user(['auth' => 'ldap']); 162 163 // Mock data for test. 164 $ldapuser->lastip = '1.2.3.4'; 165 $SESSION->isnewsessioncookie = true; 166 @complete_user_login($ldapuser); 167 168 // Redirect messages to sink and stop buffer output from CLI task. 169 $sink = $this->redirectMessages(); 170 ob_start(); 171 $this->runAdhocTasks(send_login_notifications::class); 172 ob_end_clean(); 173 $messages = $sink->get_messages(); 174 $sink->close(); 175 176 // Send notification, assert custom change password URL is present. 177 $this->assertCount(1, $messages); 178 $this->assertStringContainsString("If you don't recognise this activity, please " . 179 "<a href=\"{$changepasswordurl}\">change your password</a>.", $messages[0]->fullmessagehtml); 180 } 181 182 /** 183 * Test new mobile app login notification. 184 */ 185 public function test_mobile_app_login_notification() { 186 global $USER, $DB, $SESSION; 187 188 $this->resetAfterTest(); 189 190 $loginuser = self::getDataGenerator()->create_user(); 191 $this->setUser($loginuser); 192 193 // Mock data for test. 194 $USER->lastip = '1.2.3.4.6'; // Different ip that current. 195 196 $service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE)); 197 $token = \core_external\util::generate_token_for_current_user($service); 198 \core_useragent::instance(true, 'MoodleMobile'); // Force fake mobile app user agent. 199 200 // Simulate we are using an new device. 201 $fakedevice = (object) [ 202 'userid' => $USER->id, 203 'appid' => 'com.moodle.moodlemobile', 204 'name' => 'occam', 205 'model' => 'Nexus 4', 206 'platform' => 'Android', 207 'version' => '4.2.2', 208 'pushid' => 'kishUhd', 209 'uuid' => 'KIhud7s', 210 'timecreated' => time() + MINSECS, 211 'timemodified' => time() + MINSECS 212 ]; 213 $DB->insert_record('user_devices', $fakedevice); 214 215 \core_external\util::log_token_request($token); 216 217 // Redirect messages to sink and stop buffer output from CLI task. 218 $sink = $this->redirectMessages(); 219 ob_start(); 220 $this->runAdhocTasks('\core\task\send_login_notifications'); 221 $output = ob_get_contents(); 222 ob_end_clean(); 223 $messages = $sink->get_messages(); 224 $sink->close(); 225 226 // We sent a login notification because we are using a new device and different IP. 227 $this->assertCount(1, $messages); 228 $this->assertEquals($loginuser->id, $messages[0]->useridto); 229 $this->assertEquals('newlogin', $messages[0]->eventtype); 230 } 231 232 /** 233 * Test new mobile app login notification skipped becase of same last ip. 234 */ 235 public function test_mobile_app_login_notification_skip_same_ip() { 236 global $USER, $DB, $SESSION; 237 238 $this->resetAfterTest(); 239 240 $loginuser = self::getDataGenerator()->create_user(); 241 $this->setUser($loginuser); 242 243 // Mock data for test. 244 $USER->lastip = '0.0.0.0'; 245 $service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE)); 246 $token = \core_external\util::generate_token_for_current_user($service); 247 \core_useragent::instance(true, 'MoodleMobile'); // Force fake mobile app user agent. 248 249 // Simulate we are using an new device. 250 $fakedevice = (object) [ 251 'userid' => $USER->id, 252 'appid' => 'com.moodle.moodlemobile', 253 'name' => 'occam', 254 'model' => 'Nexus 4', 255 'platform' => 'Android', 256 'version' => '4.2.2', 257 'pushid' => 'kishUhd', 258 'uuid' => 'KIhud7s', 259 'timecreated' => time() + MINSECS, 260 'timemodified' => time() + MINSECS 261 ]; 262 $DB->insert_record('user_devices', $fakedevice); 263 264 \core_external\util::log_token_request($token); 265 266 // Redirect messages to sink and stop buffer output from CLI task. 267 $sink = $this->redirectMessages(); 268 ob_start(); 269 $this->runAdhocTasks('\core\task\send_login_notifications'); 270 $output = ob_get_contents(); 271 ob_end_clean(); 272 $messages = $sink->get_messages(); 273 $sink->close(); 274 275 // While using the same IP avoid sending new login notifications even if we are using a new device. 276 $this->assertCount(0, $messages); 277 } 278 279 /** 280 * Test new mobile app login notification skipped becase of same device. 281 */ 282 public function test_mobile_app_login_notification_skip_same_device() { 283 global $USER, $DB, $SESSION; 284 285 $this->resetAfterTest(); 286 287 $loginuser = self::getDataGenerator()->create_user(); 288 $this->setUser($loginuser); 289 290 // Mock data for test. 291 $USER->lastip = '1.2.3.4.6'; // New ip. 292 $service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE)); 293 $token = \core_external\util::generate_token_for_current_user($service); 294 \core_useragent::instance(true, 'MoodleMobile'); // Force fake mobile app user agent. 295 296 \core_external\util::log_token_request($token); 297 298 // Redirect messages to sink and stop buffer output from CLI task. 299 $sink = $this->redirectMessages(); 300 ob_start(); 301 $this->runAdhocTasks('\core\task\send_login_notifications'); 302 $output = ob_get_contents(); 303 ob_end_clean(); 304 $messages = $sink->get_messages(); 305 $sink->close(); 306 307 // While using the same device avoid sending new login notifications even if the IP changes. 308 $this->assertCount(0, $messages); 309 } 310 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body