Commit acb6b46

mo khan <mo@mokhan.ca>
2014-11-15 17:34:55
generate unique session key instead of id.
1 parent 2059e8b
app/models/session.rb
@@ -1,11 +1,12 @@
 class Session < ActiveRecord::Base
   belongs_to :user
+  before_create :create_key
 
   def access(request)
     self.ip_address = request.remote_ip
     if save
       {
-        value: self.id,
+        value: self.key,
         httponly: true,
         secure: Rails.env.production? || Rails.env.staging?,
         expires: 2.weeks.from_now
@@ -25,7 +26,13 @@ class Session < ActiveRecord::Base
     end
 
     def authenticate!(session_key)
-      active.find(session_key)
+      active.find_by!(key: session_key)
     end
   end
+
+  private
+
+  def create_key
+    self.key = SecureRandom.uuid
+  end
 end
db/migrate/20141115172026_add_key_to_sessions.rb
@@ -0,0 +1,6 @@
+class AddKeyToSessions < ActiveRecord::Migration
+  def change
+    add_column :sessions, :key, :string, null: false
+    add_index :sessions, :key
+  end
+end
db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20141115170606) do
+ActiveRecord::Schema.define(version: 20141115172026) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -50,8 +50,10 @@ ActiveRecord::Schema.define(version: 20141115170606) do
     t.datetime "created_at"
     t.datetime "updated_at"
     t.datetime "revoked_at"
+    t.string   "key",        null: false
   end
 
+  add_index "sessions", ["key"], name: "index_sessions_on_key", using: :btree
   add_index "sessions", ["revoked_at"], name: "index_sessions_on_revoked_at", using: :btree
 
   create_table "users", force: true do |t|
spec/controllers/application_controller_spec.rb
@@ -12,7 +12,7 @@ describe ApplicationController do
     let(:user) { create(:user, password: 'password', password_confirmation: 'password') }
     let(:user_session) { create(:session, user: user) }
 
-    before { cookies.signed[:raphael] = user_session.id }
+    before { cookies.signed[:raphael] = user_session.key }
     before { get :index }
 
     it "lets you continue to do whatever the heck you were trying to do" do
@@ -26,7 +26,7 @@ describe ApplicationController do
 
   context "when not signed in" do
     before :each do
-      cookies.signed[:raphael] = rand(100)
+      cookies.signed[:raphael] = SecureRandom.uuid
       get :index
     end
 
spec/controllers/sessions_controller_spec.rb
@@ -35,7 +35,7 @@ describe SessionsController do
       end
 
       it 'assigns a session key to a secure cookie' do
-        expect(cookies.signed[:raphael]).to eql(Session.last.id)
+        expect(cookies.signed[:raphael]).to eql(Session.last.key)
       end
     end
   end
@@ -44,7 +44,7 @@ describe SessionsController do
     let(:user_session) { create(:session) }
 
     before :each do
-      cookies.signed[:raphael] = user_session.id
+      cookies.signed[:raphael] = user_session.key
       delete :destroy, { id: 'mine' }
     end
 
spec/models/session_spec.rb
@@ -7,6 +7,7 @@ describe Session do
       session = Session.last
       expect(session.user_id).to eql(1)
       expect(session.ip_address).to eql("127.0.0.1")
+      expect(session.key).to_not be_nil
     end
   end
 
@@ -15,7 +16,7 @@ describe Session do
 
     context "when the session key is legit" do
       it 'returns the session' do
-        expect(Session.authenticate!(user_session.id)).to eql(user_session)
+        expect(Session.authenticate!(user_session.key)).to eql(user_session)
       end
     end
 
@@ -29,7 +30,7 @@ describe Session do
       let(:revoked_session) { create(:session, revoked_at: Time.now) }
 
       it 'raises an error' do
-        expect(-> { Session.authenticate(revoked_session.id) }).to raise_error
+        expect(-> { Session.authenticate(revoked_session.key) }).to raise_error
       end
     end
   end
spec/support/authentication.rb
@@ -1,6 +1,6 @@
 module HttpAuthentication
   def http_login(user, password = 'password')
     user_session = create(:session, user: user)
-    cookies.signed[:raphael] = user_session.id
+    cookies.signed[:raphael] = user_session.key
   end
 end