Posted in

Password Reminders & Reset en Laravel

A continuación montaremos un sistema de recuperación de contraseñas basado en Laravel 4.2

Generamos el archivo migration para la tabla reminder

php artisan auth:reminders-table

Podríamos generar el controlador vía consola

php artisan auth:reminders-controller

Pero en nuestro caso y dado que partimos de un ejemplo algo personalizado y podría variar alguna de las líneas, sustituiremos el código generado por el siguiente:

<?php

class RemindersController extends Controller {

/**
 * Display the password reminder view.
 *
 * @return Response
 */
public function getRemind()
{
return View::make('password-reset.remind');
}

/**
 * Handle a POST request to remind a user of their password.
 *
 * @return Response
 */
public function postRemind()
{
switch ($response = Password::remind(Input::only('email')))
{
case Password::INVALID_USER:
return Redirect::back()->with('error', Lang::get($response));

case Password::REMINDER_SENT:
return Redirect::back()->with('status', Lang::get($response));
}
}

/**
 * Display the password reset view for the given token.
 *
 * @param  string  $token
 * @return Response
 */
public function getReset($token = null)
{
if (is_null($token)) App::abort(404);

return View::make('password-reset.reset')->with('token', $token);
}

/**
 * Handle a POST request to reset a user's password.
 *
 * @return Response
 */
public function postReset()
{
$credentials = Input::only(
'email', 'password', 'password_confirmation', 'token'
);

$response = Password::reset($credentials, function($user, $password)
{
$user->password = Hash::make($password);

$user->save();
});

switch ($response)
{
case Password::INVALID_PASSWORD:
case Password::INVALID_TOKEN:
case Password::INVALID_USER:
return Redirect::back()->with('error', Lang::get($response));

case Password::PASSWORD_RESET:
return Redirect::to('/access?email=' . Input::get('email'))->with('password_changed', 1);
}
}

}

En el archivo roots pegaremos las siguientes rutas

Route::get('password-reset', 'RemindersController@getRemind');
Route::post('password-modify', 'RemindersController@postRemind');
Route::get('password/reset/{token}', 'RemindersController@getReset');
Route::post('password/reset', 'RemindersController@postReset');

Podemos modificar el template de email que viene por defecto en /views/emails/auth por el siguiente:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="es">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="format-detection" content="telephone=no">
        <title>Mondelez</title>
        <style>

            .container {
                width: 600px;
                max-width: 600px;
            }

            .container-padding {
                padding-left: 24px;
                padding-right: 24px;
            }

            .content {
                padding-top: 22px;
                padding-bottom: 22px;
                background-color: #ffffff;
            }

            .col {
                font-family: Helvetica, Arial, sans-serif;
                font-size: 14px;
                line-height: 20px;
                text-align: left;
                color: #333333;
                width: 100%;
            }
            body {
                margin: 0;
                padding: 0;
                -ms-text-size-adjust: 100%;
                -webkit-text-size-adjust: 100%;
            }

            table {
                border-spacing: 0;
                mso-table-lspace: 0pt;
                mso-table-rspace: 0pt;
            }

            table td {
                border-collapse: collapse;
            }

            img {
                -ms-interpolation-mode: bicubic;
            }

            @media screen and (max-width: 599px) {
                .force-row,
                .container {
                    width: 100% !important;
                    max-width: 100% !important;
                }
            }
            @media screen and (max-width: 400px) {
                .container-padding {
                    padding-left: 12px !important;
                    padding-right: 12px !important;
                }
            }

        </style>
    </head>
    <body style="margin:0; padding:0;" bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">

        <table border="0" width="100%" height="100%" cellpadding="20" cellspacing="0" bgcolor="#FFFFFF">
            <tr>
                <td align="center" valign="top" bgcolor="#FFFFFF" style="background-color: #FFFFFF;">
                    <table cellpadding="0" cellspacing="0" border="0" width="600" class="container">
                        <tr>
                            <td align="center"><img src="{{ URL::to('assets/images/logo.png') }}" width="76" height="76" /></td>
                        </tr>
                        <tr>
                            <td height="42"></td>
                        </tr>
                        <tr>
                            <td align="center">
                                <table cellpadding="0" cellspacing="0" border="0" align="center" style="width: 100%; max-width: 400px;">
                                    <tr>
                                        <td align="center">
                                            <h3 style="font-family: Arial, Gotham, 'Helvetica Neue', Helvetica, sans-serif; color:#333; font-size:16px; margin-bottom: 20px; padding-bottom: 0;">Cambio de contraseña</h3>
                                            <p style="font-family: Arial, Gotham, 'Helvetica Neue', Helvetica, sans-serif; color:#333; font-size:14px; padding-bottom: 30px;">Para cambiar tu contraseña haz clic en el siguiente botón y rellena el formulario.</p>
                                            <p style="font-family: Arial, Gotham, 'Helvetica Neue', Helvetica, sans-serif; color:#333; font-size:14px; padding-bottom: 30px;">El enlace caducará en {{ Config::get('auth.reminder.expire', 60) }} minutos.</p>
                                            <table cellpadding="0" cellspacing="0" border="0" bgcolor="#000000">
                                                <tr>
                                                    <td style="color:#FFF; padding:9px; font-size:14px; font-family: Arial, Helvetica, sans-serif;">
                                                        <a style="text-decoration:none; color:#FFFFFF;" href="{{ URL::to('password/reset', array($token)) }}" target="_blank">CLICA AQUÍ</a>
                                                    </td>
                                                </tr>
                                            </table>
                                        </td>
                                    </tr>
                                </table>
                            </td>
                        </tr>
                        <tr>
                            <td height="45"></td>
                        </tr>
                    </table>
                </td>
            </tr>
        </table>
    </body>
