Skip to content

Instantly share code, notes, and snippets.

@snitko
Created January 5, 2009 16:04
Show Gist options
  • Save snitko/43446 to your computer and use it in GitHub Desktop.
Save snitko/43446 to your computer and use it in GitHub Desktop.
module Authentication
# Is included both in SessionController and UsersController
module ControllerUtils
private
def save_cookies(params)
params.each do |k,v|
name = "#{auth_model_name}_#{k}"
cookies.delete(name)
cookies[name] = {
:value => v.to_s,
:expires => 7.years.from_now
}
end
end
# We need this method to avoid code duplication.
# success/fail cases could happen multiple times,
# both in actions and in their before_filters.
# This way before_filter always knows which
# action was called on the controller.
#
# For this to work an AUTHENTICATION_SETTINGS[:action_on]
# should be defined in the controller, which includes this
# module and uses this method.
def action_on(event)
action = self.class::AUTHENTICATION_SETTINGS[:action_on][params[:action].to_sym][event]
if action.kind_of?(Proc)
self.instance_eval(&action)
else
raise "No action was set for #{params[:action]} on #{event}"
end
end
end
end
class UsersController < ApplicationController
include Authentication::ControllerUtils
AUTHENTICATION_SETTINGS =
{:action_on =>
{:create => {
:success => Proc.new { redirect_to_stored },
:fail => Proc.new { render :action => :new }
},
:change_password => {
:success => Proc.new { redirect_to @model }
},
:recover_password => {
:success => Proc.new { redirect_to :action => :change_password }
}
}}
def new
@user = User.new
end
def create
@model = model = auth_model.create(params[auth_model_name])
if model.errors.empty?
session[auth_model_name] = model.id # auto signing in
self.send("#{auth_model_name.to_s}=".to_sym, model)
#self.mailer.deliver_signup(model)
save_cookies({:id => model.id, :password => model.password})
flash[:message] = "You've successfully created an account"
action_on(:success)
else
self.send("#{auth_model_name.to_s}=".to_sym, model)
action_on(:fail)
end
end
def change_password
@model = model = auth_model.find(session[auth_model_name])
if request.put?
model.update_attributes(params[auth_model_name])
if model.errors.empty?
save_cookies({:password => model.password, :id => model.id})
flash[:message] = "Password has been changed successfully"
action_on(:success)
end
end
# If get request or errors, then just render the form
self.send("#{auth_model_name.to_s}=".to_sym, model)
end
def lost_password
if request.post?
if model = auth_model.find_by_email(
params[auth_model_name][:email]
)
model.set_password_token
model.save!
UserMailer.deliver_lost_password(model)
flash[:message] = "You password recovery token has been emailed to you"
else # just render form again
flash.now[:error] = "Sorry, there's no such email in our database"
end
end
end
def recover_password
model = self.auth_model.find_by_password_token(params[:token]) if params[:token]
if model && model.password_token_expires > Time.now
session[auth_model_name] = model.id
action_on(:success)
else
flash.now[:error] = "This token is invalid"
end
model.destroy_password_token if model
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment