I was trying to disable multi login for single user using devise authentication and came up with this solution.
Thought it may help someone.
I used active record session store, so that I can access all user session by their ID. Changed initializer session_store.rb to
[source language=”ruby”]
MyApp::Application.config.session_store :active_record_store
[/source]
added field session_id to user table and created model for session(session.rb)
rails migration
[source language=”ruby”]
rails g migration add_session_id_to_users session_id:integer
[/source]
Add activerecord-session_store to Gemfile and create migration.
[source language=”ruby”]
rails generate active_record:session_migration
[/source]
session.rb
[source language=”ruby”]
class Session < ActiveRecord::Base
end
[/source]
devise gem uses warden, so I set callback after_authentication to check user session.
user.rb
[source language="ruby"]
class << self
def delete_session(session_id)
begin
session = Session.where("session_id=?",session_id)
session.delete_all
rescue => e
end
end
end
Warden::Manager.after_authentication do |user, auth, opts|
unless user.session_id == “”
auth.logout
User.delete_session(user.session_id)
user.session_id = “”
user.save
throw(:warden, :message => “User already logged in, Try again to kill the existing session and start new on here.”)
end
end
[/source]
The callback will alert the user, if he/she was already logged in at some other machine.
Stored user session id in application_controller before_filter (aplication_helper.rb)
before_action :save_session
[source language=”ruby”]
def save_session
if user_signed_in? && current_user.session_id == “”
current_user.session_id = request.session_options[:id]
current_user.save
end
end
[/source]
Now I get the session ID by request.session_options[:id].