Skip to content

Commit

Permalink
Add ability to set cookies and login users from Tasks.
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanstout committed Aug 29, 2015
1 parent 6c47780 commit 9c5c434
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 11 deletions.
8 changes: 8 additions & 0 deletions lib/volt/controllers/login_as_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Volt
module LoginAsHelper
def login_as(user)
# Assign the user_id cookie to the signature for the user id
cookies._user_id = Volt.user_login_signature(user)
end
end
end
9 changes: 8 additions & 1 deletion lib/volt/page/tasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,14 @@ def received_message(name, promise_id, *args)

# When a request is sent to the backend, it can attach a callback,
# this is called from the backend to pass to the callback.
def response(promise_id, result, error)
def response(promise_id, result, error, cookies)
# Set the cookies
if cookies
cookies.each do |key, value|
@volt_app.cookies.set(key, value)
end
end

promise = @promises.delete(promise_id)

if promise
Expand Down
15 changes: 9 additions & 6 deletions lib/volt/tasks/dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ def initialize(volt_app)
@worker_pool = Concurrent::ImmediateExecutor.new
else
@worker_pool = Concurrent::ThreadPoolExecutor.new(
min_threads: Volt.config.min_worker_threads,
max_threads: Volt.config.max_worker_threads
)
min_threads: Volt.config.min_worker_threads,
max_threads: Volt.config.max_worker_threads
)
end

@worker_timeout = Volt.config.worker_timeout || 60
Expand Down Expand Up @@ -102,6 +102,7 @@ def dispatch_in_thread(channel, message)
klass = Object.send(:const_get, class_name)

promise = Promise.new
cookies = nil

start_time = Time.now.to_f

Expand All @@ -116,7 +117,9 @@ def dispatch_in_thread(channel, message)
Timeout.timeout(klass.__timeout || @worker_timeout) do
Thread.current['meta'] = meta_data
begin
result = klass.new(@volt_app, channel, self).send(method_name, *args)
klass_inst = klass.new(@volt_app, channel, self)
result = klass_inst.send(method_name, *args)
cookies = klass_inst.fetch_cookies
ensure
Thread.current['meta'] = nil
end
Expand All @@ -143,7 +146,7 @@ def dispatch_in_thread(channel, message)

# Run the promise and pass the return value/error back to the client
promise.then do |result|
reply = EJSON.stringify(['response', callback_id, result, nil])
reply = EJSON.stringify(['response', callback_id, result, nil, cookies])
channel.send_string_message(reply)

finish.call
Expand All @@ -152,7 +155,7 @@ def dispatch_in_thread(channel, message)
# Convert the error into a string so it can be serialized.
error_str = "#{error.class.to_s}: #{error.to_s}"

channel.send_message('response', callback_id, nil, error_str)
channel.send_message('response', callback_id, nil, error_str, cookies)
end

end
Expand Down
11 changes: 11 additions & 0 deletions lib/volt/tasks/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ def timeout(value)
self.__timeout = value
end

def cookies
@cookies ||= Model.new
end

# Get the cookies that got set
def fetch_cookies
if @cookies
@cookies.to_h.reject {|k,v| k == :id }
end
end

# On the backend, we proxy all class methods like we would
# on the front-end. This returns a promise, even if the
# original code did not.
Expand Down
2 changes: 2 additions & 0 deletions spec/integration/cookies_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@

expect(page).to_not have_content('two: two')
end

it 'should set a cookie from a task'
end
8 changes: 4 additions & 4 deletions spec/tasks/dispatcher_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def post(*args)
channel = double('channel')

# Tasks handle their own conversion to EJSON
msg = Volt::EJSON.stringify(['response', 0, 'yes it works', nil])
msg = Volt::EJSON.stringify(['response', 0, 'yes it works', nil, nil])
expect(channel).to receive(:send_string_message).with(msg)

dispatcher.dispatch(channel, [0, 'TestTask', :allowed_method, {}, ' it', ' works'])
Expand All @@ -39,23 +39,23 @@ def post(*args)
it 'should not allow eval' do
channel = double('channel')

expect(channel).to receive(:send_message).with('response', 0, nil, "RuntimeError: unsafe method: eval")
expect(channel).to receive(:send_message).with('response', 0, nil, "RuntimeError: unsafe method: eval", nil)

dispatcher.dispatch(channel, [0, 'TestTask', :eval, '5 + 10'])
end

it 'should not allow instance_eval' do
channel = double('channel')

expect(channel).to receive(:send_message).with('response', 0, nil, 'RuntimeError: unsafe method: instance_eval')
expect(channel).to receive(:send_message).with('response', 0, nil, 'RuntimeError: unsafe method: instance_eval', nil)

dispatcher.dispatch(channel, [0, 'TestTask', :instance_eval, '5 + 10'])
end

it 'should not allow #methods' do
channel = double('channel')

expect(channel).to receive(:send_message).with('response', 0, nil, 'RuntimeError: unsafe method: methods')
expect(channel).to receive(:send_message).with('response', 0, nil, 'RuntimeError: unsafe method: methods', nil)

dispatcher.dispatch(channel, [0, 'TestTask', :methods])
end
Expand Down

0 comments on commit 9c5c434

Please sign in to comment.