Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
     */
11 efrain 34
    public function test_login_notification(): void {
1 efrain 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
     */
11 efrain 65
    public function test_login_notification_skip_same_ip(): void {
1 efrain 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
     */
11 efrain 93
    public function test_login_notification_skip_same_browser(): void {
1 efrain 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
     */
11 efrain 122
    public function test_login_notification_skip_mobileapp(): void {
1 efrain 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
     */
11 efrain 185
    public function test_mobile_app_login_notification(): void {
1 efrain 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
     */
11 efrain 235
    public function test_mobile_app_login_notification_skip_same_ip(): void {
1 efrain 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
     */
11 efrain 282
    public function test_mobile_app_login_notification_skip_same_device(): void {
1 efrain 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
}