Skip to content

Commit

Permalink
Test and set Ruby v2.5 as minimum. (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix authored Oct 23, 2024
1 parent f9b045c commit 336e14b
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 55 deletions.
5 changes: 1 addition & 4 deletions .github/workflows/test-external.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,14 @@ jobs:
matrix:
os:
- ubuntu
# - macos

ruby:
- "2.7"
- "3.0"
- "3.1"
- "3.2"
- "3.3"

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{matrix.ruby}}
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ jobs:
- macos

ruby:
- "jruby"
- "2.5"
- "2.6"
- "2.7"
- "3.0"
- "3.1"
- "3.2"
- "3.3"

experimental: [false]

Expand All @@ -35,11 +35,15 @@ jobs:
ruby: truffleruby
experimental: true
- os: ubuntu
ruby: jruby-head
ruby: jruby
experimental: true
- os: ubuntu
ruby: head
experimental: true
exclude:
# Not supported on macos-arm64:
- os: macos
ruby: "2.5"

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion rack-session.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Gem::Specification.new do |spec|

spec.files = Dir['{lib}/**/*', '*.md']

spec.required_ruby_version = ">= 2.4.0"
spec.required_ruby_version = ">= 2.5"

spec.add_dependency "base64", ">= 0.1.0"
spec.add_dependency "rack", ">= 3.0.0"
Expand Down
54 changes: 27 additions & 27 deletions test/spec_session_cookie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def decode(str); @calls << :decode; JSON.parse(str); end
response = response_for(app: [incrementor, { coder: identity }])

response["Set-Cookie"].must_include "rack.session="
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)
identity.calls.must_equal [:encode]

response_for(app: [incrementor, { coder: identity }], cookie: response["Set-Cookie"].split(';', 2).first)
Expand All @@ -219,7 +219,7 @@ def decode(str); @calls << :decode; JSON.parse(str); end
it "creates a new cookie" do
response = response_for(app: incrementor)
response["Set-Cookie"].must_include "rack.session="
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)
end

it "passes through same_site option to session cookie" do
Expand All @@ -243,10 +243,10 @@ def decode(str); @calls << :decode; JSON.parse(str); end
response = response_for(app: incrementor)

response = response_for(app: incrementor, cookie: response)
response.body.must_equal '{"counter"=>2}'
response.body.must_equal ({"counter"=>2}.to_s)

response = response_for(app: incrementor, cookie: response)
response.body.must_equal '{"counter"=>3}'
response.body.must_equal ({"counter"=>3}.to_s)
end

it "renew session id" do
Expand Down Expand Up @@ -285,13 +285,13 @@ def decode(str); @calls << :decode; JSON.parse(str); end
app: incrementor,
cookie: "rack.session=blarghfasel"
)
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)

response = response_for(
app: [incrementor, { secrets: @secret }],
cookie: "rack.session="
)
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)
end

it "barks on too big cookies" do
Expand All @@ -305,15 +305,15 @@ def decode(str); @calls << :decode; JSON.parse(str); end

response = response_for(app: app)
response = response_for(app: app, cookie: response)
response.body.must_equal '{"counter"=>2}'
response.body.must_equal ({"counter"=>2}.to_s)

response = response_for(app: app, cookie: response)
response.body.must_equal '{"counter"=>3}'
response.body.must_equal ({"counter"=>3}.to_s)

app = [incrementor, { secrets: random_encryptor_secret }]

response = response_for(app: app, cookie: response)
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)
end

it "loads from a cookie with accept-only integrity hash for graceful key rotation" do
Expand All @@ -323,14 +323,14 @@ def decode(str); @calls << :decode; JSON.parse(str); end

app = [incrementor, { secrets: [new_secret, @secret] }]
response = response_for(app: app, cookie: response)
response.body.must_equal '{"counter"=>2}'
response.body.must_equal ({"counter"=>2}.to_s)

newer_secret = random_encryptor_secret

app = [incrementor, { secrets: [newer_secret, new_secret] }]
response = response_for(app: app, cookie: response)

response.body.must_equal '{"counter"=>3}'
response.body.must_equal ({"counter"=>3}.to_s)
end

it 'loads from a legacy hmac cookie' do
Expand All @@ -342,17 +342,17 @@ def decode(str); @calls << :decode; JSON.parse(str); end

app = [incrementor, { secrets: @secret, legacy_hmac_secret: legacy_secret }]
response = response_for(app: app, cookie: legacy_cookie)
response.body.must_equal '{"counter"=>2}'
response.body.must_equal ({"counter"=>2}.to_s)
end

it "ignores tampered session cookies" do
app = [incrementor, { secrets: @secret }]

response = response_for(app: app)
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)

