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ñadir 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
<?php
= @user.login
?>, pinche en el enlace para resetear su contraseña
<?php
= @url
?>
# app/views/user_notifier/reset_password.html.erb
<?php
= @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
<p>¿Olvidó su contraseña? </p>
<% form_tag url_for(:action => 'forgot_password') do %>
<p><label for="email">Correo electrónico: </label><br />
<%= text_field_tag :email, "", :size => 50 %></p>
<p><%= submit_tag 'Recuperar contraseña' %></p>
<% end %>
# app/views/passwords/reset_password.html.erb
<p>Resetear contraseña</p>
<% form_tag url_for(:action => "reset_password") do %>
<p><label for="password">Contraseña: </label><br />
<%= password_field_tag :password %></p>
<p><label for=":password_confirmation">Confirmar contraseña</label><br />
<%= password_field_tag :password_confirmation %></p>
<p><%= submit_tag "Resetear contraseña" %></p>
<% end %>

twitter
Comentarios
carakan (no verificado)
Mié, 09/04/2008 - 01:04
Permalink
Gracias por el codigo, me hacia falta la manera de recuperar contraseñas con el plugin. Me ahorraron un trabajito :D Saludos.
Davis Zanetti Cabral (no verificado)
Mar, 18/11/2008 - 15:15
Permalink
Thank you! Your code save me a few hours of work!
carmen maría pelayo (no verificado)
Vie, 20/11/2009 - 07:05
Permalink
Felicitaciones, gracias por esta publicación. Sin embargo tengo una pregunta, si el usuario olvido su contraseña de acceso apenas quiera entrar en la pantalla de login deberia estar esta opción, pregunto ¿Comó haria para que entre directamente solo preguntando el login y luego a la opción ¿olvidó la contraseña? porque lo intento pero no me direcciona a la opcion forgot_password en el log visualizo lo siguiente:
Processing EmpleadosController#show (for 127.0.0.1 at 2009-11-19 15:31:27) [GET] Parameters: {"action"=>"show", "id"=>"forgot_password", "controller"=>"empleados"} Redirected to http://localhost:3008/sesiones/new Filter chain halted as [:login_required] rendered_or_redirected. Completed in 1ms (DB: 1) | 302 Found [http://localhost/empleados/forgot_password] SQL (0.3ms) SET client_min_messages TO 'panic' SQL (0.3ms) SET client_min_messages TO 'notice'
Processing SesionesController#new (for 127.0.0.1 at 2009-11-19 15:31:27) [GET] Parameters: {"action"=>"new", "controller"=>"sesiones"} Rendering template within layouts/bienvenida Rendering sesiones/new Completed in 5ms (View: 2, DB: 1) | 200 OK [http://localhost/sesiones/new]
Añadir nuevo comentario