</html>

Y solo nos quedará crear las vistas de la pantalla donde pediremos el correo electrónico y donde confirmaremos el correo y la nueva contraseña. Cabe destacar que estas dos pantallas están basadas en el theme del admin Milton.

Archivo remind.blade.php (petición del correo electrónico)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <meta name="author" content="4funkies">

    <link rel="shortcut icon" href="assets/images/favicon_1.ico">

    <title>SmartPlace by Mondel?z</title>

    {{ HTML::style("assets/css/bootstrap.min.css") }}
    {{ HTML::style("assets/css/core.css") }}
    {{ HTML::style("assets/css/icons.css") }}
    {{ HTML::style("assets/css/components.css") }}
    {{ HTML::style("assets/css/pages.css") }}
    {{ HTML::style("assets/css/menu.css") }}
    {{ HTML::style("assets/css/responsive.css") }}

    {{ HTML::script("assets/js/modernizr.min.js") }}

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    {{ HTML::script("https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js") }}
    {{ HTML::script("https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js") }}
    <![endif]-->

</head>
<body>

<div class="wrapper-page">
    <div class="text-center">
        <a href="/" class="logo-lg">
            <i class="md md-directions-car"></i>
            <span>SmartPlace by Mondel?z</span>
        </a>
    </div>
    <div class="row">
        <div class="col-sm-12">
            <h4 class="page-title">¿Olvidaste tu contraseña?</h4>
            <p>Introduce tu correo electrónico y te enviaremos un enlace para crear una nueva.</p>
        </div>
    </div>
    {{ Form::open(array('url' => action('RemindersController@postRemind'))) }}
        <div class="form-group m-t-15">
            <div class="input-group">
                {{ Form::text('email', '', array('class'=>'form-control', 'placeholder' => 'Correo electrónico', 'required')) }}
                <i class="md md-email form-control-feedback l-h-34" style="left:6px;"></i>
                <span class="input-group-btn"> <button type="submit" class="btn btn-email btn-primary waves-effect waves-light">Enviar</button> </span>
            </div>
        </div>
    {{ Form::close() }}
    @if( Session::get('error') )
    <div class="alert alert-danger alert-dismissable">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
        {{ Session::get('error') }}
    </div>
    @endif
    @if( Session::get('status') )
    <div class="alert alert-success alert-dismissable">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
        {{ Session::get('status') }}
    </div>
    @endif
</div>

<script>
    var resizefunc = [];
</script>

<!-- Main  -->
{{ HTML::script("assets/js/jquery.min.js") }}
{{ HTML::script("assets/js/bootstrap.min.js") }}
{{ HTML::script("assets/js/detect.js") }}
{{ HTML::script("assets/js/fastclick.js") }}
{{ HTML::script("assets/js/jquery.slimscroll.js") }}
{{ HTML::script("assets/js/jquery.blockUI.js") }}
{{ HTML::script("assets/js/waves.js") }}
{{ HTML::script("assets/js/wow.min.js") }}
{{ HTML::script("assets/js/jquery.nicescroll.js") }}
{{ HTML::script("assets/js/jquery.scrollTo.min.js") }}

<!-- Custom main Js -->
{{ HTML::script("assets/js/jquery.core.js") }}
{{ HTML::script("assets/js/jquery.app.js") }}

</body>
</html>

Archivo reset.blade.php (confirmación email y nueva contraseña)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <meta name="author" content="4funkies">

    <link rel="shortcut icon" href="assets/images/favicon_1.ico">

    <title>SmartPlace by Mondel?z</title>

    {{ HTML::style("assets/css/bootstrap.min.css") }}
    {{ HTML::style("assets/css/core.css") }}
    {{ HTML::style("assets/css/icons.css") }}
    {{ HTML::style("assets/css/components.css") }}
    {{ HTML::style("assets/css/pages.css") }}
    {{ HTML::style("assets/css/menu.css") }}
    {{ HTML::style("assets/css/responsive.css") }}

    {{ HTML::script("assets/js/modernizr.min.js") }}

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    {{ HTML::script("https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js") }}
    {{ HTML::script("https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js") }}
    <![endif]-->

</head>
<body>

<div class="wrapper-page">
    <div class="text-center">
        <a href="/" class="logo-lg">
            <i class="md md-directions-car"></i>
            <span>SmartPlace by Mondel?z</span>
        </a>
    </div>
    <div class="row">
        <div class="col-sm-12">
            <h4 class="page-title">Cambio de contraseña</h4>
            <p>Introduce tu correo electrónico y una nueva contraseña de acceso</p>
        </div>
    </div>
    {{ Form::open(array('url' => action('RemindersController@postReset'))) }}
    <div class="form-group m-t-15">
        <div class="input-group">
            {{ Form::email('email', Input::old('email'), array('class' => 'form-control', 'placeholder' => 'Correo electrónico', 'parsley-type' => "email", 'required')) }}
            <span class="input-group-addon">
                <i class="fa fa-envelope-o"></i>
            </span>
        </div>
    </div>
    <div class="form-group">
        <div class="input-group">
            {{ Form::password('password', array('class' => 'form-control', 'placeholder' => 'Contraseña', 'id' => "pass", 'required')) }}
            <span class="input-group-addon">
                <i class="fa fa-key"></i>
            </span>
        </div>
    </div>
    <div class="form-group">
        <div class="input-group">
            {{ Form::password('password_confirmation', array('class' => 'form-control', 'placeholder' => 'Repetir contraseña', 'data-parsley-equalto' => "#pass", 'required')) }}
            <span class="input-group-addon">
                <i class="fa fa-key"></i>
            </span>
        </div>
    </div>
    <div class="form-group">
        {{ Form::submit('Enviar', array('class' => 'btn btn-primary m-t-15')) }}
    </div>
    {{ Form::hidden('token', $token) }}
    {{ Form::close() }}
    @if( Session::get('error') )
    <div class="alert alert-danger alert-dismissable">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
        {{ Session::get('error') }}
    </div>
    @endif
</div>

<script>
    var resizefunc = [];
</script>

<!-- Main  -->
{{ HTML::script("assets/js/jquery.min.js") }}
{{ HTML::script("assets/js/bootstrap.min.js") }}
{{ HTML::script("assets/js/detect.js") }}
{{ HTML::script("assets/js/fastclick.js") }}
{{ HTML::script("assets/js/jquery.slimscroll.js") }}
{{ HTML::script("assets/js/jquery.blockUI.js") }}
{{ HTML::script("assets/js/waves.js") }}
{{ HTML::script("assets/js/wow.min.js") }}
{{ HTML::script("assets/js/jquery.nicescroll.js") }}
{{ HTML::script("assets/js/jquery.scrollTo.min.js") }}

{{ HTML::script('assets/plugins/parsleyjs/dist/parsley.min.js') }}

<!-- Custom main Js -->
{{ HTML::script("assets/js/jquery.core.js") }}
{{ HTML::script("assets/js/jquery.app.js") }}

<script type="text/javascript">
    $(document).ready(function() {
        $('form').parsley();
    });
</script>

</body>
</html>

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *


The reCAPTCHA verification period has expired. Please reload the page.