martes, 27 de diciembre de 2016

Notificar al usuario via Email cuando hubo un cambio de contraseña en Laravel 5.3

Este artículo es la continuación de "Crear un formulario y controlador para el cambio de contraseña de una cuenta en Laravel 5.3":

Ya que se terminó la funcionalidad de permitirle al usuario cambiar su contraseña, ahora vamos a notificarle via email acerca del cambio de la contraseña.

Para ello vamos a hacer uso de eventos y de escuchas (events & listeners) de Laravel 5.3

Lo que se hizo fue lo siguiente:

1.- Ir al archivo providers/EventServiceProvider.php en donde se dieron de alta tanto el "event" como el "listener" dentro del arreglo protected $listen[]:


'App\Events\UserChangedPassword' => ['App\Listeners\SendPasswordChangedNotificationEmail',],


2.- Ahora en la consola, con PHP Artisan generamos los archivos para el "event" y el "listener" con el siguiente comando:

$ php artisan event:generate

3.- Simplemente en el evento, le inyectamos los datos del usuario a través de User $user, ya que Laravel, por defecto buscará los campos "name" e "email" para hacer el envío del correo:

El código del evento "UserChangedPassword" queda como sigue:

class UserChangedPassword
{
    use SerializesModels;//InteractsWithSockets,

    public $user;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    /*public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }*/

}




Ahora, el listener "SendPasswordChangedNotificationEmail.php" queda como sigue:

class SendPasswordChangedNotificationEmail
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  UserChangedPassword  $event
     * @return void
     */
    public function handle($event)/*UserChangedPassword $event*/
    {
        Mail::to($event->user)->send(new SendPasswordChangeNotification($event->user));
    }
}

Nos damos cuenta que también necesitamos crear una clase, la cual llamamos "SendPasswordChangeNotification", para el envío del correo. Creamos pues la clase email desde la consola tecleando

$php artisan make:mail SendPasswordChangeNotification

Y el archivo "Mail/SendPasswordChangeNotification.php" queda como sigue:
class SendPasswordChangeNotification extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->subject('Your password has been changed')
            ->from('system@authentication.app')
            ->view('email.auth.passwordChanged');
    }
}


Asimismo nos falta crear la vista del mensaje de correo electrónico la cual se llama "views/email/passwordChanged.blade.php"
This email is to let you know that your account's password has been changed.


Have a nice day!



Finalmente activamos dicho evento dentro del controlador "Controllers/Auth/ChangePasswordController.php"

//Fire event to notify the user about the password change
        event(new UserChangedPassword($user));


Uff, es todo!

lunes, 26 de diciembre de 2016

Crear un formulario y controlador para el cambio de contraseña de una cuenta en Laravel 5.3

Si has ejecutado la creación de autentificación de usuarios en laravel

Y ahora quieres agregar un formulario y un controlador para que el usuario pueda cambiar su contraseña, cuando éste se encuentra logueado o autentificado, estos son los pasos que seguí:

1) Creación de la vista del formulario. En este caso, creé el archivo /views/auth/passwords/change.blade.php

 @extends('layouts.app')  
   
 @section('title')  
   Cambio de contraseña  
 @endsection  
   
 @section('content')  
   <div class="container">  
     <div class="row">  
       <div class="col-md-8 col-md-offset-2">  
         <div class="panel panel-default">  
           <div class="panel-heading">Change Password</div>  
           <div class="panel-body">  
             <form class="form-horizontal" method="POST" role="form" action="{{ route('password.change.post') }}">  
               @if (count($errors) > 0)  
                 <div class="alert alert-danger">  
                   <ul>  
                     @foreach ($errors->all() as $error)  
                       <li>{{ $error }}</li>  
                     @endforeach  
                   </ul>  
                 </div>  
               @endif  
               {{ csrf_field() }}  
               {{-- Current password --}}  
               <div class="form-group{{ $errors->has('current_password') ? ' has-error' : '' }}">  
                 <label for="current_password" class="col-md-4 control-label">Current Password</label>  
   
                 <div class="col-md-6">  
                   <input id="current_password" type="password" class="form-control" name="current_password" required autofocus>  
   
                   @if ($errors->has('current_password'))  
                     <span class="help-block">  
                     <strong>{{ $errors->first('current_password') }}</strong>  
                   </span>  
                   @endif  
                 </div>  
               </div>  
   
               {{-- New password --}}  
               <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">  
                 <label for="password" class="col-md-4 control-label">Password</label>  
   
                 <div class="col-md-6">  
                   <input id="password" type="password" class="form-control" name="password" required>  
   
                   @if ($errors->has('password'))  
                     <span class="help-block">  
                     <strong>{{ $errors->first('password') }}</strong>  
                   </span>  
                   @endif  
                 </div>  
               </div>  
   
               {{-- Confirm new password --}}  
               <div class="form-group">  
                 <label for="password-confirm" class="col-md-4 control-label">Confirm Password</label>  
   
                 <div class="col-md-6">  
                   <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>  
                 </div>  
               </div>  
   
               {{-- Submit button --}}  
               <div class="form-group">  
                 <div class="col-md-6 col-md-offset-4">  
                   <button type="submit" class="btn btn-primary">  
                     Change password  
                   </button>  
                 </div>  
               </div>  
   
             </form>  
           </div>  
           <div class="panel-footer">Hello</div>  
         </div>  
       </div>  
     </div>  
   </div>  
 @endsection  
