Recuperar contraseñas con restful_authentication

Continuación del post anterior para recuperar las contraseñas olvidadas.

Crear una migration para añadir un campo reset_code al modelo User

$  script/generate migration password_reset_code

class PasswordResetCode < ActiveRecord::Migration
  def self.up
    add_column "users", "password_reset_code", :string, :limit => 40
  end

  def self.down
    remove_column "users", "password_reset_code" 
  end
end

Añanir los siguientes métodos a app/models/user.rb


   def forgot_password
     @forgotten_password = true
     self.make_password_reset_code
   end

   def reset_password
     # First update the password_reset_code before setting the 
     # reset_password flag to avoid duplicate email notifications.
     update_attributes(:password_reset_code => nil)
     @reset_password = true
   end

   def recently_reset_password?
     @reset_password
   end

   def recently_forgot_password?
     @forgotten_password
   end

  protected

  def make_password_reset_code
     self.password_reset_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
    end

Crear los modelos user_notifier.rb y user_observer.rb


# app/models/user_observer.rb
class UserObserver < ActiveRecord::Observer

  def after_save(user)
    UserNotifier.deliver_forgot_password(user) if user.recently_forgot_password?
    UserNotifier.deliver_reset_password(user) if user.recently_reset_password?
  end
end

# app/models/user_notifier.rb
class UserNotifier < ActionMailer::Base

  def forgot_password(user)
    setup_email(user)
    @subject    += 'Contraseña olvidada'
    @body[:url]  = "#{HOST}/passwords/reset_password/#{user.password_reset_code}" 
  end

  def reset_password(user)
    setup_email(user)
    @subject    += 'Su contraseña ha sido reseteada.'
  end

  protected
  def setup_email(user)
    @recipients  = "#{user.email}"
    @from        = "notifier@midominio.com"
    @subject     = "[midominio.com] "
    @sent_on     = Time.now
    @body[:user] = user
  end
end

En app/views/user_notifier/ crear los ficheros forgot_password.html.erb y reset_password.html.erb

# app/views/user_notifier/forgot_password.html.erb
<%= @user.login %>, pinche en el enlace para resetear su contraseña

<%= @url %>


# app/views/user_notifier/reset_password.html.erb
<%= @user.login %>, su contraseña ha sido reseteada.

En config/environment.rb añadir el observer:

# Activate observers that should always be running
# config.active_record.observers = :cacher, :garbage_collector
config.active_record.observers = :user_observer

Crear un controlador para gestionar las contrseñas olvidadas y los reseteos:


# app/controllers/passwords_controller.rb
class PasswordsController < ApplicationController

  skip_filter :login_required

  def forgot_password
    return unless request.post?
    if @user = User.find_by_email(params[:email])
      @user.forgot_password
      @user.save
      redirect_to(login_path)
      flash[:notice] = "Hemos envíado un enlace para resetear la contraseña a su correo electrónico." 
    else
      flash[:error] = "No se ha encontrado ningún usuario con esa dirección de correo electrónico." 
    end
  end

  def reset_password 
    return unless request.post?
    @user = User.find_by_password_reset_code(params[:id]) if params[:id]
    if @user.nil? 
      flash[:error] = "Código inválido."
      return
    end
    return if @user unless params[:password]
    begin
      if (params[:password] == params[:password_confirmation])
        @user.password_confirmation = params[:password_confirmation]
        @user.password = params[:password]              
        @user.reset_password
        @user.save!
        flash[:notice] = "Su contraseña ha sido reseteada, ya puede entrar con la nueva contraseña."
        redirect_back_or_default(login_path)                  
      else
        flash[:error] = "Las contraseñas no coinciden."
      end

      rescue ActiveRecord::RecordInvalid
        flash[:error] = "Por favor introduzca información válida."
      end
    end

end

En app/views/passwords/


# app/views/passwords/forgot_password.html.erb

¿Olvidó su contraseña?

<% form_tag url_for(:action => 'forgot_password') do %>


<%= text_field_tag :email, "", :size => 50 %>

<%= submit_tag 'Recuperar contraseña' %>

<% end %>

# app/views/passwords/reset_password.html.erb

Resetear contraseña

<% form_tag url_for(:action => "reset_password") do %>


<%= password_field_tag :password %>


<%= password_field_tag :password_confirmation %>

<%= submit_tag "Resetear contraseña" %>

<% end %>
Hierarchy: previous, next

Comments

There are 2 comments on this post. Post yours →

Gracias por el codigo, me hacia falta la manera de recuperar contraseñas con el plugin. Me ahorraron un trabajito :D Saludos.

Thank you! Your code save me a few hours of work!

Post a comment

Required fields in bold.






Markdown syntax enabled (no html). See the syntax rules for help.