Guest User

Untitled

a guest
Nov 21st, 2018
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.14 KB | None | 0 0
  1. # Place me in initializers
  2. # Configure the database connection
  3. #
  4. require 'sequel'
  5. module Rails
  6. class SessionStore < ActionDispatch::Session::AbstractStore
  7. module ClassMethods # :nodoc:
  8. def marshal(data)
  9. ::Base64.encode64(Marshal.dump(data)) if data
  10. end
  11.  
  12. def unmarshal(data)
  13. Marshal.load(::Base64.decode64(data)) if data
  14. end
  15. end
  16.  
  17.  
  18. # A barebones session store which duck-types with the default session
  19. # store but bypasses Active Record and issues SQL directly. This is
  20. # an example session model class meant as a basis for your own classes.
  21. #
  22. # The database connection, table name, and session id and data columns
  23. # are configurable class attributes. Marshaling and unmarshaling
  24. # are implemented as class methods that you may override. By default,
  25. # marshaling data is
  26. #
  27. # ::Base64.encode64(Marshal.dump(data))
  28. #
  29. # and unmarshaling data is
  30. #
  31. # Marshal.load(::Base64.decode64(data))
  32. #
  33. # This marshaling behavior is intended to store the widest range of
  34. # binary session data in a +text+ column. For higher performance,
  35. # store in a +blob+ column instead and forgo the Base64 encoding.
  36. class SqlBypass
  37. extend ClassMethods
  38.  
  39. ##
  40. # :singleton-method:
  41. # The table name defaults to 'sessions'.
  42. cattr_accessor :table_name
  43. @@table_name = 'sessions'
  44.  
  45. ##
  46. # :singleton-method:
  47. # The session id field defaults to 'session_id'.
  48. cattr_accessor :session_id_column
  49. @@session_id_column = 'session_id'
  50.  
  51. ##
  52. # :singleton-method:
  53. # The data field defaults to 'data'.
  54. cattr_accessor :data_column
  55. @@data_column = 'data'
  56.  
  57. class << self
  58. alias :data_column_name :data_column
  59.  
  60. attr_writer :connection
  61.  
  62. attr_writer :connection_pool # Is this needed?
  63.  
  64. def connection
  65. @connection ||= ::Sequel.connect(:adapter=>'postgres', :host=>'localhost', :database=>'xxx', :user=>'xxx', :password=>'xxx')
  66. end
  67.  
  68. # def connection_pool
  69. # @connection_pool ||= ::Sequel.connect(:adapter=>'postgres', :host=>'localhost', :database=>'', :user=>'', :password=>'')
  70. # end
  71.  
  72. # Look up a session by id and unmarshal its data if found.
  73. def find_by_session_id(session_id)
  74. record = connection.fetch("SELECT * FROM #{@@table_name} WHERE #{@@session_id_column}='#{session_id}'").first
  75. # debugger
  76. if !record.nil?
  77. new(:session_id => session_id, :marshaled_data => record[:data])
  78. end
  79. end
  80. end
  81.  
  82. delegate :connection, :connection=, :connection_pool, :connection_pool=, :to => self
  83.  
  84. attr_reader :session_id, :new_record
  85. alias :new_record? :new_record
  86.  
  87. attr_writer :data
  88.  
  89. # Look for normal and marshaled data, self.find_by_session_id's way of
  90. # telling us to postpone unmarshaling until the data is requested.
  91. # We need to handle a normal data attribute in case of a new record.
  92. def initialize(attributes)
  93. @session_id = attributes[:session_id]
  94. @data = attributes[:data]
  95. @marshaled_data = attributes[:marshaled_data]
  96. @new_record = @marshaled_data.nil?
  97. end
  98.  
  99. # Lazy-unmarshal session state.
  100. def data
  101. unless @data
  102. if @marshaled_data
  103. @data, @marshaled_data = self.class.unmarshal(@marshaled_data) || {}, nil
  104. else
  105. @data = {}
  106. end
  107. end
  108. @data
  109. end
  110.  
  111. def loaded?
  112. @data
  113. end
  114.  
  115. def save
  116. return false unless loaded?
  117. marshaled_data = self.class.marshal(data)
  118. connect = connection
  119.  
  120. if @new_record
  121. @new_record = false
  122. connect << "INSERT INTO #{table_name} (#{session_id_column}, #{data_column}) VALUES ('#{session_id}', '#{marshaled_data}')"
  123. else
  124. connect << "UPDATE #{table_name} SET #{data_column}='#{marshaled_data}' WHERE #{session_id_column}='#{session_id}'"
  125. end
  126. end
  127.  
  128. def destroy
  129. return if @new_record
  130. connect = connection
  131. connect << "DELETE FROM #{table_name} WHERE #{session_id_column}='#{session_id}'"
  132. end
  133. end
  134.  
  135. # The class used for session storage.
  136. cattr_accessor :session_class
  137. self.session_class = SqlBypass
  138.  
  139. SESSION_RECORD_KEY = 'rack.session.record'
  140. ENV_SESSION_OPTIONS_KEY = ::Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY
  141.  
  142. private
  143. def get_session(env, sid)
  144. # Base.silence do
  145. unless sid and session = @@session_class.find_by_session_id(sid)
  146. # If the sid was nil or if there is no pre-existing session under the sid,
  147. # force the generation of a new sid and associate a new session associated with the new sid
  148. sid = generate_sid
  149. session = @@session_class.new(:session_id => sid, :data => {})
  150. end
  151. env[SESSION_RECORD_KEY] = session
  152. [sid, session.data]
  153. # end
  154. end
  155.  
  156. def set_session(env, sid, session_data, options)
  157. # Base.silence do
  158. record = get_session_model(env, sid)
  159. record.data = session_data
  160. return false unless record.save
  161.  
  162. session_data = record.data
  163. if session_data && session_data.respond_to?(:each_value)
  164. session_data.each_value do |obj|
  165. obj.clear_association_cache if obj.respond_to?(:clear_association_cache)
  166. end
  167. end
  168. # end
  169.  
  170. sid
  171. end
  172.  
  173. def destroy_session(env, session_id, options)
  174. if sid = current_session_id(env)
  175. # Base.silence do
  176. get_session_model(env, sid).destroy
  177. env[SESSION_RECORD_KEY] = nil
  178. # end
  179. end
  180.  
  181. generate_sid unless options[:drop]
  182. end
  183.  
  184. def get_session_model(env, sid)
  185. if env[ENV_SESSION_OPTIONS_KEY][:id].nil?
  186. env[SESSION_RECORD_KEY] = find_session(sid)
  187. else
  188. env[SESSION_RECORD_KEY] ||= find_session(sid)
  189. end
  190. end
  191.  
  192. def find_session(id)
  193. @@session_class.find_by_session_id(id) ||
  194. @@session_class.new(:session_id => id, :data => {})
  195. end
  196.  
  197. end
  198. end
Add Comment
Please, Sign In to add comment