2) Creación del controlador para el cambio de contraseña ChangePasswordController.php

Ejecuté el comando:

$ php artisan make:controller Auth\\ChangePasswordController

** Aunque por ahí vi en la documentación de Laravel que, a manera de ejemplo, le llamaban UpdatePasswordController

 <?php  
   
 namespace App\Http\Controllers\Auth;  
   
 use App\User;  
 use Illuminate\Http\Request;  
 use App\Http\Controllers\Controller;  
 use Illuminate\Support\Facades\Hash;  
   
 class ChangePasswordController extends Controller  
 {  
   public function __construct()  
   {  
     $this->middleware('auth');  
   }  
   
   //show form:  
   public function showChangePasswordForm(Request $request, User $user)  
   {  
     return view('auth.passwords.change')->with(  
       ['user' => $user]  
     );  
   }  
   
   public function change(Request $request)  
   {  
     //Get current user data:  
     //$user = auth()->user();  
   
     //Validation:  
     $this->validate($request, [  
       'password'     => 'required|min:6|confirmed',  
       'current_password' => 'isCurrentPassword' ,  
     ]);  
   
     $request->user()->fill([  
       'password' => Hash::make($request->password)  
     ])->save();  
   
     return redirect('home')->with('info','Your password has been updated succesfully.');  
   }  
   
   
 }  
   
3) Registrar las rutas para el cambio de la contraseña
Las siguientes rutas las registré justo en el archivo en donde se encuentran las demás rutas relacionadas con el sistema de autentificación que te crea Laravel, dicho archivo se encuentra en y es: /vendor/laravel/framework/src/Illuminate/Routing/Router.php y justo dentro y al final de la función o método public function auth(){}:
        // Password Change Routes...
        $this->get('password/change', 'Auth\ChangePasswordController@showChangePasswordForm')->name('password.change');
        $this->post('password/change', 'Auth\ChangePasswordController@change')->name('password.change.post');


Habrá que ver si luego pongo esas rutas en otro archivo, como por ejemplo, en routes/web.php 4) Validación del formulario para el cambio de contraseña.

La validación se ve ya en el controlador ChangePasswordController.php, pero esto me hizo crear una nueva regla para comprobar si la contraseña actual es la correcta. Básicamente es obtener la contraseña actual que el usuario tecleó en el formulario, encriptarla o hashearla, y compararla con la contraseña del usuario autentificado que está en la base de datos. Entonces, de acuerdo a un tutorial (http://itsolutionstuff.com/post/laravel-5-create-custom-validation-rule-exampleexample.html) lo que hice fue abrir el archivo Providers/AppServiceProvider.php y dentro del método boot() {} declaré la nueva regla a la que titulé como "isCurrentPassword":
        //Validate if user's current password is correct
        Validator::extend('isCurrentPassword',function ($attribute, $value, $parameters, $validator){
            $user = auth()->user();
            if(Hash::check($value, $user->password)){
                return true;
            }
            return false;
        });

5) Agregar esta nueva regla de validación al listado ya existente de reglas de validación. Luego, abrí el archivo resources/lang/en/validation.php y agregué el mensaje de error, pero fíjense que el CamelCase lo tuve que sustituir por guiones bajos y dentro del arreglo return[] fue donde agregué el mensaje:
'is_current_password'    => 'The :attribute is not correct.',

6) De momento es lo que llevo. Continuará ... notificar via email al usuario del cambio de contraseña utilizando events y listeners ...

Siguiente parte: "Notificar al usuario via Email cuando hubo un cambio de contraseña"

domingo, 18 de diciembre de 2016

Composer self-update error exception permission denied

Si después de intentar actualizar tu composer

$ composer self-update

 te sale el siguiente error:

[ErrorException] rename(/home/vagrant/.composer/cache/composer-temp.phar,/usr/local/bin/composer): Permission denied

Lo que tienes que hacer es agregarle sudo al principio y listo:

$ sudo composer self-update

Listo


Wordpress fatal error maximum execution of time of 30 seconds class-wp-image-editor.php line 420

Este error se debe a que el tiempo por defecto de tiempo de ejecución para un script de php dado, ha excedido los 30 segundos.

Prueba aumentando el tiempo de ejecución a, por ejemplo, 60 segundos.

Busca el archivo php.ini de tu servidor y en la parte donde diga:

max_execution_time = 30

Cámbialo a:

max_execution_time = 60

Si no, prueba a agregar un archivo php.ini en la raíz de tu aplicación de wordpress, es decir, en donde se encuentran archivos tales como .htaccess y wp-config.php

y sólo agrega esa línea.

Por ejemplo, estando en la consola, en el directorio raíz de tu aplicación, teclea:

$ touch php.ini

$ nano php.ini

max_execution_time = 30

Dale ctrl + o para guardar y luego ctrl + x para salir del editor.

Saludos.


 

Tags