module Hyperloop ::Hyperloop::Engine.routes.append do Hyperloop.initialize_policies module ::WebConsole class Middleware private def acceptable_content_type?(headers) Mime::Type.parse(headers['Content-Type'] || '').first == Mime[:html] end end end if defined? ::WebConsole::Middleware module ::Rails module Rack class Logger < ActiveSupport::LogSubscriber unless method_defined? :pre_hyperloop_call alias pre_hyperloop_call call def call(env) if !Hyperloop.opts[:noisy] && env['HTTP_X_HYPERLOOP_SILENT_REQUEST'] Rails.logger.silence do pre_hyperloop_call(env) end else pre_hyperloop_call(env) end end end end end end if defined?(::Rails::Rack::Logger) class HyperloopController < ::ApplicationController protect_from_forgery except: [:console_update, :execute_remote_api] def client_id params[:client_id] end before_action do session.delete 'hyperloop-dummy-init' unless session.id end def channels(user = acting_user, session_id = session.id) Hyperloop::AutoConnect.channels(session_id, user) end def can_connect?(channel, user = acting_user) Hyperloop::InternalPolicy.regulate_connection( user, Hyperloop::InternalPolicy.channel_to_string(channel) ) true rescue nil end def view_permitted?(model, attr, user = acting_user) !!model.check_permission_with_acting_user(user, :view_permitted?, attr) rescue nil end def viewable_attributes(model, user = acting_user) model.attributes.select { |attr| view_permitted?(model, attr, user) } end [:create, :update, :destroy].each do |op| define_method "#{op}_permitted?" do |model, user = acting_user| begin !!model.check_permission_with_acting_user(user, "#{op}_permitted?".to_sym) rescue nil end end end def debug_console if Rails.env.development? render inline: "\n".html_safe # "
additional helper methods: channels, can_connect? "\ # "viewable_attributes, view_permitted?, create_permitted?, "\ # "update_permitted? and destroy_permitted?
\n".html_safe console else head :unauthorized end end def subscribe channel = params[:channel].gsub('==', '::') Hyperloop::InternalPolicy.regulate_connection(try(:acting_user), channel) root_path = request.original_url.gsub(/hyperloop-subscribe.*$/, '') Hyperloop::Connection.open(channel, client_id, root_path) head :ok rescue Exception head :unauthorized end def read root_path = request.original_url.gsub(/hyperloop-read.*$/, '') data = Hyperloop::Connection.read(client_id, root_path) render json: data end def pusher_auth channel = params[:channel_name].gsub(/^#{Regexp.quote(Hyperloop.channel)}\-/,'').gsub('==', '::') Hyperloop::InternalPolicy.regulate_connection(acting_user, channel) response = Hyperloop.pusher.authenticate(params[:channel_name], params[:socket_id]) render json: response rescue Exception => e head :unauthorized end def action_cable_auth channel = params[:channel_name].gsub(/^#{Regexp.quote(Hyperloop.channel)}\-/,'') Hyperloop::InternalPolicy.regulate_connection(acting_user, channel) salt = SecureRandom.hex authorization = Hyperloop.authorization(salt, channel, client_id) render json: {authorization: authorization, salt: salt} rescue Exception head :unauthorized end def connect_to_transport root_path = request.original_url.gsub(/hyperloop-connect-to-transport.*$/, '') render json: Hyperloop::Connection.connect_to_transport(params[:channel], client_id, root_path) end def execute_remote parsed_params = JSON.parse(params[:json]).symbolize_keys render ServerOp.run_from_client( :acting_user, parsed_params[:operation], parsed_params[:params].merge(acting_user: acting_user)) end def execute_remote_api parsed_params = params[:params].symbolize_keys raise AccessViolation unless parsed_params[:authorization] render ServerOp.run_from_client(:authorization, params[:operation], parsed_params) end def console_update # TODO this should just become an execute-remote-api call authorization = Hyperloop.authorization(params[:salt], params[:channel], params[:data][1][:broadcast_id]) #params[:data].to_json) return head :unauthorized if authorization != params[:authorization] Hyperloop::Connection.send_to_channel(params[:channel], params[:data]) head :no_content rescue head :unauthorized end def server_up head :no_content end end unless defined? Hyperloop::HyperloopController match 'execute_remote', to: 'hyperloop#execute_remote', via: :post match 'execute_remote_api', to: 'hyperloop#execute_remote_api', via: :post # match 'hyperloop-subscribe', # to: 'hyperloop#subscribe', via: :get # match 'hyperloop-read/:subscriber', # to: 'hyperloop#read', via: :get match 'hyperloop-subscribe/:client_id/:channel', to: 'hyperloop#subscribe', via: :get match 'hyperloop-read/:client_id', to: 'hyperloop#read', via: :get match 'hyperloop-pusher-auth', to: 'hyperloop#pusher_auth', via: :post match 'hyperloop-action-cable-auth/:client_id/:channel_name', to: 'hyperloop#action_cable_auth', via: :post match 'hyperloop-connect-to-transport/:client_id/:channel', to: 'hyperloop#connect_to_transport', via: :get match 'console', to: 'hyperloop#debug_console', via: :get match 'console_update', to: 'hyperloop#console_update', via: :post match 'server_up', to: 'hyperloop#server_up', via: :get end end