mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
freshen :expires option with duration support and add expiry metadata to cookies
This commit is contained in:
parent
57585b6f3b
commit
5f37e16ab5
3 changed files with 54 additions and 5 deletions
|
@ -361,6 +361,10 @@ module ActionDispatch
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_options(options) # :nodoc:
|
def handle_options(options) # :nodoc:
|
||||||
|
if options[:expires].respond_to?(:from_now)
|
||||||
|
options[:expires] = options[:expires].from_now
|
||||||
|
end
|
||||||
|
|
||||||
options[:path] ||= "/"
|
options[:path] ||= "/"
|
||||||
|
|
||||||
if options[:domain] == :all || options[:domain] == "all"
|
if options[:domain] == :all || options[:domain] == "all"
|
||||||
|
@ -488,6 +492,14 @@ module ActionDispatch
|
||||||
def request; @parent_jar.request; end
|
def request; @parent_jar.request; end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
def expiry_options(options)
|
||||||
|
if options[:expires].respond_to?(:from_now)
|
||||||
|
{ expires_in: options[:expires] }
|
||||||
|
else
|
||||||
|
{ expires_at: options[:expires] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def parse(name, data); data; end
|
def parse(name, data); data; end
|
||||||
def commit(options); end
|
def commit(options); end
|
||||||
end
|
end
|
||||||
|
@ -569,7 +581,7 @@ module ActionDispatch
|
||||||
end
|
end
|
||||||
|
|
||||||
def commit(options)
|
def commit(options)
|
||||||
options[:value] = @verifier.generate(serialize(options[:value]))
|
options[:value] = @verifier.generate(serialize(options[:value]), expiry_options(options))
|
||||||
|
|
||||||
raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
|
raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
|
||||||
end
|
end
|
||||||
|
@ -609,7 +621,7 @@ module ActionDispatch
|
||||||
end
|
end
|
||||||
|
|
||||||
def commit(options)
|
def commit(options)
|
||||||
options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]))
|
options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]), expiry_options(options))
|
||||||
|
|
||||||
raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
|
raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
|
||||||
end
|
end
|
||||||
|
|
|
@ -278,6 +278,11 @@ class CookiesTest < ActionController::TestCase
|
||||||
def encrypted_cookie
|
def encrypted_cookie
|
||||||
cookies.encrypted["foo"]
|
cookies.encrypted["foo"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cookie_expires_in_two_hours
|
||||||
|
cookies[:user_name] = { value: "assain", expires: 2.hours }
|
||||||
|
head :ok
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
tests TestController
|
tests TestController
|
||||||
|
@ -1235,6 +1240,33 @@ class CookiesTest < ActionController::TestCase
|
||||||
assert_equal "bar", @controller.encrypted_cookie
|
assert_equal "bar", @controller.encrypted_cookie
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_signed_cookie_with_expires_set_relatively
|
||||||
|
cookies.signed[:user_name] = { value: "assain", expires: 2.hours }
|
||||||
|
|
||||||
|
travel 1.hour
|
||||||
|
assert_equal "assain", cookies.signed[:user_name]
|
||||||
|
|
||||||
|
travel 2.hours
|
||||||
|
assert_nil cookies.signed[:user_name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_encrypted_cookie_with_expires_set_relatively
|
||||||
|
cookies.encrypted[:user_name] = { value: "assain", expires: 2.hours }
|
||||||
|
|
||||||
|
travel 1.hour
|
||||||
|
assert_equal "assain", cookies.encrypted[:user_name]
|
||||||
|
|
||||||
|
travel 2.hours
|
||||||
|
assert_nil cookies.encrypted[:user_name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_vanilla_cookie_with_expires_set_relatively
|
||||||
|
travel_to Time.utc(2017, 8, 15) do
|
||||||
|
get :cookie_expires_in_two_hours
|
||||||
|
assert_cookie_header "user_name=assain; path=/; expires=Tue, 15 Aug 2017 02:00:00 -0000"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def assert_cookie_header(expected)
|
def assert_cookie_header(expected)
|
||||||
header = @response.headers["Set-Cookie"]
|
header = @response.headers["Set-Cookie"]
|
||||||
|
|
|
@ -26,6 +26,11 @@ class CookieStoreTest < ActionDispatch::IntegrationTest
|
||||||
render plain: Rack::Utils.escape(Verifier.generate(session.to_hash))
|
render plain: Rack::Utils.escape(Verifier.generate(session.to_hash))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_session_value_expires_in_five_hours
|
||||||
|
session[:foo] = "bar"
|
||||||
|
render plain: Rack::Utils.escape(Verifier.generate(session.to_hash, expires_in: 5.hours))
|
||||||
|
end
|
||||||
|
|
||||||
def get_session_value
|
def get_session_value
|
||||||
render plain: "foo: #{session[:foo].inspect}"
|
render plain: "foo: #{session[:foo].inspect}"
|
||||||
end
|
end
|
||||||
|
@ -283,7 +288,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest
|
||||||
|
|
||||||
cookies[SessionKey] = SignedBar
|
cookies[SessionKey] = SignedBar
|
||||||
|
|
||||||
get "/set_session_value"
|
get "/set_session_value_expires_in_five_hours"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
|
||||||
cookie_body = response.body
|
cookie_body = response.body
|
||||||
|
@ -299,7 +304,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest
|
||||||
get "/no_session_access"
|
get "/no_session_access"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
|
||||||
assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly",
|
assert_equal "_myapp_session=#{cookies[SessionKey]}; path=/; expires=#{expected_expiry}; HttpOnly",
|
||||||
headers["Set-Cookie"]
|
headers["Set-Cookie"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue