web-console 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of web-console might be problematic. Click here for more details.

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