module Sso class Session < ActiveRecord::Base include ::Sso::Logging # FIXME: Not sure to use application or doorkeeper_application_id belongs_to :application, class_name: 'Doorkeeper::Application' #, inverse_of: :sso_sessions belongs_to :access_grant, class_name: 'Doorkeeper::AccessGrant' #, inverse_of: :sso_sessions belongs_to :access_token, class_name: 'Doorkeeper::AccessToken' #, inverse_of: :sso_sessions belongs_to :owner, class_name: 'User' #, inverse_of: :sso_sessions validates :group_id, presence: true validates :owner_id, presence: true validates :ip, presence: true validates :secret, presence: true validates :access_token_id, uniqueness: { scope: [:owner_id, :revoked_at, :application_id], allow_blank: true } validates :revoke_reason, allow_blank: true, format: { with: /\A[a-z_]+\z/ } scope :active, -> { where(revoked_at: nil) } scope :master, -> { where(application_id: nil) } before_validation :ensure_secret before_validation :ensure_group_id before_validation :ensure_activity_at class << self def master_for(grant_id) active.master.find_by!(access_grant_id: grant_id) end def generate_master(user, options) relations = { owner: user } attributes = ActionController::Parameters.new(options).permit(:ip, :agent, :location) debug { "Sso::Session::generate_master for #{user.inspect} - #{attributes.inspect}" } create!(relations.merge(attributes)) end def generate(user, access_token, options = {}) master_sso_session = active.master.find_by!(owner_id: user.id, access_token_id: access_token.id) attributes = ActionController::Parameters.new(options).permit(:ip, :agent, :location) relations = { owner: user, application: access_token.application, access_token: access_token, group_id: master_sso_session.group_id } debug { "Sso::Session::generate for #{user.inspect} - #{access_token.inspect} - #{attributes.inspect}" } create!(relations.merge(attributes)) end def logout(sso_session_id) sso_session = find(sso_session_id) group_id = sso_session.group_id debug { "Sso::Session#logout - Revoking Session Group #{sso_session.group_id.inspect} from Session #{sso_session.id.inspect}" } count = where(group_id: group_id).update_all revoked_at: Time.current, revoke_reason: "logout" debug { "Successfully removed #{count.inspect} sessions." } count end def update_master_with_grant(master_sso_session_id, oauth_grant) master_sso_session = active.master.find(master_sso_session_id) if master_sso_session.update_attribute(:access_grant_id, oauth_grant.id) debug { "#update_master_with_grant : #{master_sso_session.id} with Access Grant ID #{oauth_grant.id} which is #{oauth_grant.token}" } else error { "#update_master_with_grant : FAILED to update oauth_grant" } end end def update_master_with_access_token(grant_token, access_token) oauth_grant = Doorkeeper::AccessGrant.by_token(grant_token) oauth_token = Doorkeeper::AccessToken.by_token(access_token) return false if oauth_token.blank? or oauth_grant.blank? master_sso_session = active.master.find_by!(access_grant_id: oauth_grant.id) if master_sso_session.update_attribute(:access_token_id, oauth_token.id) debug { "#register_access_token : #{master_sso_session.id} with Access Token ID #{oauth_token.id} which is #{oauth_token.token}" } else error { "#register_access_token : FAILED to update oauth_access_token_id" } end master_sso_session end end def create_session(token, options = {}) create(access_token_id) end # def to_s # ['Sso:Session', owner_id, ip, activity_at].join ', ' # end private def ensure_secret self.secret ||= SecureRandom.uuid end def ensure_group_id self.group_id ||= SecureRandom.uuid end def ensure_activity_at self.activity_at ||= Time.current end end end # Sso # == Schema Information # Schema version: 20150330031153 # # Table name: sso_sessions # # id :uuid not null, primary key # access_grant_id :integer # access_token_id :integer # application_id :integer # owner_id :integer not null # group_id :string not null # secret :string not null # ip :inet not null # agent :string # location :string # activity_at :datetime not null # revoked_at :datetime # revoke_reason :string # created_at :datetime not null # updated_at :datetime not null # # Indexes # # index_sso_sessions_on_access_grant_id (access_grant_id) # index_sso_sessions_on_access_token_id (access_token_id) # index_sso_sessions_on_application_id (application_id) # index_sso_sessions_on_group_id (group_id) # index_sso_sessions_on_ip (ip) # index_sso_sessions_on_owner_id (owner_id) # index_sso_sessions_on_revoke_reason (revoke_reason) # index_sso_sessions_on_secret (secret) # one_access_token_per_owner (owner_id,access_token_id,application_id) UNIQUE #