module Hyperstack
::Hyperstack::Engine.routes.append do
Hyperstack.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_hyperstack_call
alias pre_hyperstack_call call
def call(env)
if Hyperstack.transport == :simple_poller && env['PATH_INFO'] && env['PATH_INFO'].include?('/hyperstack-read/')
Rails.logger.silence do
pre_hyperstack_call(env)
end
else
pre_hyperstack_call(env)
end
end
end
end
end
end if defined?(::Rails::Rack::Logger)
class HyperstackController < ::ApplicationController
protect_from_forgery except: [:console_update, :execute_remote_api]
def client_id
params[:client_id]
end
before_action do
session.delete 'hyperstack-dummy-init' unless session.id
end
def session_channel
"Hyperstack::Session-#{session.id}"
end
def regulate(channel)
unless channel == session_channel # "Hyperstack::Session-#{client_id.split('-').last}"
Hyperstack::InternalPolicy.regulate_connection(try(:acting_user), channel)
end
channel
end
def channels(user = acting_user, session_id = session.id)
Hyperstack::AutoConnect.channels(session_id, user)
end
def can_connect?(channel, user = acting_user)
Hyperstack::InternalPolicy.regulate_connection(
user,
Hyperstack::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 = regulate params[:channel].gsub('==', '::')
root_path = request.original_url.gsub(/hyperstack-subscribe.*$/, '')
Hyperstack::Connection.open(channel, client_id, root_path)
head :ok
rescue Exception
head :unauthorized
end
def read
root_path = request.original_url.gsub(/hyperstack-read.*$/, '')
data = Hyperstack::Connection.read(client_id, root_path)
render json: data
end
def pusher_auth
raise unless Hyperstack.transport == :pusher
channel = regulate params[:channel_name].gsub(/^#{Regexp.quote(Hyperstack.channel)}\-/,'').gsub('==', '::')
response = Hyperstack.pusher.authenticate(params[:channel_name], params[:socket_id])
render json: response
rescue Exception => e
head :unauthorized
end
def action_cable_auth
raise unless Hyperstack.transport == :action_cable
channel = regulate params[:channel_name].gsub(/^#{Regexp.quote(Hyperstack.channel)}\-/,'')
salt = SecureRandom.hex
authorization = Hyperstack.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(/hyperstack-connect-to-transport.*$/, '')
render json: Hyperstack::Connection.connect_to_transport(params[:channel], client_id, root_path)
rescue Exception => e
render status: :service_unavailable, json: {error: e}
end
def execute_remote
parsed_params = JSON.parse(params[:json]).symbolize_keys
render ServerOp.run_from_client(
:acting_user,
self,
parsed_params[:operation],
parsed_params[:params].merge(acting_user: acting_user)
)
end
def execute_remote_api
params.require(:params).permit!
parsed_params = params[:params].to_h.symbolize_keys
raise AccessViolation unless parsed_params[:authorization]
render ServerOp.run_from_client(:authorization, self, params[:operation], parsed_params)
end
def console_update # TODO this should just become an execute-remote-api call
raise unless Rails.env.development?
authorization = Hyperstack.authorization(params[:salt], params[:channel], params[:data][1][:broadcast_id]) #params[:data].to_json)
return head :unauthorized if authorization != params[:authorization]
Hyperstack::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? Hyperstack::HyperstackController
match 'execute_remote',
to: 'hyperstack#execute_remote', via: :post
match 'execute_remote_api',
to: 'hyperstack#execute_remote_api', via: :post
# match 'hyperstack-subscribe',
# to: 'hyperstack#subscribe', via: :get
# match 'hyperstack-read/:subscriber',
# to: 'hyperstack#read', via: :get
match 'hyperstack-subscribe/:client_id/:channel',
to: 'hyperstack#subscribe', via: :get
match 'hyperstack-read/:client_id',
to: 'hyperstack#read', via: :get
match 'hyperstack-pusher-auth',
to: 'hyperstack#pusher_auth', via: :post
match 'hyperstack-action-cable-auth/:client_id/:channel_name',
to: 'hyperstack#action_cable_auth', via: :post
match 'hyperstack-connect-to-transport/:client_id/:channel',
to: 'hyperstack#connect_to_transport', via: :get
match 'console',
to: 'hyperstack#debug_console', via: :get
match 'console_update',
to: 'hyperstack#console_update', via: :post
match 'server_up',
to: 'hyperstack#server_up', via: :get
end
end