Class: DoorMat::Session
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- DoorMat::Session
- Defined in:
- app/models/door_mat/session.rb
Instance Attribute Summary collapse
-
#token ⇒ Object
Returns the value of attribute token.
Class Method Summary collapse
- .clean_up(cookies) ⇒ Object
-
.clear_current_session ⇒ Object
destroy existing valid session if any at sign_in and sign_up time or when expired to prevent unreferenced sessions from accumulating in the store.
-
.current_session ⇒ Object
The current_session is never nil but it might not be valid Check with DoorMat::Session.current_session.valid?.
- .destroy_if_linked_to(cookies) ⇒ Object
- .for(actor, password, request) ⇒ Object
- .from(cookies, request) ⇒ Object
- .new_sub_session_for_actor(actor, password) ⇒ Object
Instance Method Summary collapse
- #append_sub_session(session) ⇒ Object
- #autoload_sesion_for(actor) ⇒ Object
- #decrypt(ciphertext) ⇒ Object
- #encrypt(message) ⇒ Object
- #initialization_performed? ⇒ Boolean
- #initialize_with(actor, password) ⇒ Object
- #is_older_than(minutes_old) ⇒ Object
- #memberships_for(actor) ⇒ Object
- #package_recovery_key ⇒ Object
- #re_key_with(actor, password) ⇒ Object
- #reconfirm_password(password) ⇒ Object
- #recovery_key_restore(actor, recovery_key) ⇒ Object
- #renew_session_key_and_token(old_session_key, cookies) ⇒ Object
- #session_for_actor_loaded?(actor) ⇒ Boolean
- #set_up(cookies) ⇒ Object
- #unlock_with(session_key) ⇒ Object
- #with_session_for_actor(actor) ⇒ Object
Instance Attribute Details
#token ⇒ Object
Returns the value of attribute token.
7 8 9 |
# File 'app/models/door_mat/session.rb', line 7 def token @token end |
Class Method Details
.clean_up(cookies) ⇒ Object
224 225 226 227 228 229 |
# File 'app/models/door_mat/session.rb', line 224 def self.clean_up() .delete(:session_guid) .delete(:session_key) nil end |
.clear_current_session ⇒ Object
destroy existing valid session if any at sign_in and sign_up time or when expired to prevent unreferenced sessions from accumulating in the store
28 29 30 31 32 33 34 35 |
# File 'app/models/door_mat/session.rb', line 28 def self.clear_current_session session = current_session RequestStore.store[:current_session] = nil session.destroy if session.persisted? nil end |
.current_session ⇒ Object
The current_session is never nil but it might not be valid Check with DoorMat::Session.current_session.valid?
21 22 23 |
# File 'app/models/door_mat/session.rb', line 21 def self.current_session RequestStore.store[:current_session] ||= self.new end |
.destroy_if_linked_to(cookies) ⇒ Object
199 200 201 202 203 204 205 206 207 208 209 |
# File 'app/models/door_mat/session.rb', line 199 def self.destroy_if_linked_to() session_guid = .encrypted[:session_guid].to_s.strip clean_up() return false if DoorMat::Regex.session_guid.match(session_guid).blank? session = self.find_by(hashed_token: DoorMat::Crypto::FastHash.sha256(session_guid) ) || self.new return false unless session.persisted? session.destroy! true end |
.for(actor, password, request) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 |
# File 'app/models/door_mat/session.rb', line 37 def self.for(actor, password, request) clear_current_session return nil if password.blank? || actor.key_salt.blank? session = self.new session.ip = request.remote_ip session.agent = request.user_agent RequestStore.store[:current_session] = session.initialize_with(actor, password) end |
.from(cookies, request) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'app/models/door_mat/session.rb', line 126 def self.from(, request) clear_current_session session_guid = .encrypted[:session_guid].to_s.strip session_key = .encrypted[:session_key].to_s.strip return nil if session_guid.blank? || session_key.blank? return nil if DoorMat::Regex.session_guid.match(session_guid).blank? session = self.find_by(hashed_token: DoorMat::Crypto::FastHash.sha256(session_guid) ) || self.new session.token = session_guid if session.actor.nil? session.destroy! return nil end case when session.remember_me? if session.created_at < DoorMat.configuration.remember_me_max_day_count.days.ago session.destroy! return nil end if session.updated_at < DoorMat.configuration.private_computer_access_session_timeout.minutes.ago session_key = session.renew_session_key_and_token(session_key, ) end when session.private_computer? if session.updated_at < DoorMat.configuration.private_computer_access_session_timeout.minutes.ago session.destroy! return nil end else if session.updated_at < DoorMat.configuration.public_computer_access_session_timeout.minutes.ago session.destroy! return nil end end session.ip = request.remote_ip session.agent = request.user_agent # Check for major change in user_agent in case of strict session policy session.updated_at = DateTime.current RequestStore.store[:current_session] = session if session.unlock_with(session_key) session.save else clear_current_session end end |
.new_sub_session_for_actor(actor, password) ⇒ Object
78 79 80 81 82 83 84 |
# File 'app/models/door_mat/session.rb', line 78 def self.new_sub_session_for_actor(actor, password) session = self.new session.initialize_with(actor, password) session.actor = actor session end |
Instance Method Details
#append_sub_session(session) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'app/models/door_mat/session.rb', line 86 def append_sub_session(session) unless DoorMat::Session.current_session == self DoorMat.configuration.logger.error "ERROR: append_sub_session must only be called on DoorMat::Session.current_session" return false end unless session.valid? DoorMat.configuration.logger.error "ERROR: append_sub_session was given an invalid session" return false end actor_id = session.actor.id if sub_sessions.has_key? actor_id DoorMat.configuration.logger.warn "WARN: sub_session #{actor_id} already present; updating." end sub_sessions[actor_id] = session return true end |
#autoload_sesion_for(actor) ⇒ Object
115 116 117 118 119 120 121 122 123 124 |
# File 'app/models/door_mat/session.rb', line 115 def autoload_sesion_for(actor) return if session_for_actor_loaded?(actor) memberships = memberships_for(actor) unless memberships.empty? membership = memberships.first session = DoorMat::Session.new_sub_session_for_actor(membership.member_of, membership.key) append_sub_session(session) end end |
#decrypt(ciphertext) ⇒ Object
247 248 249 250 251 252 |
# File 'app/models/door_mat/session.rb', line 247 def decrypt(ciphertext) DoorMat::Crypto::SymmetricStore.decrypt(ciphertext, @symmetric_actor_key.first) rescue OpenSSL::Cipher::CipherError => e DoorMat.configuration.logger.warn "WARN: Failed to decrypt for actor #{self.actor.id} - #{e}" nil end |
#encrypt(message) ⇒ Object
243 244 245 |
# File 'app/models/door_mat/session.rb', line 243 def encrypt() DoorMat::Crypto::SymmetricStore.encrypt(, @symmetric_actor_key.last)[:ciphertext] end |
#initialization_performed? ⇒ Boolean
13 14 15 16 17 |
# File 'app/models/door_mat/session.rb', line 13 def initialization_performed? if @symmetric_actor_key.blank? || @symmetric_actor_key.first.blank? || @session_key.blank? || @token.blank? || self.hashed_token.blank? errors.add(:base, I18n.t("door_mat.session.initialization_failure")) end end |
#initialize_with(actor, password) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'app/models/door_mat/session.rb', line 49 def initialize_with(actor, password) reset self.email = actor.current_email re_key_with(actor, password) self rescue Exception => e reset DoorMat.configuration.logger.error "ERROR: Failed to initialize session with password for actor #{actor.id} - #{e}" nil end |
#is_older_than(minutes_old) ⇒ Object
231 232 233 |
# File 'app/models/door_mat/session.rb', line 231 def is_older_than(minutes_old) self.password_authenticated_at < minutes_old.minutes.ago end |
#memberships_for(actor) ⇒ Object
106 107 108 109 110 111 112 113 |
# File 'app/models/door_mat/session.rb', line 106 def memberships_for(actor) current_session_ids = sub_sessions.keys current_session_ids.push(self.actor_id) unless self.actor_id.nil? DoorMat::Membership.where("member_of_id = :member_of and member_id in (:ids)", :member_of => actor.id, :ids => current_session_ids).select {|m| !m.readonly?} end |
#package_recovery_key ⇒ Object
254 255 256 257 258 259 |
# File 'app/models/door_mat/session.rb', line 254 def package_recovery_key h = DoorMat::Crypto::SymmetricStore.encrypt(@symmetric_actor_key.last) self.actor.recovery_key = h[:ciphertext] self.actor.save! self.actor.system_encrypt(h[:key]) end |
#re_key_with(actor, password) ⇒ Object
63 64 65 66 67 68 69 70 71 72 |
# File 'app/models/door_mat/session.rb', line 63 def re_key_with(actor, password) @symmetric_actor_key << DoorMat::Crypto::PasswordHash.pbkdf2_hash(password, actor.key_salt) encrypt_actor_key(actor, @symmetric_actor_key.last) set_new_token self.password_authenticated_at = DateTime.current self end |
#reconfirm_password(password) ⇒ Object
271 272 273 274 275 276 277 278 279 |
# File 'app/models/door_mat/session.rb', line 271 def reconfirm_password(password) if self.actor.authenticate(password) self.password_authenticated_at = DateTime.current self.save! true else false end end |
#recovery_key_restore(actor, recovery_key) ⇒ Object
261 262 263 264 265 266 267 268 269 |
# File 'app/models/door_mat/session.rb', line 261 def recovery_key_restore(actor, recovery_key) self.actor = actor key = self.actor.system_decrypt(recovery_key) @symmetric_actor_key = [DoorMat::Crypto::SymmetricStore.decrypt(self.actor.recovery_key, key)] true rescue OpenSSL::Cipher::CipherError => e DoorMat.configuration.logger.warn "WARN: Failed recovery_key_restore for actor #{self.actor.id} - #{e}" false end |
#renew_session_key_and_token(old_session_key, cookies) ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 |
# File 'app/models/door_mat/session.rb', line 173 def renew_session_key_and_token(old_session_key, ) if unlock_with(old_session_key) encrypt_actor_key(self.actor, @symmetric_actor_key.last) set_new_token set_up() end @session_key end |
#session_for_actor_loaded?(actor) ⇒ Boolean
74 75 76 |
# File 'app/models/door_mat/session.rb', line 74 def session_for_actor_loaded?(actor) actor.nil? || (self.actor == actor) || (sub_sessions.has_key? actor.id) end |
#set_up(cookies) ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'app/models/door_mat/session.rb', line 211 def set_up() = { secure: DoorMat.configuration., httponly: true } .merge!({ expires: DoorMat.configuration.remember_me_max_day_count.days.since(self.created_at) }) unless self.public_computer? .encrypted[:session_guid] = .merge({value: self.token}) .encrypted[:session_key] = .merge({value: @session_key}) nil end |
#unlock_with(session_key) ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'app/models/door_mat/session.rb', line 185 def unlock_with(session_key) @symmetric_actor_key = [DoorMat::Crypto::SymmetricStore.decrypt( self.encrypted_symmetric_actor_key, self.actor.system_decrypt(session_key) )] @session_key = session_key true rescue Exception => e reset DoorMat.configuration.logger.error "ERROR: Failed to unlock session with session_key for actor #{self.actor.id} - #{e}" false end |
#with_session_for_actor(actor) ⇒ Object
235 236 237 238 239 240 241 |
# File 'app/models/door_mat/session.rb', line 235 def with_session_for_actor(actor) if self.valid? && (actor.nil? || self.actor_id.nil? || self.actor == actor) yield(self) elsif !actor.nil? && (sub_sessions.has_key? actor.id) yield(sub_sessions[actor.id]) end end |