[ARVADOS] updated: cb52a672642bdec7c6a97868a68bbb9b8daa0efb
git at public.curoverse.com
git at public.curoverse.com
Tue Apr 22 15:20:00 EDT 2014
Summary of changes:
apps/workbench/app/views/websocket/index.html.erb | 5 +-
.../api/app/controllers/application_controller.rb | 58 ---------------
services/api/app/middlewares/arvados_api_token.rb | 52 ++++++++++++++
services/api/app/middlewares/rack_socket.rb | 48 +------------
services/api/app/models/arvados_model.rb | 2 +-
services/api/config/initializers/authorization.rb | 5 ++
services/api/config/initializers/eventbus.rb | 4 +-
services/api/lib/eventbus.rb | 75 ++++++++++++++++++++
8 files changed, 141 insertions(+), 108 deletions(-)
create mode 100644 services/api/app/middlewares/arvados_api_token.rb
create mode 100644 services/api/config/initializers/authorization.rb
create mode 100644 services/api/lib/eventbus.rb
via cb52a672642bdec7c6a97868a68bbb9b8daa0efb (commit)
via d07a96a0f0c11b98ecc927f0b3e0b052f8ef99f7 (commit)
via e484a466d78c87114779b596d6ecd79f22088ee2 (commit)
from aa920f1659aa830861c196617fe664f35b5c12ef (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit cb52a672642bdec7c6a97868a68bbb9b8daa0efb
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date: Tue Apr 22 15:19:51 2014 -0400
Added permission checking to event bus so that it only report changes for
objects that the user has current read permission.
diff --git a/services/api/lib/eventbus.rb b/services/api/lib/eventbus.rb
index 30b400c..26674b7 100644
--- a/services/api/lib/eventbus.rb
+++ b/services/api/lib/eventbus.rb
@@ -2,6 +2,13 @@ require 'eventmachine'
require 'oj'
require 'faye/websocket'
+module Faye
+ class WebSocket
+ attr_accessor :user
+ attr_accessor :last_log_id
+ end
+end
+
class EventBus
include CurrentApiClient
@@ -18,9 +25,16 @@ class EventBus
return
end
+ ws.user = current_user
+
sub = @channel.subscribe do |msg|
Log.where(id: msg.to_i).each do |l|
- ws.send(l.as_api_response.to_json)
+ if rsc = ArvadosModel::resource_class_for_uuid(l.object_uuid)
+ rsc.readable_by(ws.user).where(uuid: l.object_uuid).each do
+ ws.send(l.as_api_response.to_json)
+ end
+ end
+ ws.last_log_id = msg.to_i
end
end
commit d07a96a0f0c11b98ecc927f0b3e0b052f8ef99f7
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date: Tue Apr 22 14:24:03 2014 -0400
Moves API token authentication from ApplicationController into ArvadosApiToken Rack middleware.
Rearranges rack middleware stack a bit to accomodate.
diff --git a/apps/workbench/app/views/websocket/index.html.erb b/apps/workbench/app/views/websocket/index.html.erb
index e1fca78..425ddd4 100644
--- a/apps/workbench/app/views/websocket/index.html.erb
+++ b/apps/workbench/app/views/websocket/index.html.erb
@@ -15,12 +15,13 @@
<script>
$(function() {
putStuffThere = function (content) {
- $("#PutStuffHere").append(content["message"] + "<br>");
+ $("#PutStuffHere").append(content + "<br>");
};
var dispatcher = new WebSocket('ws://localhost:3001/websocket?api_token=<%= Thread.current[:arvados_api_token] %>');
dispatcher.onmessage = function(event) {
- putStuffThere(JSON.parse(event.data));
+ //putStuffThere(JSON.parse(event.data));
+ putStuffThere(event.data);
};
sendStuff = function () {
diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index 4b13fca..033eccd 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -4,7 +4,6 @@ class ApplicationController < ActionController::Base
respond_to :json
protect_from_forgery
- around_filter :thread_with_auth_info, :except => [:render_error, :render_not_found]
before_filter :remote_ip
before_filter :require_auth_scope_all, :except => :render_not_found
@@ -330,63 +329,6 @@ class ApplicationController < ActionController::Base
end
end
- def thread_with_auth_info
- Thread.current[:request_starttime] = Time.now
- Thread.current[:api_url_base] = root_url.sub(/\/$/,'') + '/arvados/v1'
- begin
- user = nil
- api_client = nil
- api_client_auth = nil
- supplied_token =
- params[:api_token] ||
- params[:oauth_token] ||
- request.headers["Authorization"].andand.match(/OAuth2 ([a-z0-9]+)/).andand[1]
- if supplied_token
- api_client_auth = ApiClientAuthorization.
- includes(:api_client, :user).
- where('api_token=? and (expires_at is null or expires_at > CURRENT_TIMESTAMP)', supplied_token).
- first
- if api_client_auth.andand.user
- session[:user_id] = api_client_auth.user.id
- session[:api_client_uuid] = api_client_auth.api_client.andand.uuid
- session[:api_client_authorization_id] = api_client_auth.id
- user = api_client_auth.user
- api_client = api_client_auth.api_client
- else
- # Token seems valid, but points to a non-existent (deleted?) user.
- api_client_auth = nil
- end
- elsif session[:user_id]
- user = User.find(session[:user_id]) rescue nil
- api_client = ApiClient.
- where('uuid=?',session[:api_client_uuid]).
- first rescue nil
- if session[:api_client_authorization_id] then
- api_client_auth = ApiClientAuthorization.
- find session[:api_client_authorization_id]
- end
- end
- Thread.current[:api_client_ip_address] = remote_ip
- Thread.current[:api_client_authorization] = api_client_auth
- Thread.current[:api_client_uuid] = api_client.andand.uuid
- Thread.current[:api_client] = api_client
- Thread.current[:user] = user
- if api_client_auth
- api_client_auth.last_used_at = Time.now
- api_client_auth.last_used_by_ip_address = remote_ip
- api_client_auth.save validate: false
- end
- yield
- ensure
- Thread.current[:api_client_ip_address] = nil
- Thread.current[:api_client_authorization] = nil
- Thread.current[:api_client_uuid] = nil
- Thread.current[:api_client] = nil
- Thread.current[:user] = nil
- end
- end
- # /Authentication
-
def model_class
controller_name.classify.constantize
end
diff --git a/services/api/app/middlewares/arvados_api_token.rb b/services/api/app/middlewares/arvados_api_token.rb
new file mode 100644
index 0000000..fac1916
--- /dev/null
+++ b/services/api/app/middlewares/arvados_api_token.rb
@@ -0,0 +1,52 @@
+class ArvadosApiToken
+ def initialize(app = nil, options = nil)
+ @app = app if app.respond_to?(:call)
+ end
+
+ def call env
+ # first, clean up just in case
+ Thread.current[:api_client_ip_address] = nil
+ Thread.current[:api_client_authorization] = nil
+ Thread.current[:api_client_uuid] = nil
+ Thread.current[:api_client] = nil
+ Thread.current[:user] = nil
+
+ request = Rack::Request.new(env)
+ params = request.params
+ remote_ip = env["action_dispatch.remote_ip"]
+
+ Thread.current[:request_starttime] = Time.now
+ user = nil
+ api_client = nil
+ api_client_auth = nil
+ supplied_token =
+ params["api_token"] ||
+ params["oauth_token"] ||
+ env["HTTP_AUTHORIZATION"].andand.match(/OAuth2 ([a-z0-9]+)/).andand[1]
+ if supplied_token
+ api_client_auth = ApiClientAuthorization.
+ includes(:api_client, :user).
+ where('api_token=? and (expires_at is null or expires_at > CURRENT_TIMESTAMP)', supplied_token).
+ first
+ if api_client_auth.andand.user
+ user = api_client_auth.user
+ api_client = api_client_auth.api_client
+ else
+ # Token seems valid, but points to a non-existent (deleted?) user.
+ api_client_auth = nil
+ end
+ end
+ Thread.current[:api_client_ip_address] = remote_ip
+ Thread.current[:api_client_authorization] = api_client_auth
+ Thread.current[:api_client_uuid] = api_client.andand.uuid
+ Thread.current[:api_client] = api_client
+ Thread.current[:user] = user
+ if api_client_auth
+ api_client_auth.last_used_at = Time.now
+ api_client_auth.last_used_by_ip_address = remote_ip.to_s
+ api_client_auth.save validate: false
+ end
+
+ @app.call env
+ end
+end
diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index f0f846c..3a79810 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -295,7 +295,7 @@ class ArvadosModel < ActiveRecord::Base
log = Log.new(event_type: event_type).fill_object(self)
yield log
log.save!
- connection.execute "NOTIFY logs"
+ connection.execute "NOTIFY logs, '#{log.id}'"
log_start_state
end
diff --git a/services/api/config/initializers/authorization.rb b/services/api/config/initializers/authorization.rb
new file mode 100644
index 0000000..e491e40
--- /dev/null
+++ b/services/api/config/initializers/authorization.rb
@@ -0,0 +1,5 @@
+Server::Application.configure do
+ config.middleware.insert_before ActionDispatch::Static, ArvadosApiToken
+ config.middleware.delete ActionDispatch::RemoteIp
+ config.middleware.insert_before ArvadosApiToken, ActionDispatch::RemoteIp
+end
diff --git a/services/api/config/initializers/eventbus.rb b/services/api/config/initializers/eventbus.rb
index a065632..31d8fac 100644
--- a/services/api/config/initializers/eventbus.rb
+++ b/services/api/config/initializers/eventbus.rb
@@ -1,5 +1,5 @@
require 'eventbus'
Server::Application.configure do
- config.middleware.insert_before ActionDispatch::Static, RackSocket, {:handler => EventBus}
+ config.middleware.insert_after ArvadosApiToken, RackSocket, {:handler => EventBus}
end
diff --git a/services/api/lib/eventbus.rb b/services/api/lib/eventbus.rb
index ff3cd8b..30b400c 100644
--- a/services/api/lib/eventbus.rb
+++ b/services/api/lib/eventbus.rb
@@ -3,28 +3,37 @@ require 'oj'
require 'faye/websocket'
class EventBus
+ include CurrentApiClient
+
def initialize
@channel = EventMachine::Channel.new
- @bgthread = nil
+ @mtx = Mutex.new
+ @bgthread = false
end
def on_connect ws
- sub = @channel.subscribe do |msg|
- puts "sending #{msg}"
- ws.send({:message => "log"}.to_json)
- end
+ if not current_user
+ ws.send '{"error":"Not logged in"}'
+ ws.close
+ return
+ end
- ws.on :message do |event|
- puts "got #{event.data}"
- ws.send(event.data)
+ sub = @channel.subscribe do |msg|
+ Log.where(id: msg.to_i).each do |l|
+ ws.send(l.as_api_response.to_json)
end
+ end
- ws.on :close do |event|
- p [:close, event.code, event.reason]
- @channel.unsubscribe sub
- ws = nil
- end
+ ws.on :message do |event|
+ #puts "got #{event.data}"
+ end
+ ws.on :close do |event|
+ @channel.unsubscribe sub
+ ws = nil
+ end
+
+ @mtx.synchronize do
unless @bgthread
@bgthread = true
Thread.new do
@@ -35,10 +44,7 @@ class EventBus
conn.async_exec "LISTEN logs"
while true
conn.wait_for_notify do |channel, pid, payload|
- puts "Received a NOTIFY on channel #{channel}"
- puts "from PG backend #{pid}"
- puts "saying #{payload}"
- @channel.push true
+ @channel.push payload
end
end
ensure
@@ -50,6 +56,6 @@ class EventBus
end
end
end
-
+ end
end
end
commit e484a466d78c87114779b596d6ecd79f22088ee2
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date: Tue Apr 22 09:47:38 2014 -0400
Moved application-specific code out from rack_socket to lib/eventbus.rb
diff --git a/services/api/app/middlewares/rack_socket.rb b/services/api/app/middlewares/rack_socket.rb
index 779c675..f13316f 100644
--- a/services/api/app/middlewares/rack_socket.rb
+++ b/services/api/app/middlewares/rack_socket.rb
@@ -1,6 +1,5 @@
require 'rack'
require 'faye/websocket'
-require 'oj'
require 'eventmachine'
class RackSocket
@@ -38,8 +37,7 @@ class RackSocket
}
end
- @channel = EventMachine::Channel.new
- @bgthread = nil
+ @handler = @options[:handler].new
end
def call env
@@ -47,47 +45,7 @@ class RackSocket
if request.path_info == @endpoint and Faye::WebSocket.websocket?(env)
ws = Faye::WebSocket.new(env)
- sub = @channel.subscribe do |msg|
- puts "sending #{msg}"
- ws.send({:message => "log"}.to_json)
- end
-
- ws.on :message do |event|
- puts "got #{event.data}"
- ws.send(event.data)
- end
-
- ws.on :close do |event|
- p [:close, event.code, event.reason]
- @channel.unsubscribe sub
- ws = nil
- end
-
- unless @bgthread
- @bgthread = true
- Thread.new do
- # from http://stackoverflow.com/questions/16405520/postgres-listen-notify-rails
- ActiveRecord::Base.connection_pool.with_connection do |connection|
- conn = connection.instance_variable_get(:@connection)
- begin
- conn.async_exec "LISTEN logs"
- while true
- conn.wait_for_notify do |channel, pid, payload|
- puts "Received a NOTIFY on channel #{channel}"
- puts "from PG backend #{pid}"
- puts "saying #{payload}"
- @channel.push true
- end
- end
- ensure
- # Don't want the connection to still be listening once we return
- # it to the pool - could result in weird behavior for the next
- # thread to check it out.
- conn.async_exec "UNLISTEN *"
- end
- end
- end
- end
+ @handler.on_connect ws
# Return async Rack response
ws.rack_response
@@ -97,5 +55,3 @@ class RackSocket
end
end
-
-
diff --git a/services/api/config/initializers/eventbus.rb b/services/api/config/initializers/eventbus.rb
index 2350b57..a065632 100644
--- a/services/api/config/initializers/eventbus.rb
+++ b/services/api/config/initializers/eventbus.rb
@@ -1,3 +1,5 @@
+require 'eventbus'
+
Server::Application.configure do
- config.middleware.insert_before ActionDispatch::Static, RackSocket
+ config.middleware.insert_before ActionDispatch::Static, RackSocket, {:handler => EventBus}
end
diff --git a/services/api/lib/eventbus.rb b/services/api/lib/eventbus.rb
new file mode 100644
index 0000000..ff3cd8b
--- /dev/null
+++ b/services/api/lib/eventbus.rb
@@ -0,0 +1,55 @@
+require 'eventmachine'
+require 'oj'
+require 'faye/websocket'
+
+class EventBus
+ def initialize
+ @channel = EventMachine::Channel.new
+ @bgthread = nil
+ end
+
+ def on_connect ws
+ sub = @channel.subscribe do |msg|
+ puts "sending #{msg}"
+ ws.send({:message => "log"}.to_json)
+ end
+
+ ws.on :message do |event|
+ puts "got #{event.data}"
+ ws.send(event.data)
+ end
+
+ ws.on :close do |event|
+ p [:close, event.code, event.reason]
+ @channel.unsubscribe sub
+ ws = nil
+ end
+
+ unless @bgthread
+ @bgthread = true
+ Thread.new do
+ # from http://stackoverflow.com/questions/16405520/postgres-listen-notify-rails
+ ActiveRecord::Base.connection_pool.with_connection do |connection|
+ conn = connection.instance_variable_get(:@connection)
+ begin
+ conn.async_exec "LISTEN logs"
+ while true
+ conn.wait_for_notify do |channel, pid, payload|
+ puts "Received a NOTIFY on channel #{channel}"
+ puts "from PG backend #{pid}"
+ puts "saying #{payload}"
+ @channel.push true
+ end
+ end
+ ensure
+ # Don't want the connection to still be listening once we return
+ # it to the pool - could result in weird behavior for the next
+ # thread to check it out.
+ conn.async_exec "UNLISTEN *"
+ end
+ end
+ end
+ end
+
+ end
+end
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list