web-console 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/README.markdown +132 -85
  3. data/lib/web_console.rb +14 -13
  4. data/lib/web_console/errors.rb +7 -0
  5. data/lib/web_console/{repl.rb → evaluator.rb} +7 -10
  6. data/lib/web_console/helper.rb +22 -0
  7. data/lib/web_console/integration.rb +8 -0
  8. data/lib/web_console/{core_ext/exception → integration}/cruby.rb +0 -0
  9. data/lib/web_console/integration/jruby.rb +111 -0
  10. data/lib/web_console/integration/rubinius.rb +66 -0
  11. data/lib/web_console/middleware.rb +117 -0
  12. data/lib/web_console/railtie.rb +61 -0
  13. data/lib/web_console/request.rb +30 -0
  14. data/lib/web_console/session.rb +65 -0
  15. data/lib/web_console/template.rb +49 -0
  16. data/lib/web_console/templates/_inner_console_markup.html +3 -0
  17. data/lib/web_console/templates/_markup.html +4 -0
  18. data/lib/web_console/templates/_prompt_box_markup.html +2 -0
  19. data/lib/web_console/templates/console.js +373 -0
  20. data/lib/web_console/templates/error_page.js +83 -0
  21. data/lib/web_console/templates/index.html +8 -0
  22. data/lib/web_console/templates/layouts/inlined_string.erb +1 -0
  23. data/lib/web_console/templates/layouts/javascript.erb +5 -0
  24. data/lib/web_console/templates/main.js +24 -0
  25. data/lib/web_console/templates/style.css +9 -0
  26. data/lib/web_console/version.rb +1 -1
  27. data/lib/web_console/whiny_request.rb +38 -0
  28. data/lib/web_console/whitelist.rb +42 -0
  29. data/test/dummy/config/environments/test.rb +0 -4
  30. data/test/dummy/log/development.log +7075 -0
  31. data/test/dummy/log/test.log +66006 -0
  32. data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  33. data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  34. data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  35. data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  36. data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  37. data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  38. data/test/support/scenarios/bad_custom_error_scenario.rb +17 -0
  39. data/test/support/scenarios/basic_nested_scenario.rb +15 -0
  40. data/test/support/scenarios/custom_error_scenario.rb +11 -0
  41. data/test/support/scenarios/eval_nested_scenario.rb +15 -0
  42. data/test/support/scenarios/flat_scenario.rb +9 -0
  43. data/test/support/scenarios/reraised_scenario.rb +21 -0
  44. data/test/test_helper.rb +50 -3
  45. data/test/web_console/evaluator_test.rb +73 -0
  46. data/test/web_console/helper_test.rb +76 -0
  47. data/test/web_console/integration_test.rb +47 -0
  48. data/test/web_console/middleware_test.rb +116 -0
  49. data/test/web_console/railtie_test.rb +99 -0
  50. data/test/web_console/request_test.rb +52 -0
  51. data/test/web_console/session_test.rb +59 -0
  52. data/test/web_console/whiny_request_test.rb +33 -0
  53. data/test/web_console/whitelist_test.rb +43 -0
  54. metadata +66 -56
  55. data/lib/action_dispatch/debug_exceptions.rb +0 -105
  56. data/lib/action_dispatch/exception_wrapper.rb +0 -38
  57. data/lib/action_dispatch/templates/rescues/_request_and_response.html.erb +0 -34
  58. data/lib/action_dispatch/templates/rescues/_request_and_response.text.erb +0 -23
  59. data/lib/action_dispatch/templates/rescues/_source.erb +0 -29
  60. data/lib/action_dispatch/templates/rescues/_trace.html.erb +0 -72
  61. data/lib/action_dispatch/templates/rescues/_trace.text.erb +0 -9
  62. data/lib/action_dispatch/templates/rescues/_web_console.html.erb +0 -420
  63. data/lib/action_dispatch/templates/rescues/diagnostics.html.erb +0 -18
  64. data/lib/action_dispatch/templates/rescues/diagnostics.text.erb +0 -9
  65. data/lib/action_dispatch/templates/rescues/layout.erb +0 -160
  66. data/lib/action_dispatch/templates/rescues/missing_template.html.erb +0 -13
  67. data/lib/action_dispatch/templates/rescues/missing_template.text.erb +0 -3
  68. data/lib/action_dispatch/templates/rescues/routing_error.html.erb +0 -34
  69. data/lib/action_dispatch/templates/rescues/routing_error.text.erb +0 -11
  70. data/lib/action_dispatch/templates/rescues/template_error.html.erb +0 -22
  71. data/lib/action_dispatch/templates/rescues/template_error.text.erb +0 -7
  72. data/lib/action_dispatch/templates/rescues/unknown_action.html.erb +0 -6
  73. data/lib/action_dispatch/templates/rescues/unknown_action.text.erb +0 -3
  74. data/lib/action_dispatch/templates/routes/_route.html.erb +0 -16
  75. data/lib/action_dispatch/templates/routes/_table.html.erb +0 -200
  76. data/lib/assets/javascripts/web-console.js +0 -1
  77. data/lib/assets/javascripts/web_console.js +0 -41
  78. data/lib/web_console/controller_helpers.rb +0 -46
  79. data/lib/web_console/core_ext/exception.rb +0 -7
  80. data/lib/web_console/core_ext/exception/jruby.rb +0 -25
  81. data/lib/web_console/core_ext/exception/rubinius.rb +0 -32
  82. data/lib/web_console/engine.rb +0 -47
  83. data/lib/web_console/repl_session.rb +0 -89
  84. data/lib/web_console/unsupported_platforms.rb +0 -28
  85. data/lib/web_console/view_helpers.rb +0 -16
  86. data/test/action_pack/exception_wrapper_test.rb +0 -26
  87. data/test/controllers/tests_controller_test.rb +0 -41
  88. data/test/web_console/core_ext/exception_test.rb +0 -46
  89. data/test/web_console/engine_test.rb +0 -108
  90. data/test/web_console/repl_session_test.rb +0 -32
  91. data/test/web_console/repl_test.rb +0 -75
