refactored login process, added remember option for login

This commit is contained in:
albert
2011-10-15 16:36:07 -04:00
parent 1b7102b2e6
commit d324f4a071
10 changed files with 142 additions and 37 deletions
@@ -1,14 +1,11 @@
@import "../common/000_vars.css.scss"; @import "../common/000_vars.css.scss";
div#sessions { div#c-sessions {
div#new { div#a-new {
section { label#remember-label {
width: 30em; display: inline;
float: left; font-weight: normal;
} font-style: italic;
h1 {
font-size: $h2_size;
} }
} }
} }
+2 -14
View File
@@ -31,20 +31,8 @@ protected
end end
def set_current_user def set_current_user
if session[:user_id] session_loader = SessionLoader.new(session, cookies, request)
CurrentUser.user = User.find_by_id(session[:user_id]) session_loader.load
CurrentUser.ip_addr = request.remote_ip
end
if CurrentUser.user
if CurrentUser.user.is_banned? && CurrentUser.user.ban && CurrentUser.user.ban.expires_at < Time.now
CurrentUser.user.unban!
end
else
CurrentUser.user = AnonymousUser.new
end
Time.zone = CurrentUser.user.time_zone
end end
def reset_current_user def reset_current_user
+3 -4
View File
@@ -4,10 +4,9 @@ class SessionsController < ApplicationController
end end
def create def create
if User.authenticate(params[:name], params[:password]) session_creator = SessionCreator.new(session, cookies, params[:name], params[:password], params[:remember])
@user = User.find_by_name(params[:name])
@user.update_column(:last_logged_in_at, Time.now) if session_creator.authenticate
session[:user_id] = @user.id
redirect_to(params[:url] || session[:previous_uri] || posts_path, :notice => "You are now logged in.") redirect_to(params[:url] || session[:previous_uri] || posts_path, :notice => "You are now logged in.")
else else
redirect_to(new_session_path, :notice => "Password was incorrect.") redirect_to(new_session_path, :notice => "Password was incorrect.")
+28
View File
@@ -0,0 +1,28 @@
class SessionCreator
attr_reader :session, :cookies, :name, :password, :remember
def initialize(session, cookies, name, password, remember)
@session = session
@cookies = cookies
@name = name
@password = password
@remember = remember
end
def authenticate
if User.authenticate(name, password)
user = User.find_by_name(name)
user.update_column(:last_logged_in_at, Time.now)
if remember.present?
cookies[:user_name] = {:expires => 1.year.from_now, :value => user.name}
cookies[:cookie_password_hash] = {:expires => 1.year.from_now, :value => user.cookie_password_hash}
end
session[:user_id] = user.id
return true
else
return false
end
end
end
+51
View File
@@ -0,0 +1,51 @@
class SessionLoader
attr_reader :session, :cookies, :request
def initialize(session, cookies, request)
@session = session
@cookies = cookies
@request = request
end
def load
if session[:user_id]
load_session_user
elsif cookie_password_hash_valid?
load_cookie_user
end
if CurrentUser.user
CurrentUser.user.unban! if ban_expired?
else
CurrentUser.user = AnonymousUser.new
end
set_time_zone
end
private
def load_session_user
CurrentUser.user = User.find_by_id(session[:user_id])
CurrentUser.ip_addr = request.remote_ip
end
def load_cookie_user
CurrentUser.user = User.find_by_name(cookies[:user_name])
CurrentUser.ip_addr = request.remote_ip
end
def ban_expired?
CurrentUser.user.is_banned? && CurrentUser.user.ban && CurrentUser.user.ban.expired?
end
def cookie_password_hash_valid?
puts "cookie_password_hash=#{cookies[:cookie_password_hash]}"
cookies[:cookie_password_hash] && User.authenticate_cookie_hash(cookies[:user_name], cookies[:cookie_password_hash])
end
def set_time_zone
Time.zone = CurrentUser.user.time_zone
end
end
+4
View File
@@ -54,4 +54,8 @@ class Ban < ActiveRecord::Base
def duration def duration
@duration @duration
end end
def expired?
expires_at < Time.now
end
end end
+23 -3
View File
@@ -139,12 +139,21 @@ class User < ActiveRecord::Base
end end
module AuthenticationMethods module AuthenticationMethods
extend ActiveSupport::Concern
module ClassMethods
def authenticate(name, pass) def authenticate(name, pass)
authenticate_hash(name, sha1(pass)) authenticate_hash(name, sha1(pass))
end end
def authenticate_hash(name, pass) def authenticate_hash(name, hash)
where(["lower(name) = ? AND password_hash = ?", name.downcase, pass]).first != nil where(["lower(name) = ? AND password_hash = ?", name.downcase, hash]).first != nil
end
def authenticate_cookie_hash(name, hash)
user = User.find_by_name(name)
return nil if user.nil?
return hash == user.cookie_password_hash
end end
def sha1(pass) def sha1(pass)
@@ -152,6 +161,17 @@ class User < ActiveRecord::Base
end end
end end
def cookie_password_hash
hash = password_hash
(name.size + 8).times do
hash = User.sha1(hash)
end
return hash
end
end
module FavoriteMethods module FavoriteMethods
def favorites def favorites
Favorite.where("user_id = ?", id).order("id desc") Favorite.where("user_id = ?", id).order("id desc")
@@ -354,7 +374,7 @@ class User < ActiveRecord::Base
include BanMethods include BanMethods
include NameMethods include NameMethods
include PasswordMethods include PasswordMethods
extend AuthenticationMethods include AuthenticationMethods
include FavoriteMethods include FavoriteMethods
include LevelMethods include LevelMethods
include EmailMethods include EmailMethods
+3
View File
@@ -13,6 +13,9 @@
<div class="input"> <div class="input">
<label for="password">Password</label> <label for="password">Password</label>
<%= password_field_tag :password %> <%= password_field_tag :password %>
<%= check_box_tag :remember %>
<label for="remember" id="remember-label">Remember</label>
</div> </div>
<div class="input"> <div class="input">
+2 -1
View File
@@ -2433,7 +2433,8 @@ CREATE TABLE uploads (
post_id integer, post_id integer,
md5_confirmation character varying(255), md5_confirmation character varying(255),
created_at timestamp without time zone, created_at timestamp without time zone,
updated_at timestamp without time zone updated_at timestamp without time zone,
backtrace text
); );
+14
View File
@@ -174,6 +174,20 @@ class UserTest < ActiveSupport::TestCase
end end
end end
context "cookie password hash" do
setup do
@user = Factory.create(:user, :password_hash => "1234")
end
should "be correct" do
assert_equal("8ac3b1d04bdb95ba92f9e355897c880e0d88ac5a", @user.cookie_password_hash)
end
should "validate" do
assert(User.authenticate_cookie_hash(@user.name, "8ac3b1d04bdb95ba92f9e355897c880e0d88ac5a"))
end
end
context "password" do context "password" do
should "match the confirmation" do should "match the confirmation" do
@user = Factory.create(:user) @user = Factory.create(:user)