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
 
1391 ariadna 3
// Este archivo es parte de Moodle - http://moodle.org/
1 efrain 4
//
1391 ariadna 5
// Moodle es software libre: puedes redistribuirlo y/o modificarlo
6
// bajo los términos de la Licencia Pública General GNU publicada por
7
// la Free Software Foundation, ya sea la versión 3 de la Licencia, o
8
// (a tu elección) cualquier versión posterior.
1 efrain 9
//
1391 ariadna 10
// Moodle se distribuye con la esperanza de que sea útil,
11
// pero SIN NINGUNA GARANTÍA; sin siquiera la garantía implícita de
12
// COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Ver la
13
// Licencia Pública General GNU para más detalles.
1 efrain 14
//
1391 ariadna 15
// Deberías haber recibido una copia de la Licencia Pública General GNU
16
// junto con Moodle. Si no, ve <http://www.gnu.org/licenses/>.
1 efrain 17
 
18
/**
1391 ariadna 19
 * Página principal de inicio de sesión de Moodle.
20
 * Este archivo maneja todo el proceso de autenticación de usuarios,
21
 * incluyendo la validación de credenciales, manejo de sesiones,
22
 * redirecciones y mensajes de error.
1 efrain 23
 *
24
 * @package    core
25
 * @subpackage auth
26
 * @copyright  1999 onwards Martin Dougiamas  http://dougiamas.com
27
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28
 */
29
 
1391 ariadna 30
// Incluir archivos de configuración y librerías necesarias
1 efrain 31
require('../config.php');
32
require_once('lib.php');
33
 
1391 ariadna 34
// Verificar si se requiere una actualización mayor del sistema
35
// Si es así, redirigir al usuario a la página de actualización
1 efrain 36
redirect_if_major_upgrade_required();
37
 
1391 ariadna 38
// ============================================================================
39
// PARÁMETROS DE LA PÁGINA DE INICIO DE SESIÓN
40
// ============================================================================
1 efrain 41
 
1391 ariadna 42
// Parámetros opcionales que controlan el comportamiento del inicio de sesión
43
$testsession = optional_param('testsession', 0, PARAM_INT);     // Verifica el funcionamiento correcto de la sesión
44
$anchor = optional_param('anchor', '', PARAM_RAW);              // Mantiene la posición del ancla en la URL de destino
45
$loginredirect = optional_param('loginredirect', 1, PARAM_BOOL); // Controla la redirección a URL de login alternativo
46
$resendconfirmemail = optional_param('resendconfirmemail', false, PARAM_BOOL); // Permite reenviar email de confirmación
1 efrain 47
 
1391 ariadna 48
// Verificación especial para sitios Behat (entorno de pruebas)
49
// Esto podría ser seguro para sitios no-Behat, pero por ahora solo lo permitimos en sitios Behat
1 efrain 50
if (defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) {
1391 ariadna 51
    $wantsurl = optional_param('wantsurl', '', PARAM_LOCALURL);   // Sobrescribe $SESSION->wantsurl si se proporciona
1 efrain 52
    if ($wantsurl !== '') {
53
        $SESSION->wantsurl = (new moodle_url($wantsurl))->out(false);
54
    }
55
}
56
 
1391 ariadna 57
// Configuración del contexto y la página
1 efrain 58
$context = context_system::instance();
59
$PAGE->set_url("$CFG->wwwroot/login/index.php");
60
$PAGE->set_context($context);
61
$PAGE->set_pagelayout('login');
62
 
1391 ariadna 63
// ============================================================================
64
// CONFIGURACIÓN INICIAL Y VARIABLES
65
// ============================================================================
1 efrain 66
 
1391 ariadna 67
// Inicialización de variables para el manejo de mensajes y errores
68
$errormsg = '';    // Almacena mensajes de error para mostrar al usuario
69
$infomsg = '';     // Almacena mensajes informativos para mostrar al usuario
70
$errorcode = 0;    // Código numérico que identifica el tipo de error
71
 
72
// ============================================================================
73
// VERIFICACIÓN DE SESIÓN
74
// ============================================================================
75
 
76
// Prueba de funcionamiento de la sesión
1 efrain 77
if ($testsession) {
78
    if ($testsession == $USER->id) {
1391 ariadna 79
        // Si la sesión es válida, redirigir a la URL deseada
1 efrain 80
        if (isset($SESSION->wantsurl)) {
81
            $urltogo = $SESSION->wantsurl;
82
        } else {
1391 ariadna 83
            $urltogo = $CFG->wwwroot . '/';
1 efrain 84
        }
85
        unset($SESSION->wantsurl);
86
        redirect($urltogo);
87
    } else {
1391 ariadna 88
        // Si la sesión no es válida, mostrar error de cookies
1 efrain 89
        $errormsg = get_string("cookiesnotenabled");
90
        $errorcode = 1;
91
    }
92
}
93
 
1391 ariadna 94
// ============================================================================
95
// MANEJO DE SESIONES EXPIRADAS
96
// ============================================================================
97
 
98
// Verificar si la sesión actual ha expirado
1 efrain 99
if (!empty($SESSION->has_timed_out)) {
100
    $session_has_timed_out = true;
101
    unset($SESSION->has_timed_out);
102
} else {
103
    $session_has_timed_out = false;
104
}
105
 
1391 ariadna 106
// Inicialización de variables para el formulario y usuario
107
$frm = false;
1 efrain 108
$user = false;
109
 
1391 ariadna 110
// Obtener la secuencia de plugins de autenticación habilitados
111
$authsequence = get_enabled_auth_plugins();
112
foreach ($authsequence as $authname) {
1 efrain 113
    $authplugin = get_auth_plugin($authname);
1391 ariadna 114
    // El hook loginpage_hook() del plugin de autenticación puede establecer $frm y/o $user
1 efrain 115
    $authplugin->loginpage_hook();
116
}
117
 
1391 ariadna 118
// ============================================================================
119
// CONFIGURACIÓN DEL SITIO Y NAVEGACIÓN
120
// ============================================================================
1 efrain 121
 
1391 ariadna 122
// Obtener información del sitio
1 efrain 123
$site = get_site();
124
 
1391 ariadna 125
// Ignorar páginas activas en la navegación/configuración
1 efrain 126
$PAGE->navbar->ignore_active();
127
$loginsite = get_string("loginsite");
128
$PAGE->navbar->add($loginsite);
129
 
1391 ariadna 130
// ============================================================================
131
// PROCESO DE AUTENTICACIÓN
132
// ============================================================================
133
 
134
// Verificar si algún plugin de autenticación ya proporcionó el usuario completo
1 efrain 135
if ($user !== false or $frm !== false or $errormsg !== '') {
1391 ariadna 136
    // El plugin de autenticación ya proporcionó el usuario completo, datos del formulario falso
137
    // o impidió el inicio de sesión con mensaje de error
138
} else if (!empty($SESSION->wantsurl) && file_exists($CFG->dirroot . '/login/weblinkauth.php')) {
139
    // Maneja el caso de otro sitio Moodle vinculando a una página en este sitio
140
    include($CFG->dirroot . '/login/weblinkauth.php');
1 efrain 141
    if (function_exists('weblink_auth')) {
142
        $user = weblink_auth($SESSION->wantsurl);
143
    }
144
    if ($user) {
145
        $frm->username = $user->username;
146
    } else {
147
        $frm = data_submitted();
148
    }
149
} else {
150
    $frm = data_submitted();
151
}
152
 
1391 ariadna 153
// Restaurar el #anchor a la wantsurl original
1 efrain 154
if ($anchor && isset($SESSION->wantsurl) && strpos($SESSION->wantsurl, '#') === false) {
155
    $wantsurl = new moodle_url($SESSION->wantsurl);
156
    $wantsurl->set_anchor(substr($anchor, 1));
157
    $SESSION->wantsurl = $wantsurl->out();
158
}
159
 
1391 ariadna 160
// ============================================================================
161
// VERIFICACIÓN DE CREDENCIALES
162
// ============================================================================
1 efrain 163
 
1391 ariadna 164
// Verificar si el usuario ha enviado datos de inicio de sesión
165
if ($frm and isset($frm->username)) {
166
    // Normalizar el nombre de usuario
1 efrain 167
    $frm->username = trim(core_text::strtolower($frm->username));
168
 
1391 ariadna 169
    // Verificar la autenticación 'none' si está habilitada
170
    if (is_enabled_auth('none')) {
1 efrain 171
        if ($frm->username !== core_user::clean_field($frm->username, 'username')) {
1391 ariadna 172
            $errormsg = get_string('username') . ': ' . get_string("invalidusername");
1 efrain 173
            $errorcode = 2;
174
            $user = null;
175
        }
176
    }
177
 
1391 ariadna 178
    // Verificar si el usuario es invitado
1 efrain 179
    if ($user) {
1391 ariadna 180
        // El plugin de autenticación ya proporcionó el usuario
1 efrain 181
    } else if (($frm->username == 'guest') and empty($CFG->guestloginbutton)) {
1391 ariadna 182
        $user = false;    // No se puede iniciar sesión como invitado si el botón de invitado está deshabilitado
1 efrain 183
        $frm = false;
184
    } else {
185
        if (empty($errormsg)) {
1391 ariadna 186
            // Intentar autenticar al usuario
1 efrain 187
            $logintoken = isset($frm->logintoken) ? $frm->logintoken : '';
188
            $loginrecaptcha = login_captcha_enabled() ? $frm->{'g-recaptcha-response'} ?? '' : false;
189
            $user = authenticate_user_login($frm->username, $frm->password, false, $errorcode, $logintoken, $loginrecaptcha);
190
        }
191
    }
192
 
1391 ariadna 193
    // ============================================================================
194
    // MANEJO DE USUARIOS RESTAURADOS
195
    // ============================================================================
196
 
197
    // Procesar usuarios que han sido restaurados desde una copia de seguridad
1 efrain 198
    if (!$user and $frm and is_restored_user($frm->username)) {
199
        $PAGE->set_title(get_string('restoredaccount'));
200
        $PAGE->set_heading($site->fullname);
201
        echo $OUTPUT->header();
202
        echo $OUTPUT->heading(get_string('restoredaccount'));
203
        echo $OUTPUT->box(get_string('restoredaccountinfo'), 'generalbox boxaligncenter');
1391 ariadna 204
        require_once('restored_password_form.php');
1 efrain 205
        $form = new login_forgot_password_form('forgot_password.php', array('username' => $frm->username));
206
        $form->display();
207
        echo $OUTPUT->footer();
208
        die;
209
    }
210
 
1391 ariadna 211
    // ============================================================================
212
    // CONFIRMACIÓN DE CUENTA
213
    // ============================================================================
214
 
1 efrain 215
    if ($user) {
1391 ariadna 216
        // Configuración del idioma
1 efrain 217
        if (isguestuser($user)) {
1391 ariadna 218
            // Sin idioma predefinido para invitados - usar sesión existente o idioma predeterminado del sitio
1 efrain 219
            unset($user->lang);
220
        } else if (!empty($user->lang)) {
1391 ariadna 221
            // Desactivar idioma de sesión anterior - usar preferencia del usuario
1 efrain 222
            unset($SESSION->lang);
223
        }
224
 
1391 ariadna 225
        // Verificar si la cuenta nunca fue confirmada
226
        if (empty($user->confirmed)) {
1 efrain 227
            $PAGE->set_title(get_string("mustconfirm"));
228
            $PAGE->set_heading($site->fullname);
229
            echo $OUTPUT->header();
230
            echo $OUTPUT->heading(get_string("mustconfirm"));
231
            if ($resendconfirmemail) {
232
                if (!send_confirmation_email($user)) {
233
                    echo $OUTPUT->notification(get_string('emailconfirmsentfailure'), \core\output\notification::NOTIFY_ERROR);
234
                } else {
235
                    echo $OUTPUT->notification(get_string('emailconfirmsentsuccess'), \core\output\notification::NOTIFY_SUCCESS);
236
                }
237
            }
238
            echo $OUTPUT->box(get_string("emailconfirmsent", "", s($user->email)), "generalbox boxaligncenter");
1391 ariadna 239
            $resendconfirmurl = new moodle_url(
240
                '/login/index.php',
1 efrain 241
                [
242
                    'username' => $frm->username,
243
                    'password' => $frm->password,
244
                    'resendconfirmemail' => true,
245
                    'logintoken' => \core\session\manager::get_login_token()
246
                ]
247
            );
248
            echo $OUTPUT->single_button($resendconfirmurl, get_string('emailconfirmationresend'));
249
            echo $OUTPUT->footer();
250
            die;
251
        }
252
 
1391 ariadna 253
        // ============================================================================
254
        // COMPLETAR INICIO DE SESIÓN
255
        // ============================================================================
256
 
257
        // Completar el proceso de inicio de sesión
1 efrain 258
        complete_user_login($user);
259
 
1391 ariadna 260
        // Aplicar límite de inicio de sesión concurrente
1 efrain 261
        \core\session\manager::apply_concurrent_login_limit($user->id, session_id());
262
 
1391 ariadna 263
        // Configurar cookie de nombre de usuario
1 efrain 264
        if (!empty($CFG->nolastloggedin)) {
1391 ariadna 265
            // No almacenar último usuario conectado en cookie
1 efrain 266
        } else if (empty($CFG->rememberusername)) {
1391 ariadna 267
            // Sin cookies permanentes, eliminar la anterior si existe
1 efrain 268
            set_moodle_cookie('');
269
        } else {
270
            set_moodle_cookie($USER->username);
271
        }
272
 
1391 ariadna 273
        // Obtener URL de redirección
1 efrain 274
        $urltogo = core_login_get_return_url();
275
 
1391 ariadna 276
        // ============================================================================
277
        // VERIFICACIÓN DE CONTRASEÑAS EXPIRADAS
278
        // ============================================================================
279
 
280
        // Verificar si la contraseña del usuario ha expirado (solo para autenticación LDAP)
1 efrain 281
        $userauth = get_auth_plugin($USER->auth);
282
        if (!isguestuser() and !empty($userauth->config->expiration) and $userauth->config->expiration == 1) {
283
            $externalchangepassword = false;
284
            if ($userauth->can_change_password()) {
285
                $passwordchangeurl = $userauth->change_password_url();
286
                if (!$passwordchangeurl) {
1391 ariadna 287
                    $passwordchangeurl = $CFG->wwwroot . '/login/change_password.php';
1 efrain 288
                } else {
289
                    $externalchangepassword = true;
290
                }
291
            } else {
1391 ariadna 292
                $passwordchangeurl = $CFG->wwwroot . '/login/change_password.php';
1 efrain 293
            }
294
            $days2expire = $userauth->password_expire($USER->username);
295
            $PAGE->set_title($loginsite);
296
            $PAGE->set_heading("$site->fullname");
297
            if (intval($days2expire) > 0 && intval($days2expire) < intval($userauth->config->expiration_warning)) {
298
                echo $OUTPUT->header();
299
                echo $OUTPUT->confirm(get_string('auth_passwordwillexpire', 'auth', $days2expire), $passwordchangeurl, $urltogo);
300
                echo $OUTPUT->footer();
301
                exit;
1391 ariadna 302
            } elseif (intval($days2expire) < 0) {
1 efrain 303
                if ($externalchangepassword) {
1391 ariadna 304
                    // Cerrar sesión si el formulario de cambio de contraseña es externo
1 efrain 305
                    require_logout();
306
                } else {
1391 ariadna 307
                    // Forzar cambio de contraseña si se usa el formulario estándar
1 efrain 308
                    set_user_preference('auth_forcepasswordchange', 1, $USER);
309
                }
310
                echo $OUTPUT->header();
311
                echo $OUTPUT->confirm(get_string('auth_passwordisexpired', 'auth'), $passwordchangeurl, $urltogo);
312
                echo $OUTPUT->footer();
313
                exit;
314
            }
315
        }
316
 
1391 ariadna 317
        // Limpiar mensajes de error antes de la última redirección
1 efrain 318
        unset($SESSION->loginerrormsg);
319
        unset($SESSION->logininfomsg);
320
 
1391 ariadna 321
        // Descartar loginredirect si estamos redirigiendo
1 efrain 322
        unset($SESSION->loginredirect);
323
 
1391 ariadna 324
        // Probar que la sesión funciona redirigiendo a sí mismo
1 efrain 325
        $SESSION->wantsurl = $urltogo;
1391 ariadna 326
        redirect(new moodle_url(get_login_url(), array('testsession' => $USER->id)));
1 efrain 327
    } else {
1391 ariadna 328
        // Manejo de errores de autenticación
1 efrain 329
        if (empty($errormsg)) {
330
            if ($errorcode == AUTH_LOGIN_UNAUTHORISED) {
331
                $errormsg = get_string("unauthorisedlogin", "", $frm->username);
332
            } else if ($errorcode == AUTH_LOGIN_FAILED_RECAPTCHA) {
333
                $errormsg = get_string('missingrecaptchachallengefield');
334
            } else {
335
                $errormsg = get_string("invalidlogin");
336
                $errorcode = 3;
337
            }
338
        }
339
    }
340
}
341
 
