mirror of
https://github.com/github/rails.git
synced 2026-01-08 22:27:59 -05:00
Merge pull request #64 from github/json-sessions
Support custom serialization for Session::CookieStore
This commit is contained in:
@@ -1 +1 @@
|
||||
2.3.14.github43
|
||||
2.3.14.github45
|
||||
|
||||
@@ -45,37 +45,74 @@ module ActionController #:nodoc:
|
||||
end
|
||||
|
||||
def []=(k, v)
|
||||
k = k.to_s
|
||||
@flash[k] = v
|
||||
@flash.discard(k)
|
||||
v
|
||||
end
|
||||
|
||||
def [](k)
|
||||
@flash[k]
|
||||
@flash[k.to_s]
|
||||
end
|
||||
end
|
||||
|
||||
class FlashHash < Hash
|
||||
def self.from_session_value(value)
|
||||
flash = case value
|
||||
when FlashHash # Rails 2.3
|
||||
value
|
||||
when Hash # Rails 4.0
|
||||
flashes = value['flashes'] || {}
|
||||
flashes.stringify_keys!
|
||||
discard = value['discard'] || []
|
||||
discard = discard.map do |item|
|
||||
item.kind_of?(Symbol) ? item.to_s : item
|
||||
end
|
||||
used = Hash[flashes.keys.map{|k| [k, discard.include?(k)] }]
|
||||
|
||||
new_from_values(flashes, used)
|
||||
else
|
||||
new
|
||||
end
|
||||
flash
|
||||
end
|
||||
|
||||
def initialize #:nodoc:
|
||||
super
|
||||
@used = {}
|
||||
end
|
||||
|
||||
def to_session_value
|
||||
return nil if empty?
|
||||
rails_3_discard_list = @used.map{|k,v| k if v}.compact
|
||||
{'discard' => rails_3_discard_list, 'flashes' => Hash[to_a]}
|
||||
end
|
||||
|
||||
def []=(k, v) #:nodoc:
|
||||
k = k.to_s
|
||||
keep(k)
|
||||
super
|
||||
super(k, v)
|
||||
end
|
||||
|
||||
def [](k)
|
||||
super(k.to_s)
|
||||
end
|
||||
|
||||
def delete(k)
|
||||
super(k.to_s)
|
||||
end
|
||||
|
||||
def update(h) #:nodoc:
|
||||
h.stringify_keys!
|
||||
h.keys.each { |k| keep(k) }
|
||||
super
|
||||
super(h)
|
||||
end
|
||||
|
||||
alias :merge! :update
|
||||
|
||||
def replace(h) #:nodoc:
|
||||
@used = {}
|
||||
super
|
||||
super(h.stringify_keys)
|
||||
end
|
||||
|
||||
# Sets a flash that will not be available to the next action, only to the current.
|
||||
@@ -126,8 +163,7 @@ module ActionController #:nodoc:
|
||||
end
|
||||
|
||||
def store(session, key = "flash")
|
||||
return if self.empty?
|
||||
session[key] = self
|
||||
session[key] = to_session_value
|
||||
end
|
||||
|
||||
private
|
||||
@@ -138,11 +174,20 @@ module ActionController #:nodoc:
|
||||
# use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action)
|
||||
def use(k=nil, v=true)
|
||||
unless k.nil?
|
||||
@used[k] = v
|
||||
@used[k.to_s] = v
|
||||
else
|
||||
keys.each{ |key| use(key, v) }
|
||||
end
|
||||
end
|
||||
|
||||
def self.new_from_values(flashes, used)
|
||||
new.tap do |flash_hash|
|
||||
flashes.each do |k, v|
|
||||
flash_hash[k] = v
|
||||
end
|
||||
flash_hash.instance_variable_set("@used", used)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods #:nodoc:
|
||||
@@ -168,11 +213,11 @@ module ActionController #:nodoc:
|
||||
if notice = response_status_and_flash.delete(:notice)
|
||||
flash[:notice] = notice
|
||||
end
|
||||
|
||||
|
||||
if other_flashes = response_status_and_flash.delete(:flash)
|
||||
flash.update(other_flashes)
|
||||
end
|
||||
|
||||
|
||||
redirect_to_without_flash(options, response_status_and_flash)
|
||||
end
|
||||
|
||||
@@ -181,19 +226,19 @@ module ActionController #:nodoc:
|
||||
# to put a new one.
|
||||
def flash #:doc:
|
||||
if !defined?(@_flash)
|
||||
@_flash = session["flash"] || FlashHash.new
|
||||
@_flash = Flash::FlashHash.from_session_value(session["flash"])
|
||||
@_flash.sweep
|
||||
end
|
||||
|
||||
@_flash
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Convenience accessor for flash[:alert]
|
||||
def alert
|
||||
flash[:alert]
|
||||
end
|
||||
|
||||
|
||||
# Convenience accessor for flash[:alert]=
|
||||
def alert=(message)
|
||||
flash[:alert] = message
|
||||
@@ -203,7 +248,7 @@ module ActionController #:nodoc:
|
||||
def notice
|
||||
flash[:notice]
|
||||
end
|
||||
|
||||
|
||||
# Convenience accessor for flash[:notice]=
|
||||
def notice=(message)
|
||||
flash[:notice] = message
|
||||
|
||||
@@ -2,7 +2,7 @@ require 'rack/utils'
|
||||
|
||||
module ActionController
|
||||
module Session
|
||||
class AbstractStore
|
||||
class AbstractStore
|
||||
ENV_SESSION_KEY = 'rack.session'.freeze
|
||||
ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze
|
||||
|
||||
@@ -55,17 +55,17 @@ module ActionController
|
||||
|
||||
def [](key)
|
||||
load_for_read!
|
||||
super
|
||||
super(key.to_s) || super(key)
|
||||
end
|
||||
|
||||
def has_key?(key)
|
||||
load_for_read!
|
||||
super
|
||||
super(key.to_s) || super(key)
|
||||
end
|
||||
|
||||
def []=(key, value)
|
||||
load_for_write!
|
||||
super
|
||||
super(key.to_s, value)
|
||||
end
|
||||
|
||||
def clear
|
||||
@@ -87,7 +87,9 @@ module ActionController
|
||||
|
||||
def delete(key)
|
||||
load_for_write!
|
||||
super
|
||||
value = super(key)
|
||||
string_value = super(key.to_s)
|
||||
string_value || value
|
||||
end
|
||||
|
||||
def data
|
||||
@@ -119,7 +121,7 @@ module ActionController
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
def load_for_read!
|
||||
load! if !loaded? && exists?
|
||||
end
|
||||
@@ -183,7 +185,7 @@ module ActionController
|
||||
request = ActionController::Request.new(env)
|
||||
|
||||
return response if (options[:secure] && !request.ssl?)
|
||||
|
||||
|
||||
session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded?
|
||||
|
||||
sid = options[:id] || generate_sid
|
||||
@@ -205,12 +207,12 @@ module ActionController
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
def prepare!(env)
|
||||
env[ENV_SESSION_KEY] = SessionHash.new(self, env)
|
||||
env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options)
|
||||
end
|
||||
|
||||
|
||||
def generate_sid
|
||||
ActiveSupport::SecureRandom.hex(16)
|
||||
end
|
||||
@@ -222,7 +224,7 @@ module ActionController
|
||||
[sid, session]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def extract_session_id(env)
|
||||
stale_session_check! do
|
||||
request = Rack::Request.new(env)
|
||||
@@ -235,7 +237,7 @@ module ActionController
|
||||
def current_session_id(env)
|
||||
env[ENV_SESSION_OPTIONS_KEY][:id]
|
||||
end
|
||||
|
||||
|
||||
def exists?(env)
|
||||
current_session_id(env).present?
|
||||
end
|
||||
@@ -247,11 +249,11 @@ module ActionController
|
||||
def set_session(env, sid, session_data)
|
||||
raise '#set_session needs to be implemented.'
|
||||
end
|
||||
|
||||
|
||||
def destroy(env)
|
||||
raise '#destroy needs to be implemented.'
|
||||
end
|
||||
|
||||
|
||||
module SessionUtils
|
||||
private
|
||||
def stale_session_check!
|
||||
|
||||
@@ -86,7 +86,8 @@ module ActionController
|
||||
@secret = options.delete(:secret).freeze
|
||||
|
||||
@digest = options.delete(:digest) || 'SHA1'
|
||||
@verifier = verifier_for(@secret, @digest)
|
||||
@serializer = options.delete(:serializer) || Marshal
|
||||
@verifier = verifier_for(@secret, @digest, @serializer)
|
||||
|
||||
@default_options = DEFAULT_OPTIONS.merge(options).freeze
|
||||
|
||||
@@ -138,13 +139,13 @@ module ActionController
|
||||
def load_session(env)
|
||||
data = unpacked_cookie_data(env)
|
||||
data = persistent_session_id!(data)
|
||||
[data[:session_id], data]
|
||||
[data["session_id"] || data[:session_id], data]
|
||||
end
|
||||
|
||||
def extract_session_id(env)
|
||||
if data = unpacked_cookie_data(env)
|
||||
persistent_session_id!(data) unless data.empty?
|
||||
data[:session_id]
|
||||
data["session_id"] || data[:session_id]
|
||||
else
|
||||
nil
|
||||
end
|
||||
@@ -214,9 +215,9 @@ module ActionController
|
||||
end
|
||||
end
|
||||
|
||||
def verifier_for(secret, digest)
|
||||
def verifier_for(secret, digest, serializer)
|
||||
key = secret.respond_to?(:call) ? secret.call : secret
|
||||
ActiveSupport::MessageVerifier.new(key, digest: digest)
|
||||
ActiveSupport::MessageVerifier.new(key, digest: digest, serializer: serializer)
|
||||
end
|
||||
|
||||
def generate_sid
|
||||
@@ -232,12 +233,12 @@ module ActionController
|
||||
end
|
||||
|
||||
def inject_persistent_session_id(data)
|
||||
requires_session_id?(data) ? { :session_id => generate_sid } : {}
|
||||
requires_session_id?(data) ? { "session_id" => generate_sid } : {}
|
||||
end
|
||||
|
||||
def requires_session_id?(data)
|
||||
if data
|
||||
data.respond_to?(:key?) && !data.key?(:session_id)
|
||||
data.respond_to?(:key?) && !(data.key?("session_id") || data.key?(:session_id))
|
||||
else
|
||||
true
|
||||
end
|
||||
|
||||
@@ -219,7 +219,7 @@ module ActionController #:nodoc:
|
||||
|
||||
# A shortcut to the flash. Returns an empty hash if no session flash exists.
|
||||
def flash
|
||||
session['flash'] || {}
|
||||
ActionController::Flash::FlashHash.from_session_value(session["flash"]) || {}
|
||||
end
|
||||
|
||||
# Do we have a flash?
|
||||
|
||||
Reference in New Issue
Block a user