/login/tests/notifications_test.php

https://github.com/kordan/moodle · PHP · 271 lines · 158 code · 49 blank · 64 comment · 0 complexity · 683b2ba421d79f5611f8e200568b0c93 MD5 · raw file

  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. * Contains tests for course related notifications.
  18. *
  19. * @package core
  20. * @copyright 2021 Juan Leyva <juan@moodle.com>
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. class core_login_notifications_testcase extends \advanced_testcase {
  24. /**
  25. * Test new login notification.
  26. */
  27. public function test_login_notification() {
  28. global $SESSION;
  29. $this->resetAfterTest();
  30. $loginuser = self::getDataGenerator()->create_user();
  31. $this->setUser(0);
  32. // Mock data for test.
  33. $loginuser->lastip = '1.2.3.4.6'; // Different ip that current.
  34. $SESSION->isnewsessioncookie = true; // New session cookie.
  35. @complete_user_login($loginuser);
  36. // Redirect messages to sink and stop buffer output from CLI task.
  37. $sink = $this->redirectMessages();
  38. ob_start();
  39. $this->runAdhocTasks('\core\task\send_login_notifications');
  40. $output = ob_get_contents();
  41. ob_end_clean();
  42. $messages = $sink->get_messages();
  43. $sink->close();
  44. // Send notification, new IP and new session.
  45. $this->assertCount(1, $messages);
  46. $this->assertEquals($loginuser->id, $messages[0]->useridto);
  47. $this->assertEquals('newlogin', $messages[0]->eventtype);
  48. }
  49. /**
  50. * Test new login notification is skipped because of same IP from last login.
  51. */
  52. public function test_login_notification_skip_same_ip() {
  53. global $SESSION;
  54. $this->resetAfterTest();
  55. $loginuser = self::getDataGenerator()->create_user();
  56. $this->setUser(0);
  57. // Mock data for test.
  58. $SESSION->isnewsessioncookie = true; // New session cookie.
  59. @complete_user_login($loginuser);
  60. // Redirect messages to sink and stop buffer output from CLI task.
  61. $sink = $this->redirectMessages();
  62. ob_start();
  63. $this->runAdhocTasks('\core\task\send_login_notifications');
  64. $output = ob_get_contents();
  65. ob_end_clean();
  66. $messages = $sink->get_messages();
  67. $sink->close();
  68. // Skip notification when we have the same previous IP even if the browser used to connect is new.
  69. $this->assertCount(0, $messages);
  70. }
  71. /**
  72. * Test new login notification is skipped because of same browser from last login.
  73. */
  74. public function test_login_notification_skip_same_browser() {
  75. global $SESSION;
  76. $this->resetAfterTest();
  77. $loginuser = self::getDataGenerator()->create_user();
  78. $this->setUser(0);
  79. // Mock data for test.
  80. $loginuser->lastip = '1.2.3.4.6'; // Different ip that current.
  81. $SESSION->isnewsessioncookie = false;
  82. @complete_user_login($loginuser);
  83. // Redirect messages to sink and stop buffer output from CLI task.
  84. $sink = $this->redirectMessages();
  85. ob_start();
  86. $this->runAdhocTasks('\core\task\send_login_notifications');
  87. $output = ob_get_contents();
  88. ob_end_clean();
  89. $messages = $sink->get_messages();
  90. $sink->close();
  91. // Skip notification, different ip but same browser (probably, mobile phone browser).
  92. $this->assertCount(0, $messages);
  93. }
  94. /**
  95. * Test new login notification is skipped because of auto-login from the mobile app (skip duplicated notifications).
  96. */
  97. public function test_login_notification_skip_mobileapp() {
  98. global $SESSION;
  99. $this->resetAfterTest();
  100. $loginuser = self::getDataGenerator()->create_user();
  101. $this->setUser(0);
  102. // Mock data for test.
  103. $loginuser->lastip = '1.2.3.4.6'; // Different ip that current.
  104. $SESSION->isnewsessioncookie = true; // New session cookie.
  105. core_useragent::instance(true, 'MoodleMobile'); // Force fake mobile app user agent.
  106. @complete_user_login($loginuser);
  107. // Redirect messages to sink and stop buffer output from CLI task.
  108. $sink = $this->redirectMessages();
  109. ob_start();
  110. $this->runAdhocTasks('\core\task\send_login_notifications');
  111. $output = ob_get_contents();
  112. ob_end_clean();
  113. $messages = $sink->get_messages();
  114. $sink->close();
  115. $this->assertCount(0, $messages);
  116. }
  117. /**
  118. * Test new mobile app login notification.
  119. */
  120. public function test_mobile_app_login_notification() {
  121. global $USER, $DB, $SESSION;
  122. $this->resetAfterTest();
  123. $loginuser = self::getDataGenerator()->create_user();
  124. $this->setUser($loginuser);
  125. // Mock data for test.
  126. $USER->lastip = '1.2.3.4.6'; // Different ip that current.
  127. $service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE));
  128. $token = external_generate_token_for_current_user($service);
  129. core_useragent::instance(true, 'MoodleMobile'); // Force fake mobile app user agent.
  130. // Simulate we are using an new device.
  131. $fakedevice = (object) [
  132. 'userid' => $USER->id,
  133. 'appid' => 'com.moodle.moodlemobile',
  134. 'name' => 'occam',
  135. 'model' => 'Nexus 4',
  136. 'platform' => 'Android',
  137. 'version' => '4.2.2',
  138. 'pushid' => 'kishUhd',
  139. 'uuid' => 'KIhud7s',
  140. 'timecreated' => time() + MINSECS,
  141. 'timemodified' => time() + MINSECS
  142. ];
  143. $DB->insert_record('user_devices', $fakedevice);
  144. external_log_token_request($token);
  145. // Redirect messages to sink and stop buffer output from CLI task.
  146. $sink = $this->redirectMessages();
  147. ob_start();
  148. $this->runAdhocTasks('\core\task\send_login_notifications');
  149. $output = ob_get_contents();
  150. ob_end_clean();
  151. $messages = $sink->get_messages();
  152. $sink->close();
  153. // We sent a login notification because we are using a new device and different IP.
  154. $this->assertCount(1, $messages);
  155. $this->assertEquals($loginuser->id, $messages[0]->useridto);
  156. $this->assertEquals('newlogin', $messages[0]->eventtype);
  157. }
  158. /**
  159. * Test new mobile app login notification skipped becase of same last ip.
  160. */
  161. public function test_mobile_app_login_notification_skip_same_ip() {
  162. global $USER, $DB, $SESSION;
  163. $this->resetAfterTest();
  164. $loginuser = self::getDataGenerator()->create_user();
  165. $this->setUser($loginuser);
  166. // Mock data for test.
  167. $USER->lastip = '0.0.0.0';
  168. $service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE));
  169. $token = external_generate_token_for_current_user($service);
  170. core_useragent::instance(true, 'MoodleMobile'); // Force fake mobile app user agent.
  171. // Simulate we are using an new device.
  172. $fakedevice = (object) [
  173. 'userid' => $USER->id,
  174. 'appid' => 'com.moodle.moodlemobile',
  175. 'name' => 'occam',
  176. 'model' => 'Nexus 4',
  177. 'platform' => 'Android',
  178. 'version' => '4.2.2',
  179. 'pushid' => 'kishUhd',
  180. 'uuid' => 'KIhud7s',
  181. 'timecreated' => time() + MINSECS,
  182. 'timemodified' => time() + MINSECS
  183. ];
  184. $DB->insert_record('user_devices', $fakedevice);
  185. external_log_token_request($token);
  186. // Redirect messages to sink and stop buffer output from CLI task.
  187. $sink = $this->redirectMessages();
  188. ob_start();
  189. $this->runAdhocTasks('\core\task\send_login_notifications');
  190. $output = ob_get_contents();
  191. ob_end_clean();
  192. $messages = $sink->get_messages();
  193. $sink->close();
  194. // While using the same IP avoid sending new login notifications even if we are using a new device.
  195. $this->assertCount(0, $messages);
  196. }
  197. /**
  198. * Test new mobile app login notification skipped becase of same device.
  199. */
  200. public function test_mobile_app_login_notification_skip_same_device() {
  201. global $USER, $DB, $SESSION;
  202. $this->resetAfterTest();
  203. $loginuser = self::getDataGenerator()->create_user();
  204. $this->setUser($loginuser);
  205. // Mock data for test.
  206. $USER->lastip = '1.2.3.4.6'; // New ip.
  207. $service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE));
  208. $token = external_generate_token_for_current_user($service);
  209. core_useragent::instance(true, 'MoodleMobile'); // Force fake mobile app user agent.
  210. external_log_token_request($token);
  211. // Redirect messages to sink and stop buffer output from CLI task.
  212. $sink = $this->redirectMessages();
  213. ob_start();
  214. $this->runAdhocTasks('\core\task\send_login_notifications');
  215. $output = ob_get_contents();
  216. ob_end_clean();
  217. $messages = $sink->get_messages();
  218. $sink->close();
  219. // While using the same device avoid sending new login notifications even if the IP changes.
  220. $this->assertCount(0, $messages);
  221. }
  222. }