response = response_for(app: app, cookie: response)
response.body.must_equal '{"counter"=>2}'
response.body.must_equal ({"counter"=>2}.to_s)

encoded_cookie = response["Set-Cookie"].split('=', 2).last.split(';').first
decoded_cookie = Base64.strict_decode64(Rack::Utils.unescape(encoded_cookie))
Expand All @@ -362,21 +362,21 @@ def decode(str); @calls << :decode; JSON.parse(str); end
})}"

response = response_for(app: app, cookie: tampered_cookie)
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)
end

it 'rejects session cookie with different purpose' do
app = [incrementor, { secrets: @secrets }]
other_app = [incrementor, { secrets: @secrets, key: 'other' }]

response = response_for(app: app)
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)

response = response_for(app: app, cookie: response)
response.body.must_equal '{"counter"=>2}'
response.body.must_equal ({"counter"=>2}.to_s)

response = response_for(app: other_app, cookie: response)
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)
end

it 'adds to RACK_ERRORS on encryptor errors' do
Expand All @@ -390,7 +390,7 @@ def decode(str); @calls << :decode; JSON.parse(str); end
err_app = [echo_rack_errors, { secrets: @secret }]

response = response_for(app: app)
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)

encoded_cookie = response["Set-Cookie"].split('=', 2).last.split(';').first
decoded_cookie = Base64.urlsafe_decode64(Rack::Utils.unescape(encoded_cookie))
Expand All @@ -412,7 +412,7 @@ def decode(str); @calls << :decode; JSON.parse(str); end

app = [incrementor, { secret: @secret, legacy_hmac_secret: legacy_secret }]
response = response_for(app: app, cookie: legacy_cookie)
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)
end

it "supports custom digest instance for legacy hmac cookie" do
Expand All @@ -427,10 +427,10 @@ def decode(str); @calls << :decode; JSON.parse(str); end
}]

response = response_for(app: app, cookie: legacy_cookie)
response.body.must_equal '{"counter"=>2}'
response.body.must_equal ({"counter"=>2}.to_s)

response = response_for(app: app, cookie: response)
response.body.must_equal '{"counter"=>3}'
response.body.must_equal ({"counter"=>3}.to_s)
end

it "can handle Rack::Lint middleware" do
Expand Down Expand Up @@ -461,11 +461,11 @@ def call(env)

it "returns the session id in the session hash" do
response = response_for(app: incrementor)
response.body.must_equal '{"counter"=>1}'
response.body.must_equal ({"counter"=>1}.to_s)

response = response_for(app: session_id, cookie: response)
response.body.must_match(/"session_id"=>/)
response.body.must_match(/"counter"=>1/)
response.body.must_match(/"session_id"\s*=>/)
response.body.must_match(/"counter"\s*=>\s*1/)
end

it "does not return a cookie if set to secure but not using ssl" do
Expand Down Expand Up @@ -590,8 +590,8 @@ def decode(str)
incrementor
], cookie: non_strict_response)

response.body.must_match %Q["value"=>"#{'A' * 256}"]
response.body.must_match '"counter"=>2'
response.body.must_match /"value"\s*=>\s*"#{'A' * 256}"/
response.body.must_match /"counter"\s*=>\s*2/
response.body.must_match(/\A{[^}]+}\z/)
end
end
2 changes: 1 addition & 1 deletion test/spec_session_encryptor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def encryptor_class

# slice 1 byte for version, 32 bytes for cipher_secret, 12 bytes for IV,
# 16 bytes for the auth tag from the start of the string
encrypted_payload = decoded_message[(1 + 32 + 12 + 16)..]
encrypted_payload = decoded_message[(1 + 32 + 12 + 16)..decoded_message.size]

(encrypted_payload.bytesize % 24).must_equal 0
end
Expand Down
38 changes: 19 additions & 19 deletions test/spec_session_pool.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,24 +51,24 @@
pool = Rack::Session::Pool.new(incrementor)
res = Rack::MockRequest.new(pool).get("/")
res["Set-Cookie"].must_match(session_match)
res.body.must_equal '{"counter"=>1}'
res.body.must_equal ({"counter"=>1}.to_s)
end

it "determines session from a cookie" do
pool = Rack::Session::Pool.new(incrementor)
req = Rack::MockRequest.new(pool)
cookie = req.get("/")["Set-Cookie"]
req.get("/", "HTTP_COOKIE" => cookie).
body.must_equal '{"counter"=>2}'
body.must_equal ({"counter"=>2}.to_s)
req.get("/", "HTTP_COOKIE" => cookie).
body.must_equal '{"counter"=>3}'
body.must_equal ({"counter"=>3}.to_s)
end