1391 ariadna 342
// ============================================================================
343
// DETECCIÓN DE PROBLEMAS CON SESIONES
344
// ============================================================================
345
 
346
// Detectar problemas con sesiones con tiempo de espera agotado
1 efrain 347
if ($session_has_timed_out and !data_submitted()) {
348
    $errormsg = get_string('sessionerroruser', 'error');
349
    $errorcode = 4;
350
}
351
 
1391 ariadna 352
// ============================================================================
353
// MANEJO DE URL DE DESTINO
354
// ============================================================================
1 efrain 355
 
1391 ariadna 356
// Recordar dónde estaba intentando llegar el usuario antes de llegar aquí
1 efrain 357
if (empty($SESSION->wantsurl)) {
358
    $SESSION->wantsurl = null;
359
    $referer = get_local_referer(false);
1391 ariadna 360
    if (
361
        $referer &&
362
        $referer != $CFG->wwwroot &&
363
        $referer != $CFG->wwwroot . '/' &&
364
        $referer != $CFG->wwwroot . '/login/' &&
365
        strpos($referer, $CFG->wwwroot . '/login/?') !== 0 &&
366
        strpos($referer, $CFG->wwwroot . '/login/index.php') !== 0
367
    ) {
1 efrain 368
        $SESSION->wantsurl = $referer;
369
    }
370
}
371
 
