aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@gmail.com>2009-12-22 08:26:00 +0100
committerJosé Valim <jose.valim@gmail.com>2009-12-22 08:26:00 +0100
commit4b8330d2d50ae4de14dd43ffbea4d91804553140 (patch)
tree8d925e361688cf09ab6e3fe8df6b9609a69ffa83 /actionpack/lib/action_controller
parent5f34421c77b4cd873baadbbca877a93de5a4d602 (diff)
parent8e48a5ef0ca488b2264acd2b38bdae14970c011f (diff)
downloadrails-4b8330d2d50ae4de14dd43ffbea4d91804553140.tar.gz
rails-4b8330d2d50ae4de14dd43ffbea4d91804553140.tar.bz2
rails-4b8330d2d50ae4de14dd43ffbea4d91804553140.zip
Merge branch 'master' of git://github.com/rails/rails
Diffstat (limited to 'actionpack/lib/action_controller')
-rw-r--r--actionpack/lib/action_controller/metal/cookies.rb168
-rw-r--r--actionpack/lib/action_controller/metal/rack_delegation.rb6
2 files changed, 135 insertions, 39 deletions
diff --git a/actionpack/lib/action_controller/metal/cookies.rb b/actionpack/lib/action_controller/metal/cookies.rb
index e27374e4c4..8d5f0d7199 100644
--- a/actionpack/lib/action_controller/metal/cookies.rb
+++ b/actionpack/lib/action_controller/metal/cookies.rb
@@ -50,56 +50,148 @@ module ActionController #:nodoc:
included do
helper_method :cookies
+ cattr_accessor :cookie_verifier_secret
end
- protected
- # Returns the cookie container, which operates as described above.
- def cookies
- @cookies ||= CookieJar.build(request, response)
+ protected
+ # Returns the cookie container, which operates as described above.
+ def cookies
+ @cookies ||= CookieJar.build(request, response)
+ end
end
- end
- class CookieJar < Hash #:nodoc:
- def self.build(request, response)
- new.tap do |hash|
- hash.update(request.cookies)
- hash.response = response
+ class CookieJar < Hash #:nodoc:
+ def self.build(request, response)
+ new.tap do |hash|
+ hash.update(request.cookies)
+ hash.response = response
+ end
end
- end
- attr_accessor :response
+ attr_accessor :response
- # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists.
- def [](name)
- super(name.to_s)
- end
+ # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists.
+ def [](name)
+ super(name.to_s)
+ end
+
+ # Sets the cookie named +name+. The second argument may be the very cookie
+ # value, or a hash of options as documented above.
+ def []=(key, options)
+ if options.is_a?(Hash)
+ options.symbolize_keys!
+ value = options[:value]
+ else
+ value = options
+ options = { :value => value }
+ end
- # Sets the cookie named +name+. The second argument may be the very cookie
- # value, or a hash of options as documented above.
- def []=(key, options)
- if options.is_a?(Hash)
+ super(key.to_s, value)
+
+ options[:path] ||= "/"
+ response.set_cookie(key, options)
+ end
+
+ # Removes the cookie on the client machine by setting the value to an empty string
+ # and setting its expiration date into the past. Like <tt>[]=</tt>, you can pass in
+ # an options hash to delete cookies with extra data such as a <tt>:path</tt>.
+ def delete(key, options = {})
options.symbolize_keys!
- value = options[:value]
- else
- value = options
- options = { :value => value }
+ options[:path] ||= "/"
+ value = super(key.to_s)
+ response.delete_cookie(key, options)
+ value
end
- super(key.to_s, value)
-
- options[:path] ||= "/"
- response.set_cookie(key, options)
+ # Returns a jar that'll automatically set the assigned cookies to have an expiration date 20 years from now. Example:
+ #
+ # cookies.permanent[:prefers_open_id] = true
+ # # => Set-Cookie: prefers_open_id=true; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT
+ #
+ # This jar is only meant for writing. You'll read permanent cookies through the regular accessor.
+ #
+ # This jar allows chaining with the signed jar as well, so you can set permanent, signed cookies. Examples:
+ #
+ # cookies.permanent.signed[:remember_me] = current_user.id
+ # # => Set-Cookie: discount=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT
+ def permanent
+ @permanent ||= PermanentCookieJar.new(self)
+ end
+
+ # Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from
+ # the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed
+ # cookie was tampered with by the user (or a 3rd party), an ActiveSupport::MessageVerifier::InvalidSignature exception will
+ # be raised.
+ #
+ # This jar requires that you set a suitable secret for the verification on ActionController::Base.cookie_verifier_secret.
+ #
+ # Example:
+ #
+ # cookies.signed[:discount] = 45
+ # # => Set-Cookie: discount=BAhpMg==--2c1c6906c90a3bc4fd54a51ffb41dffa4bf6b5f7; path=/
+ #
+ # cookies.signed[:discount] # => 45
+ def signed
+ @signed ||= SignedCookieJar.new(self)
+ end
end
-
- # Removes the cookie on the client machine by setting the value to an empty string
- # and setting its expiration date into the past. Like <tt>[]=</tt>, you can pass in
- # an options hash to delete cookies with extra data such as a <tt>:path</tt>.
- def delete(key, options = {})
- options.symbolize_keys!
- options[:path] ||= "/"
- value = super(key.to_s)
- response.delete_cookie(key, options)
- value
+
+ class PermanentCookieJar < CookieJar #:nodoc:
+ def initialize(parent_jar)
+ @parent_jar = parent_jar
+ end
+
+ def []=(key, options)
+ if options.is_a?(Hash)
+ options.symbolize_keys!
+ else
+ options = { :value => options }
+ end
+
+ options[:expires] = 20.years.from_now
+ @parent_jar[key] = options
+ end
+
+ def signed
+ @signed ||= SignedCookieJar.new(self)
+ end
+
+ def controller
+ @parent_jar.controller
+ end
+
+ def method_missing(method, *arguments, &block)
+ @parent_jar.send(method, *arguments, &block)
+ end
end
+
+ class SignedCookieJar < CookieJar #:nodoc:
+ def initialize(parent_jar)
+ unless ActionController::Base.cookie_verifier_secret
+ raise "You must set ActionController::Base.cookie_verifier_secret to use signed cookies"
+ end
+
+ @parent_jar = parent_jar
+ @verifier = ActiveSupport::MessageVerifier.new(ActionController::Base.cookie_verifier_secret)
+ end
+
+ def [](name)
+ @verifier.verify(@parent_jar[name])
+ end
+
+ def []=(key, options)
+ if options.is_a?(Hash)
+ options.symbolize_keys!
+ options[:value] = @verifier.generate(options[:value])
+ else
+ options = { :value => @verifier.generate(options) }
+ end
+
+ @parent_jar[key] = options
+ end
+
+ def method_missing(method, *arguments, &block)
+ @parent_jar.send(method, *arguments, &block)
+ end
end
end
diff --git a/actionpack/lib/action_controller/metal/rack_delegation.rb b/actionpack/lib/action_controller/metal/rack_delegation.rb
index 5141918499..833475cff7 100644
--- a/actionpack/lib/action_controller/metal/rack_delegation.rb
+++ b/actionpack/lib/action_controller/metal/rack_delegation.rb
@@ -3,7 +3,7 @@ module ActionController
extend ActiveSupport::Concern
included do
- delegate :session, :reset_session, :to => "@_request"
+ delegate :session, :to => "@_request"
delegate :headers, :status=, :location=, :content_type=,
:status, :location, :content_type, :to => "@_response"
attr_internal :request
@@ -24,5 +24,9 @@ module ActionController
response.body = body if response
super
end
+
+ def reset_session
+ @_request.reset_session
+ end
end
end