Created
December 3, 2008 16:34
-
-
Save oleganza/31604 to your computer and use it in GitHub Desktop.
auto_sign_in.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module AutoSignIn | |
PARAM = :sign_in_token | |
protected | |
# usage: | |
# before :auto_sign_in | |
# url(..., auto_sign_in_params(person)) | |
# | |
def auto_sign_in | |
if tk = params[PARAM] | |
if person = AutoSignInToken.person_for_token(tk) | |
self.current_person = token.person | |
remember_signin | |
end | |
throw(:halt, :redirect_after_auto_sign_in) | |
end | |
end | |
# this method does redirect to the requested URI stripping auth token from it | |
# to prevent infinite looping | |
def redirect_after_auto_sign_in | |
qp = request.send(:query_params).dup # we use private Merb API here | |
qp.delete(PARAM) | |
redirect(request.uri + "?" + Merb::Parse.params_to_query_string(qp)) | |
end | |
module Helper | |
# Usage: | |
# url(..., auto_sign_in_params(person)) | |
# url(..., {:a => 1}.merge(auto_sign_in_params(person))) | |
def auto_sign_in_params(person) | |
{ AutoSignIn::PARAM => auto_sign_in_token_for_person(person) } | |
end | |
def auto_sign_in_token_for_person(person) | |
at = AutoSignInToken.create(:person => person) | |
at.valid? or raise "AutoSignInToken is invalid!" | |
at.token | |
end | |
end | |
include Helper | |
end | |
# Okay, we keep this model here just for keeping this tiny feature in one file. | |
# Blame me, but consider this as a "MVC subcomponent" | |
class AutoSignInToken | |
include DataMapper::Resource | |
property :id, DataMapper::Types::Serial, :key => true | |
property :created_at, DateTime | |
property :token, String, :unique_index => true | |
belongs_to :person | |
validates_present :person | |
before :valid? do | |
self.token ||= rand(2**160).to_s(16) | |
end | |
TIMEOUT = 3600*24*7 | |
class <<self | |
# Call this to get a person if all security conditions are met | |
def person_for_token(tk) | |
token = first(:token => tk) or return nil | |
Time.now - token.created_at < TIMEOUT or return nil | |
token.person | |
end | |
end | |
end # AutoSignInToken |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment