Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion lib/lotus/action/params.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ class Params
# @since 0.1.0
ROUTER_PARAMS = 'router.params'.freeze

# CSRF params key
#
# This key is shared with <tt>lotusrb</tt> and <tt>lotus-helpers</tt>
#
# @since x.x.x
# @api private
CSRF_TOKEN = '_csrf_token'.freeze

# Set of params that are never filtered
#
# @since x.x.x
# @api private
DEFAULT_PARAMS = Hash[CSRF_TOKEN => true].freeze

# Separator for #get
#
# @since 0.4.0
Expand Down Expand Up @@ -201,6 +215,18 @@ def to_h
end
alias_method :to_hash, :to_h

# Assign CSRF Token.
# This method is here for compatibility with <tt>Lotus::Validations</tt>.
#
# NOTE: When we will not support indifferent access anymore, we can probably
# remove this method.
#
# @since x.x.x
# @api private
def _csrf_token=(value)
@attributes.set(CSRF_TOKEN, value)
end

private
# @since 0.3.1
# @api private
Expand Down Expand Up @@ -236,12 +262,20 @@ def _params
def _whitelisted_params
{}.tap do |result|
_raw.to_h.each do |k, v|
next unless self.class.defined_attributes.include?(k.to_s)
next unless assign_attribute?(k)

result[k] = v
end
end
end

# Override <tt>Lotus::Validations</tt> method
#
# @since x.x.x
# @api private
def assign_attribute?(key)
DEFAULT_PARAMS[key.to_s] || super
end
end
end
end
10 changes: 9 additions & 1 deletion lib/lotus/action/rack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,15 @@ def send_file(path)
#
# @since 0.3.2
def head?
@_env[REQUEST_METHOD] == HEAD
request_method == HEAD
end

# NOTE: <tt>Lotus::Action::CSRFProtection</tt> (<tt>lotusrb</tt> gem) depends on this.
#
# @api private
# @since x.x.x
def request_method
@_env[REQUEST_METHOD]
end
end
end
Expand Down
10 changes: 10 additions & 0 deletions lib/lotus/action/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ module Session
# @api private
ERRORS_KEY = :__errors

# Add session to default exposures
#
# @since x.x.x
# @api private
def self.included(action)
action.class_eval do
expose :session
end
end

protected

# Gets the session from the request and expose it as an Hash.
Expand Down
26 changes: 20 additions & 6 deletions test/action/params_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
end

it 'raw gets all params' do
@action.call({id: 1, unknown: 2})
@action.params.raw.get(:id).must_equal 1
@action.params.raw.get(:unknown).must_equal 2
@action.call({id: '1', unknown: '2', _csrf_token: '3'})

@action.params.raw.get(:id).must_equal '1'
@action.params.raw.get(:unknown).must_equal '2'
@action.params.raw.get(:_csrf_token).must_equal '3'
end
end

Expand All @@ -35,9 +37,11 @@
end

it 'raw gets all params' do
@action.call({id: 1, unknown: 2})
@action.params.raw.get(:id).must_equal 1
@action.params.raw.get(:unknown).must_equal 2
@action.call({id: '1', unknown: '2', _csrf_token: '3'})

@action.params.raw.get(:id).must_equal '1'
@action.params.raw.get(:unknown).must_equal '2'
@action.params.raw.get(:_csrf_token).must_equal '3'
end
end
end
Expand Down Expand Up @@ -100,13 +104,23 @@
_, _, body = @action.call({id: 23, unknown: 4})
body.must_equal [%({"id"=>23})]
end

it "doesn't filter _csrf_token" do
_, _, body = @action.call(_csrf_token: 'abc')
body.must_equal [%({"_csrf_token"=>"abc"})]
end
end

describe "in a Rack context" do
it 'returns only the listed params' do
response = Rack::MockRequest.new(@action).request('PATCH', "?id=23", params: { x: { foo: 'bar' } })
response.body.must_match %({"id"=>"23"})
end

it "doesn't filter _csrf_token" do
response = Rack::MockRequest.new(@action).request('PATCH', "?id=23", params: { _csrf_token: 'def', x: { foo: 'bar' } })
response.body.must_match %("_csrf_token"=>"def")
end
end

describe "with Lotus::Router" do
Expand Down
8 changes: 8 additions & 0 deletions test/fixtures.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1207,3 +1207,11 @@ def call(env)
end
end
end

class MethodInspectionAction
include Lotus::Action

def call(params)
self.body = request_method
end
end
16 changes: 16 additions & 0 deletions test/rack_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'test_helper'

describe Lotus::Action::Rack do
before do
@action = MethodInspectionAction.new
end

['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'TRACE', 'OPTIONS'].each do |verb|
it "returns current request method (#{ verb })" do
env = Rack::MockRequest.env_for('/', method: verb)
_, _, body = @action.call(env)

body.must_equal [verb]
end
end
end
11 changes: 9 additions & 2 deletions test/session_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,21 @@
action = SessionAction.new
action.call({'rack.session' => session = { 'user_id' => '23' }})

action.send(:session).must_equal(session)
action.__send__(:session).must_equal(session)
end

it 'returns empty hash when it is missing' do
action = SessionAction.new
action.call({})

action.send(:session).must_equal({})
action.__send__(:session).must_equal({})
end

it 'exposes session' do
action = SessionAction.new
action.call({'rack.session' => session = { 'foo' => 'bar' }})

action.exposures[:session].must_equal(session)
end
end
end