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

View File

@@ -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;
} }
} }
} }

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

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.")

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

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

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

View File

@@ -139,16 +139,36 @@ class User < ActiveRecord::Base
end end
module AuthenticationMethods module AuthenticationMethods
def authenticate(name, pass) extend ActiveSupport::Concern
authenticate_hash(name, sha1(pass))
module ClassMethods
def authenticate(name, pass)
authenticate_hash(name, sha1(pass))
end
def authenticate_hash(name, hash)
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
def sha1(pass)
Digest::SHA1.hexdigest("#{Danbooru.config.password_salt}--#{pass}--")
end
end end
def authenticate_hash(name, pass) def cookie_password_hash
where(["lower(name) = ? AND password_hash = ?", name.downcase, pass]).first != nil hash = password_hash
end
def sha1(pass) (name.size + 8).times do
Digest::SHA1.hexdigest("#{Danbooru.config.password_salt}--#{pass}--") hash = User.sha1(hash)
end
return hash
end end
end end
@@ -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

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">

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
); );

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)