@@ -1 +0,0 @@
1
- //= require ./web_console
@@ -1,41 +0,0 @@
1
- //= require term
2
-
3
- ;(function(BaseTerminal) {
4
-
5
- // Expose the main WebConsole namespace.
6
- var WebConsole = this.WebConsole = {};
7
-
8
- // Follow term.js example and expose inherits and EventEmitter.
9
- var inherits = WebConsole.inherits = BaseTerminal.inherits;
10
- var EventEmitter = WebConsole.EventEmitter = BaseTerminal.EventEmitter;
11
-
12
- var Terminal = WebConsole.Terminal = function(options) {
13
- if (typeof options === 'number') {
14
- return BaseTerminal.apply(this, arguments);
15
- }
16
-
17
- BaseTerminal.call(this, options || (options = {}));
18
-
19
- this.open();
20
-
21
- if (!(options.rows || options.cols) || !options.geometry) {
22
- this.fitScreen();
23
- }
24
- };
25
-
26
- // Make WebConsole.Terminal inherit from BaseTerminal (term.js).
27
- inherits(Terminal, BaseTerminal);
28
-
29
- Terminal.prototype.fitScreen = function() {
30
- var width = Math.floor(this.element.clientWidth / this.cols);
31
- var height = Math.floor(this.element.clientHeight / this.rows);
32
-
33
- var rows = Math.floor(window.innerHeight / height);
34
- var cols = Math.floor(this.parent.clientWidth / width);
35
-
36
- this.resize(cols, rows);
37
-
38
- return [cols, rows];
39
- };
40
-
41
- }).call(this, Terminal);
@@ -1,46 +0,0 @@
1
- module WebConsole
2
- module ControllerHelpers
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- # Flag to decide whether the console should be rendered.
7
- attr_internal :console_already_rendered
8
-
9
- # Storage of a binding the console to be rendered in.
10
- attr_internal :console_binding
11
-
12
- prepend_after_action :inject_console_into_view
13
- end
14
-
15
- # Helper for capturing a controller binding to prepare for console
16
- # rendering.
17
- def console(binding = nil)
18
- @_console_binding = binding || ::Kernel.binding.of_caller(1)
19
- end
20
-
21
- private
22
-
23
- # Attempt to inject an interactive console to a view.
24
- def inject_console_into_view
25
- return unless can_render_console?
26
-
27
- console_html = ActionView::Base.new(ActionController::Base.view_paths,
28
- console_session: REPLSession.create(binding: @_console_binding)
29
- ).render(partial: 'rescues/web_console')
30
-
31
- response.body = response.body + console_html
32
- end
33
-
34
- def can_render_console?
35
- console_binding && !console_already_rendered && html_format? && whitelisted_ip?
36
- end
37
-
38
- def html_format?
39
- content_type == Mime::HTML
40
- end
41
-
42
- def whitelisted_ip?
43
- request.remote_ip.in?(WebConsole.config.whitelisted_ips)
44
- end
45
- end
46
- end
@@ -1,7 +0,0 @@
1
- if defined? JRUBY_VERSION
2
- require 'web_console/core_ext/exception/jruby'
3
- elsif RUBY_ENGINE == 'rbx'
4
- require 'web_console/core_ext/exception/rubinius'
5
- else
6
- require 'web_console/core_ext/exception/cruby'
7
- end
@@ -1,25 +0,0 @@
1
- class Exception
2
- # The bindings in which the exception originated in.
3
- def bindings
4
- @bindings || []
5
- end
6
-
7
- # JRuby won't call Exception#set_backtrace when raising, so we can't hook in
8
- # there. Our best bet is to hook into Exception#initialize, however we have
9
- # the problem that a subclass may forget to call super in its override.
10
- def initialize_with_binding_of_caller(*args)
11
- unless Thread.current[:__web_console_exception_lock]
12
- Thread.current[:__web_console_exception_lock] = true
13
- begin
14
- @bindings = binding.callers.drop(1)
15
- ensure
16
- Thread.current[:__web_console_exception_lock] = false
17
- end
18
- end
19
-
20
- initialize_without_binding_of_caller(*args)
21
- end
22
-
23
- alias_method_chain :initialize, :binding_of_caller
24
- end
25
-
@@ -1,32 +0,0 @@
1
- class Exception
2
- # The bindings in which the exception originated in.
3
- def bindings
4
- @bindings || []
5
- end
6
-
7
- # Rubinius, as JRuby, won't call Exception#set_backtrace. This means we'll
8
- # miss custom exceptions overriding #initialize, but forgetting to call
9
- # super.
10
- def initialize_with_binding_of_caller(*args)
11
- unless Thread.current[:__web_console_exception_lock]
12
- Thread.current[:__web_console_exception_lock] = true
13
- begin
14
- @bindings = binding.callers.drop(2)
15
-
16
- # When explicitly raising an exception, we have to drop one more frame
17
- # on Rubinius. The way we do it is pretty bad as it strongly depends on
18
- # the Kerner#raise implementation details. We need to do better in the
19
- # future.
20
- if _ = @bindings.first and _.eval('local_variables') == [:exc, :msg, :ctx, :skip, :loc, :pos]
21
- @bindings.shift
22
- end
23
- ensure
24
- Thread.current[:__web_console_exception_lock] = false
25
- end
26
- end
27
-
28
- initialize_without_binding_of_caller(*args)
29
- end
30
-
31
- alias_method_chain :initialize, :binding_of_caller
32
- end
@@ -1,47 +0,0 @@
1
- require 'ipaddr'
2
- require 'rails/engine'
3
-
4
- require 'active_model'
5
- require 'sprockets/rails'
6
-
7
- module WebConsole
8
- class Engine < ::Rails::Engine
9
- config.web_console = ActiveSupport::OrderedOptions.new
10
- config.web_console.whitelisted_ips = %w( 127.0.0.1 ::1 )
11
-
12
- initializer "web_console.initialize_view_helpers" do
13
- ActiveSupport.on_load :action_view do
14
- include WebConsole::ViewHelpers
15
- end
16
-
17
- ActiveSupport.on_load :action_controller do
18
- prepend_view_path File.dirname(__FILE__) + '/../action_dispatch/templates'
19
- include WebConsole::ControllerHelpers
20
- end
21
- end
22
-
23
- initializer 'web_console.process_whitelisted_ips' do
24
- config.web_console.tap do |c|
25
- # Ensure that it is an array of IPAddr instances and it is defaulted to
26
- # 127.0.0.1 if not precent. Only unique entries are left in the end.
27
- c.whitelisted_ips = Array(c.whitelisted_ips).map { |ip|
28
- if ip.is_a?(IPAddr)
29
- ip
30
- else
31
- IPAddr.new(ip.presence || '127.0.0.1')
32
- end
33
- }.uniq
34
-
35
- # IPAddr instances can cover whole networks, so simplify the #include?
36
- # check for the most common case.
37
- def (c.whitelisted_ips).include?(ip)
38
- if ip.is_a?(IPAddr)
39
- super
40
- else
41
- any? { |net| net.include?(ip.to_s) }
42
- end
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,89 +0,0 @@
1
- module WebConsole
2
- class REPLSession
3
- include ActiveModel::Serializers::JSON
4
-
5
- INMEMORY_STORAGE = {}
6
-
7
- ATTRIBUTES = [ :id, :input, :output, :prompt, :binding, :binding_stack ].each do |attr|
8
- attr_accessor attr
9
- end
10
-
11
- class NotFound < StandardError
12
- def to_json(*)
13
- { error: message }.to_json
14
- end
15
- end
16
-
17
- class << self
18
- # Finds a session by its id.
19
- def find(id)
20
- INMEMORY_STORAGE[id] or raise NotFound, 'Session unavailable'
21
- end
22
-
23
- # Creates an already persisted console session.
24
- #
25
- # Use this method if you need to persist a session, without providing it
26
- # any input.
27
- def create(attributes = {})
28
- INMEMORY_STORAGE[(model = new(attributes)).id] = model
29
- end
30
- end
31
-
32
- def initialize(attributes = {})
33
- self.attributes = attributes
34
- generate_secure_id!
35
- populate_repl_attributes!(initial: true)
36
- end
37
-
38
- def binding=(binding)
39
- @binding = binding
40
- @repl = WebConsole::REPL.new(binding)
41
- end
42
-
43
- # Saves the model into the in-memory storage.
44
- #
45
- # Returns false if the model is not valid (e.g. its missing input).
46
- def save(attributes = {})
47
- self.attributes = attributes if attributes.present?
48
- populate_repl_attributes!
49
- store!
50
- end
51
-
52
- # Returns true if the current session is persisted in the in-memory storage.
53
- def persisted?
54
- self == INMEMORY_STORAGE[id]
55
- end
56
-
57
- protected
58
-
59
- # Returns a hash of the attributes and their values.
60
- def attributes
61
- return Hash[ATTRIBUTES.zip([nil])].except(:binding, :binding_stack)
62
- end
63
-
64
- # Sets model attributes from a hash.
65
- def attributes=(attributes)
66
- attributes.each do |attr, value|
67
- next unless ATTRIBUTES.include?(attr.to_sym)
68
- public_send(:"#{attr}=", value)
69
- end
70
- end
71
-
72
- private
73
-
74
- def generate_secure_id!
75
- self.id = SecureRandom.hex(16)
76
- end
77
-
78
- def populate_repl_attributes!(options = {})
79
- # Don't send any input on the initial population so we don't bump up
80
- # the numbers in the dynamic prompts.
81
- self.output = @repl.send_input(input) unless options[:initial]
82
- self.prompt = @repl.prompt
83
- end
84
-
85
- def store!
86
- INMEMORY_STORAGE[id] = self
87
- end
88
- end
89
- end
@@ -1,28 +0,0 @@
1
- module WebConsole
2
- # Detect unsupported platforms and try to help the user, if there is
3
- # something they can do about it.
4
- #
5
- # For example, not every JRuby mode is unsupported, we can guide the user
6
- # what to do to enable support for that platform.
7
- module UnsupportedPlatforms
8
- class << self
9
- def jruby_in_non_interpreted_mode
10
- return unless RUBY_PLATFORM =~ /java/
11
-
12
- compile_mode = JRuby.runtime.instance_config.compile_mode
13
- interpreted_mode = Java::OrgJruby::RubyInstanceConfig::CompileMode::OFF
14
-
15
- yield if compile_mode != interpreted_mode
16
- end
17
- end
18
-
19
- jruby_in_non_interpreted_mode do
20
- warn <<-END.strip_heredoc
21
- JRuby needs to run in interpreted mode for Web Console support.
22
-
23
- To turn on interpreted mode, put -J-Djruby.compile.mode=OFF in the
24
- JRUBY_OPTS environment variable.
25
- END
26
- end
27
- end
28
- end
@@ -1,16 +0,0 @@
1
- module WebConsole
2
- module ViewHelpers
3
- def console(console_binding = nil)
4
- return unless request.remote_ip.in?(WebConsole.config.whitelisted_ips)
5
-
6
- console_binding ||= binding.of_caller(1)
7
-
8
- unless controller.console_already_rendered
9
- @console_session = WebConsole::REPLSession.create(binding: console_binding)
10
-
11
- controller.console_already_rendered = true
12
- render('rescues/web_console')
13
- end
14
- end
15
- end
16
- end
@@ -1,26 +0,0 @@
1
- require 'test_helper'
2
-
3
- module ActionDispatch
4
- class ExceptionWrapperTest < ActiveSupport::TestCase
5
- class TestError < StandardError
6
- attr_reader :backtrace
7
-
8
- def initialize(*backtrace)
9
- @backtrace = backtrace
10
- end
11
- end
12
-
13
- test '#extract_sources fetches source fragments for every backtrace' do
14
- exc = TestError.new("/test/controller.rb:9 in 'index'")
15
-
16
- wrapper = ExceptionWrapper.new({}, exc)
17
- wrapper.expects(:source_fragment).with('/test/controller.rb', 9).returns('some code')
18
-
19
- assert_equal [{
20
- code: 'some code',
21
- file: '/test/controller.rb',
22
- line_number: 9
23
- }], wrapper.extract_sources
24
- end
25
- end
26
- end
@@ -1,41 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestsControllerTest < ActionController::TestCase
4
- tests TestsController
5
-
6
- setup do
7
- request.stubs(:remote_ip).returns('127.0.0.1')
8
- end
9
-
10
- test "injects a console into a view" do
11
- get :render_console_ontop_of_text
12
-
13
- assert_select "#console"
14
- end
15
-
16
- test "renders console only once" do
17
- get :renders_console_only_once
18
-
19
- assert_select "#console", 1
20
- end
21
-
22
- test "keeps the original content" do
23
- get :render_console_ontop_of_text
24
-
25
- assert_select "#greeting", "Hello World"
26
- end
27
-
28
- test "doesn't inject in non HTML views" do
29
- get :doesnt_render_console_on_non_html_requests
30
-
31
- assert_no_match %r{#console}, @response.body
32
- end
33
-
34
- test "doesn't inject on requests from non whitelisted IPs" do
35
- request.stubs(:remote_ip).returns('192.168.0.100')
36
-
37
- get :render_console_ontop_of_text
38
-
39
- assert_select "#console", 0
40
- end
41
- end
@@ -1,46 +0,0 @@
1
- require 'test_helper'
2
-
3
- module WebConsole
4
- class ExceptionTest < ActiveSupport::TestCase
5
- class TestScenarionWithNestedCalls
6
- def call
7
- raise_an_error
8
- rescue => exc
9
- exc
10
- end
11
-
12
- private
13
-
14
- def raise_an_error
15
- unused_local_variable = 42
16
- raise
17
- end
18
- end
19
-
20
- CustomError = Class.new(StandardError)
21
-
22
- test '#bindings all the bindings of where the error originated' do
23
- begin
24
- unused_local_variable = "Test"
25
- raise
26
- rescue => exc
27
- assert_equal 'Test', exc.bindings.first.eval('unused_local_variable')
28
- end
29
- end
30
-
31
- test '#bindings all the bindings of where the error originated from a custom error' do
32
- begin
33
- unused_local_variable = "Test"
34
- raise CustomError
35
- rescue => exc
36
- assert_equal 'Test', exc.bindings.first.eval('unused_local_variable')
37
- end
38
- end
39
-
40
- test '#bindings goes down the stack' do
41
- exc = TestScenarionWithNestedCalls.new.call
42
-
43
- assert_equal 42, exc.bindings.first.eval('unused_local_variable')
44
- end
45
- end
46
- end