it "survives nonexistent cookies" do
pool = Rack::Session::Pool.new(incrementor)
res = Rack::MockRequest.new(pool).
get("/", "HTTP_COOKIE" => "#{session_key}=blarghfasel")
res.body.must_equal '{"counter"=>1}'
res.body.must_equal ({"counter"=>1}.to_s)
end

it "does not send the same session id if it did not change" do
Expand All @@ -77,17 +77,17 @@

res0 = req.get("/")
cookie = res0["Set-Cookie"][session_match]
res0.body.must_equal '{"counter"=>1}'
res0.body.must_equal ({"counter"=>1}.to_s)
pool.pool.size.must_equal 1

res1 = req.get("/", "HTTP_COOKIE" => cookie)
res1["Set-Cookie"].must_be_nil
res1.body.must_equal '{"counter"=>2}'
res1.body.must_equal ({"counter"=>2}.to_s)
pool.pool.size.must_equal 1

res2 = req.get("/", "HTTP_COOKIE" => cookie)
res2["Set-Cookie"].must_be_nil
res2.body.must_equal '{"counter"=>3}'
res2.body.must_equal ({"counter"=>3}.to_s)
pool.pool.size.must_equal 1
end

Expand All @@ -99,17 +99,17 @@

res1 = req.get("/")
session = (cookie = res1["Set-Cookie"])[session_match]
res1.body.must_equal '{"counter"=>1}'
res1.body.must_equal ({"counter"=>1}.to_s)
pool.pool.size.must_equal 1

res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
res2["Set-Cookie"].must_be_nil
res2.body.must_equal '{"counter"=>2}'
res2.body.must_equal ({"counter"=>2}.to_s)
pool.pool.size.must_equal 0

res3 = req.get("/", "HTTP_COOKIE" => cookie)
res3["Set-Cookie"][session_match].wont_equal session
res3.body.must_equal '{"counter"=>1}'
res3.body.must_equal ({"counter"=>1}.to_s)
pool.pool.size.must_equal 1
end

Expand All @@ -121,22 +121,22 @@

res1 = req.get("/")
session = (cookie = res1["Set-Cookie"])[session_match]
res1.body.must_equal '{"counter"=>1}'
res1.body.must_equal ({"counter"=>1}.to_s)
pool.pool.size.must_equal 1

res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
new_cookie = res2["Set-Cookie"]
new_session = new_cookie[session_match]
new_session.wont_equal session
res2.body.must_equal '{"counter"=>2}'
res2.body.must_equal ({"counter"=>2}.to_s)
pool.pool.size.must_equal 1

res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
res3.body.must_equal '{"counter"=>3}'
res3.body.must_equal ({"counter"=>3}.to_s)
pool.pool.size.must_equal 1

res4 = req.get("/", "HTTP_COOKIE" => cookie)
res4.body.must_equal '{"counter"=>1}'
res4.body.must_equal ({"counter"=>1}.to_s)
pool.pool.size.must_equal 2
end

Expand All @@ -147,7 +147,7 @@

res1 = dreq.get("/")
res1["Set-Cookie"].must_be_nil
res1.body.must_equal '{"counter"=>1}'
res1.body.must_equal ({"counter"=>1}.to_s)
pool.pool.size.must_equal 1
end

Expand All @@ -164,7 +164,7 @@

res1 = req.get("/", "HTTP_COOKIE" => cookie)
res1["Set-Cookie"].must_be_nil
res1.body.must_equal '{"counter"=>2}'
res1.body.must_equal(({"counter"=>2}.to_s))
pool.pool[session_id.private_id].wont_be_nil
end

Expand All @@ -181,7 +181,7 @@

res1 = req.get("/", "HTTP_COOKIE" => cookie)
res1["Set-Cookie"].wont_be_nil
res1.body.must_equal '{"counter"=>1}'
res1.body.must_equal ({"counter"=>1}.to_s)
end

it "drops the session in the legacy id as well" do
Expand All @@ -199,7 +199,7 @@

res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
res2["Set-Cookie"].must_be_nil
res2.body.must_equal '{"counter"=>2}'
res2.body.must_equal ({"counter"=>2}.to_s)
pool.pool[session_id.private_id].must_be_nil
pool.pool[session_id.public_id].must_be_nil
end
Expand Down Expand Up @@ -236,7 +236,7 @@
req = Rack::MockRequest.new(pool)

res = req.get('/')
res.body.must_equal '{"counter"=>1}'
res.body.must_equal ({"counter"=>1}.to_s)
cookie = res["Set-Cookie"]
sess_id = cookie[/#{pool.key}=([^,;]+)/, 1]

Expand Down

0 comments on commit 336e14b

Please sign in to comment.