Use auth token for permanent sessions

openid
Marcin Kulik 11 years ago
parent 3e1feff84e
commit 431fd87002

@ -13,23 +13,30 @@ class ApplicationController < ActionController::Base
helper_method :current_user
def current_user
if session[:user_id]
@current_user ||= User.find_by_id(session[:user_id]).decorate
if permanent_store[:auth_token]
@current_user ||= find_user_by_auth_token(permanent_store[:auth_token])
end
end
private
def current_user=(user)
if user
@current_user = user
session[:user_id] = user.id
permanent_store.permanent[:auth_token] = user.auth_token
else
@current_user = nil
session[:user_id] = nil
permanent_store.delete(:auth_token)
end
end
private
def permanent_store
cookies
end
def find_user_by_auth_token(auth_token)
user = User.where(auth_token: auth_token).first
user && user.decorate
end
def ensure_authenticated!
raise Unauthorized unless current_user
end

@ -12,6 +12,8 @@ class User < ActiveRecord::Base
validates :nickname, :email, presence: true, uniqueness: true
before_create :generate_auth_token
def self.for_credentials(credentials)
where(provider: credentials.provider, uid: credentials.uid).first
end
@ -20,6 +22,10 @@ class User < ActiveRecord::Base
where(email: email).first
end
def self.generate_auth_token
SecureRandom.urlsafe_base64
end
def nickname=(value)
value ? super(value.strip) : super
end
@ -36,4 +42,12 @@ class User < ActiveRecord::Base
user_tokens.where(:token => token).first_or_create
end
private
def generate_auth_token
begin
self[:auth_token] = self.class.generate_auth_token
end while User.exists?(auth_token: self[:auth_token])
end
end

@ -0,0 +1,6 @@
class AddAuthTokenToUsers < ActiveRecord::Migration
def change
add_column :users, :auth_token, :string
add_index :users, :auth_token
end
end

@ -0,0 +1,10 @@
class SetAuthTokenForExistingUsers < ActiveRecord::Migration
def up
User.find_each do |user|
user.update_attribute(:auth_token, SecureRandom.urlsafe_base64)
end
end
def down
end
end

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20131019165955) do
ActiveRecord::Schema.define(version: 20131022165054) do
create_table "asciicasts", force: true do |t|
t.integer "user_id"
@ -93,8 +93,10 @@ ActiveRecord::Schema.define(version: 20131019165955) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "nickname", null: false
t.string "auth_token"
end
add_index "users", ["auth_token"], name: "index_users_on_auth_token", using: :btree
add_index "users", ["provider", "uid"], name: "index_users_on_provider_and_uid", unique: true, using: :btree
end

@ -23,6 +23,7 @@ class FakesController < ApplicationController
end
describe FakesController do
before do
@orig_routes, @routes = @routes, ActionDispatch::Routing::RouteSet.new
@routes.draw do
@ -120,4 +121,63 @@ describe FakesController do
end
end
end
describe '#current_user=' do
let(:store) { {} }
before do
allow(store).to receive(:permanent) { store }
end
before do
allow(controller).to receive(:permanent_store) { store }
controller.current_user = user
end
context "with a user" do
let(:user) { double('user', auth_token: '1b2c3') }
it "stores user's auth_token in the permanent_store" do
expect(store[:auth_token]).to eq('1b2c3')
end
end
context "with nil" do
let(:store) { { auth_token: 'a-token' } }
let(:user) { nil }
it "stores deletes the auth_token from the permanent_store" do
expect(store.key?(:auth_token)).to eq(false)
end
end
end
describe '#current_user' do
let(:user) { create(:user) }
subject { controller.current_user }
before do
allow(controller).to receive(:permanent_store) { store }
end
context "when valid auth_token exists in the store" do
let(:store) { { auth_token: user.auth_token } }
it { should eq(user) }
end
context "when invalid auth_token exists in the store" do
let(:store) { { auth_token: 'xxxx' } }
it { should be(nil) }
end
context "when auth_token doesn't exist in the store" do
let(:store) { {} }
it { should be(nil) }
end
end
end

@ -2,6 +2,14 @@ require 'spec_helper'
describe User do
it 'gets an auth_token upon creation' do
attrs = attributes_for(:user)
attrs.delete(:auth_token)
user = described_class.create!(attrs)
expect(user.auth_token).to be_kind_of(String)
end
describe "#valid?" do
before do
create(:user)
@ -11,6 +19,21 @@ describe User do
it { should validate_uniqueness_of(:email) }
end
describe '.generate_auth_token' do
it 'generates a string token' do
token = described_class.generate_auth_token
expect(token).to be_kind_of(String)
end
it 'generates unique token' do
token_1 = described_class.generate_auth_token
token_2 = described_class.generate_auth_token
expect(token_1).to_not eq(token_2)
end
end
describe '.for_credentials' do
subject { described_class.for_credentials(credentials) }

Loading…
Cancel
Save