1391 ariadna 372
// Verificar si loginredirect está establecido en la SESSION
1 efrain 373
if ($errorcode && isset($SESSION->loginredirect)) {
374
    $loginredirect = $SESSION->loginredirect;
375
}
376
$SESSION->loginredirect = $loginredirect;
377
 
1391 ariadna 378
// ============================================================================
379
// REDIRECCIÓN A URL DE INICIO DE SESIÓN ALTERNATIVA
380
// ============================================================================
381
 
382
// Redirigir a URL de inicio de sesión alternativa si es necesario
1 efrain 383
if (!empty($CFG->alternateloginurl) && $loginredirect) {
384
    $loginurl = new moodle_url($CFG->alternateloginurl);
385
    $loginurlstr = $loginurl->out(false);
386
 
387
    if ($SESSION->wantsurl != '' && strpos($SESSION->wantsurl, $loginurlstr) === 0) {
1391 ariadna 388
        // No queremos volver a la URL alternativa
1 efrain 389
        $SESSION->wantsurl = null;
390
    }
391
 
1391 ariadna 392
    // Si hay código de error, agregarlo a la URL
1 efrain 393
    if ($errorcode) {
394
        $loginurl->param('errorcode', $errorcode);
395
    }
396
 
397
    redirect($loginurl->out(false));
398
}
399
 
1391 ariadna 400
// ============================================================================
401
// GENERACIÓN DE LA PÁGINA DE INICIO DE SESIÓN
402
// ============================================================================
1 efrain 403
 
1391 ariadna 404
// Inicializar el objeto del formulario si no existe
1 efrain 405
if (!isset($frm) or !is_object($frm)) {
406
    $frm = new stdClass();
407
}
408
 
1391 ariadna 409
// Configurar valores predeterminados del formulario
410
if (empty($frm->username) && $authsequence[0] != 'shibboleth') {
1 efrain 411
    if (!empty($_GET["username"])) {
1391 ariadna 412
        $frm->username = clean_param($_GET["username"], PARAM_RAW);
1 efrain 413
    } else {
414
        $frm->username = get_moodle_cookie();
415
    }
416
    $frm->password = "";
417
}
418
 
1391 ariadna 419
// Manejar mensajes de error e información
1 efrain 420
if (!empty($SESSION->loginerrormsg) || !empty($SESSION->logininfomsg)) {
421
    $errormsg = $SESSION->loginerrormsg ?? '';
422
    $infomsg = $SESSION->logininfomsg ?? '';
423
    unset($SESSION->loginerrormsg);
424
    unset($SESSION->logininfomsg);
425
} else if ($testsession) {
426
    unset($SESSION->loginerrormsg);
427
    unset($SESSION->logininfomsg);
428
} else if ($errormsg or !empty($frm->password)) {
429
    if ($errormsg) {
430
        $SESSION->loginerrormsg = $errormsg;
431
    }
432
    $loginurl = new moodle_url('/login/index.php');
433
    $loginurl->param('loginredirect', $SESSION->loginredirect);
434
    redirect($loginurl->out(false));
435
}
436
 
1391 ariadna 437
// ============================================================================
438
// RENDERIZADO DE LA PÁGINA
439
// ============================================================================
440
 
441
// Configurar título y encabezado de la página
1 efrain 442
$PAGE->set_title($loginsite);
443
$PAGE->set_heading("$site->fullname");
444
 
1391 ariadna 445
// Mostrar el encabezado de la página
1 efrain 446
echo $OUTPUT->header();
447
 
1391 ariadna 448
// Verificar el estado de la sesión del usuario
1 efrain 449
if (isloggedin() and !isguestuser()) {
1391 ariadna 450
    // Si el usuario ya está conectado, mostrar mensaje y opciones
1 efrain 451
    echo $OUTPUT->box_start();
1391 ariadna 452
    $logout = new single_button(new moodle_url('/login/logout.php', array('sesskey' => sesskey(), 'loginpage' => 1)), get_string('logout'), 'post');
1 efrain 453
    $continue = new single_button(new moodle_url('/'), get_string('cancel'), 'get');
454
    echo $OUTPUT->confirm(get_string('alreadyloggedin', 'error', fullname($USER)), $logout, $continue);
455
    echo $OUTPUT->box_end();
456
} else {
1391 ariadna 457
    // Mostrar el formulario de inicio de sesión
1 efrain 458
    $loginform = new \core_auth\output\login($authsequence, $frm->username);
459
    $loginform->set_error($errormsg);
460
    $loginform->set_info($infomsg);
461
    echo $OUTPUT->render($loginform);
462
}
463
 
1391 ariadna 464
// Mostrar el pie de página
1 efrain 465
echo $OUTPUT->footer();