web-console 2.3.0 → 4.2.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 (46) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.markdown +133 -1
  3. data/MIT-LICENSE +1 -1
  4. data/README.markdown +48 -86
  5. data/Rakefile +14 -12
  6. data/lib/web-console.rb +3 -1
  7. data/lib/web_console/context.rb +45 -0
  8. data/lib/web_console/errors.rb +2 -0
  9. data/lib/web_console/evaluator.rb +14 -5
  10. data/lib/web_console/exception_mapper.rb +56 -0
  11. data/lib/web_console/extensions.rb +28 -17
  12. data/lib/web_console/injector.rb +32 -0
  13. data/lib/web_console/interceptor.rb +18 -0
  14. data/lib/web_console/locales/en.yml +1 -1
  15. data/lib/web_console/middleware.rb +31 -31
  16. data/lib/web_console/permissions.rb +42 -0
  17. data/lib/web_console/railtie.rb +38 -24
  18. data/lib/web_console/request.rb +8 -20
  19. data/lib/web_console/session.rb +32 -18
  20. data/lib/web_console/source_location.rb +15 -0
  21. data/lib/web_console/tasks/extensions.rake +15 -13
  22. data/lib/web_console/tasks/templates.rake +56 -0
  23. data/lib/web_console/template.rb +4 -3
  24. data/lib/web_console/templates/console.js.erb +497 -37
  25. data/lib/web_console/templates/error_page.js.erb +7 -8
  26. data/lib/web_console/templates/index.html.erb +4 -0
  27. data/lib/web_console/templates/layouts/inlined_string.erb +1 -1
  28. data/lib/web_console/templates/layouts/javascript.erb +1 -1
  29. data/lib/web_console/templates/regular_page.js.erb +24 -0
  30. data/lib/web_console/templates/style.css.erb +182 -27
  31. data/lib/web_console/testing/erb_precompiler.rb +5 -3
  32. data/lib/web_console/testing/fake_middleware.rb +7 -10
  33. data/lib/web_console/testing/helper.rb +3 -1
  34. data/lib/web_console/version.rb +3 -1
  35. data/lib/web_console/view.rb +24 -3
  36. data/lib/web_console/whiny_request.rb +8 -6
  37. data/lib/web_console.rb +28 -20
  38. metadata +28 -63
  39. data/lib/web_console/helper.rb +0 -22
  40. data/lib/web_console/integration/cruby.rb +0 -40
  41. data/lib/web_console/integration/jruby.rb +0 -111
  42. data/lib/web_console/integration/rubinius.rb +0 -67
  43. data/lib/web_console/integration.rb +0 -8
  44. data/lib/web_console/response.rb +0 -23
  45. data/lib/web_console/tasks/test_templates.rake +0 -50
  46. data/lib/web_console/whitelist.rb +0 -42
@@ -8,15 +8,13 @@ for (var i = 0; i < traceFrames.length; i++) {
8
8
  e.preventDefault();
9
9
  var target = e.target;
10
10
  var frameId = target.dataset.frameId;
11
+ var exceptionObjectId = target.dataset.exceptionObjectId;
11
12
 
12
13
  // Change the binding of the console.
13
- changeBinding(frameId, function() {
14
- if (selectedFrame) {
15
- selectedFrame.className = selectedFrame.className.replace("selected", "");
16
- }
17
-
18
- target.className += " selected";
14
+ changeBinding(frameId, exceptionObjectId, function() {
15
+ // Rails already handles toggling the select class
19
16
  selectedFrame = target;
17
+ return target.innerHTML;
20
18
  });
21
19
 
22
20
  // Change the extracted source code
@@ -24,8 +22,9 @@ for (var i = 0; i < traceFrames.length; i++) {
24
22
  });
25
23
  }
26
24
 
27
- function changeBinding(frameId, callback) {
28
- REPLConsole.currentSession.switchBindingTo(frameId, callback);
25
+ // Change the binding of the current session and prompt the user.
26
+ function changeBinding(frameId, exceptionObjectId, callback) {
27
+ REPLConsole.currentSession.switchBindingTo(frameId, exceptionObjectId, callback);
29
28
  }
30
29
 
31
30
  function changeSourceExtract(frameId) {
@@ -6,3 +6,7 @@
6
6
  <% only_on_error_page do %>
7
7
  <%= render_javascript 'error_page' %>
8
8
  <% end %>
9
+
10
+ <% only_on_regular_page do %>
11
+ <%= render_javascript 'regular_page' %>
12
+ <% end %>
@@ -1 +1 @@
1
- "<%= j yield %>"
1
+ `<%= j yield %>`
@@ -1,4 +1,4 @@
1
- <script type="text/javascript">
1
+ <script type="text/javascript" data-template="<%= @template %>" nonce="<%= @nonce %>">
2
2
  (function() {
3
3
  <%= yield %>
4
4
  }).call(this);
@@ -0,0 +1,24 @@
1
+ // Push the error page body upwards the size of the console.
2
+ document.addEventListener('DOMContentLoaded', function() {
3
+ var consoleElement = document.getElementById('console');
4
+ var resizerElement = consoleElement.getElementsByClassName('resizer')[0];
5
+ var bodyElement = document.body;
6
+
7
+ function setBodyElementBottomMargin(pixels) {
8
+ bodyElement.style.marginBottom = pixels + 'px';
9
+ }
10
+
11
+ var currentConsoleElementHeight = consoleElement.offsetHeight;
12
+ setBodyElementBottomMargin(currentConsoleElementHeight);
13
+
14
+ resizerElement.addEventListener('mousedown', function(event) {
15
+ function recordConsoleElementHeight(event) {
16
+ resizerElement.removeEventListener('mouseup', recordConsoleElementHeight);
17
+
18
+ var currentConsoleElementHeight = consoleElement.offsetHeight;
19
+ setBodyElementBottomMargin(currentConsoleElementHeight);
20
+ }
21
+
22
+ resizerElement.addEventListener('mouseup', recordConsoleElementHeight);
23
+ });
24
+ });
@@ -1,27 +1,182 @@
1
- .console .pos-absolute { position: absolute; }
2
- .console .pos-fixed { position: fixed; }
3
- .console .pos-right { right: 0; }
4
- .console .border-box { box-sizing: border-box; }
5
- .console .layer { width: 100%; height: 100%; }
6
- .console .layer.console-outer { z-index: 1; }
7
- .console .layer.resizer { z-index: 2; }
8
- .console { position: fixed; left: 0; bottom: 0; width: 100%; height: 148px; padding: 0; margin: 0; background: none repeat scroll 0% 0% #333; z-index: 9999; }
9
- .console .console-outer { overflow: auto; padding-top: 4px; }
10
- .console .console-inner { font-family: monospace; font-size: 11px; width: 100%; height: 100%; overflow: none; background: #333; }
11
- .console .console-prompt-box { color: #FFF; }
12
- .console .console-message { color: #1AD027; margin: 0; border: 0; white-space: pre-wrap; background-color: #333; padding: 0; }
13
- .console .console-message.error-message { color: #fc9; }
14
- .console .console-focus .console-cursor { background: #FEFEFE; color: #333; font-weight: bold; }
15
- .console .resizer { background: #333; width: 100%; height: 4px; cursor: ns-resize; }
16
- .console .console-actions { padding-right: 3px; }
17
- .console .console-actions .button { float: left; }
18
- .console .button { cursor: pointer; border-radius: 1px; font-family: monospace; font-size: 13px; width: 14px; height: 14px; line-height: 14px; text-align: center; color: #ccc; }
19
- .console .button:hover { background: #666; color: #fff; }
20
- .console .button.close-button:hover { background: #966; }
21
- .console .clipboard { height: 0px; padding: 0px; margin: 0px; width: 0px; margin-left: -1000px; }
22
- .console .console-prompt-label { display: inline; color: #FFF; background: none repeat scroll 0% 0% #333; border: 0; padding: 0; }
23
- .console .console-prompt-display { display: inline; color: #FFF; background: none repeat scroll 0% 0% #333; border: 0; padding: 0; }
24
- .console.full-screen { height: 100%; }
25
- .console.full-screen .console-outer { padding-top: 3px; }
26
- .console.full-screen .resizer { display: none; }
27
- .console.full-screen .close-button { display: none; }
1
+ .console .pos-absolute {
2
+ position: absolute;
3
+ }
4
+
5
+ .console .pos-fixed {
6
+ position: fixed;
7
+ }
8
+
9
+ .console .pos-right {
10
+ right: 0;
11
+ }
12
+
13
+ .console .border-box {
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ .console .layer {
18
+ width: 100%;
19
+ height: 100%;
20
+ }
21
+
22
+ .console .layer.console-outer {
23
+ z-index: 1;
24
+ }
25
+
26
+ .console .layer.resizer {
27
+ z-index: 2;
28
+ }
29
+
30
+ .console {
31
+ position: fixed;
32
+ left: 0;
33
+ bottom: 0;
34
+ width: 100%;
35
+ height: 148px;
36
+ padding: 0;
37
+ margin: 0;
38
+ background: none repeat scroll 0% 0% #333;
39
+ z-index: 9999;
40
+ }
41
+
42
+ .console .console-outer {
43
+ overflow: auto;
44
+ padding-top: 4px;
45
+ }
46
+
47
+ .console .console-inner {
48
+ font-family: monospace;
49
+ font-size: 11px;
50
+ width: 100%;
51
+ height: 100%;
52
+ overflow: unset;
53
+ background: #333;
54
+ }
55
+
56
+ .console .console-prompt-box {
57
+ color: #fff;
58
+ }
59
+
60
+ .console .console-message {
61
+ color: #1ad027;
62
+ margin: 0;
63
+ border: 0;
64
+ white-space: pre-wrap;
65
+ background-color: #333;
66
+ padding: 0;
67
+ }
68
+
69
+ .console .console-message.error-message {
70
+ color: #fc9;
71
+ }
72
+
73
+ .console .console-message.notification-message {
74
+ color: #99f;
75
+ }
76
+
77
+ .console .console-message.auto-complete {
78
+ word-break: break-all;
79
+ }
80
+
81
+ .console .console-message.auto-complete .keyword {
82
+ margin-right: 11px;
83
+ }
84
+
85
+ .console .console-message.auto-complete .keyword.selected {
86
+ background: #fff;
87
+ color: #000;
88
+ }
89
+
90
+ .console .console-message.auto-complete .hidden {
91
+ display: none;
92
+ }
93
+
94
+ .console .console-message.auto-complete .trimmed {
95
+ display: none;
96
+ }
97
+
98
+ .console .console-hint {
99
+ color: #096;
100
+ }
101
+
102
+ .console .console-focus .console-cursor {
103
+ background: #fefefe;
104
+ color: #333;
105
+ font-weight: bold;
106
+ }
107
+
108
+ .console .resizer {
109
+ background: #333;
110
+ width: 100%;
111
+ height: 4px;
112
+ cursor: ns-resize;
113
+ }
114
+
115
+ .console .console-actions {
116
+ padding-right: 3px;
117
+ }
118
+
119
+ .console .console-actions .button {
120
+ float: left;
121
+ }
122
+
123
+ .console .button {
124
+ cursor: pointer;
125
+ border-radius: 1px;
126
+ font-family: monospace;
127
+ font-size: 13px;
128
+ width: 14px;
129
+ height: 14px;
130
+ line-height: 14px;
131
+ text-align: center;
132
+ color: #ccc;
133
+ }
134
+
135
+ .console .button:hover {
136
+ background: #666;
137
+ color: #fff;
138
+ }
139
+
140
+ .console .button.close-button:hover {
141
+ background: #966;
142
+ }
143
+
144
+ .console .clipboard {
145
+ height: 0px;
146
+ padding: 0px;
147
+ margin: 0px;
148
+ width: 0px;
149
+ margin-left: -1000px;
150
+ }
151
+
152
+ .console .console-prompt-label {
153
+ display: inline;
154
+ color: #fff;
155
+ background: none repeat scroll 0% 0% #333;
156
+ border: 0;
157
+ padding: 0;
158
+ }
159
+
160
+ .console .console-prompt-display {
161
+ display: inline;
162
+ color: #fff;
163
+ background: none repeat scroll 0% 0% #333;
164
+ border: 0;
165
+ padding: 0;
166
+ }
167
+
168
+ .console.full-screen {
169
+ height: 100%;
170
+ }
171
+
172
+ .console.full-screen .console-outer {
173
+ padding-top: 3px;
174
+ }
175
+
176
+ .console.full-screen .resizer {
177
+ display: none;
178
+ }
179
+
180
+ .console.full-screen .close-button {
181
+ display: none;
182
+ }
@@ -1,5 +1,7 @@
1
- require 'web_console/testing/helper'
2
- require 'web_console/testing/fake_middleware'
1
+ # frozen_string_literal: true
2
+
3
+ require "web_console/testing/helper"
4
+ require "web_console/testing/fake_middleware"
3
5
 
4
6
  module WebConsole
5
7
  module Testing
@@ -8,7 +10,7 @@ module WebConsole
8
10
  def initialize(path)
9
11
  @erb = ERB.new(File.read(path))
10
12
  @view = FakeMiddleware.new(
11
- view_path: Helper.gem_root.join('lib/web_console/templates'),
13
+ view_path: Helper.gem_root.join("lib/web_console/templates"),
12
14
  ).view
13
15
  end
14
16
 
@@ -1,16 +1,13 @@
1
- require 'action_view'
2
- require 'action_dispatch'
3
- require 'active_support/core_ext/string/access'
4
- require 'json'
5
- require 'web_console/whitelist'
6
- require 'web_console/request'
7
- require 'web_console/view'
8
- require 'web_console/testing/helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "action_view"
4
+ require "web_console"
5
+ require "web_console/testing/helper"
9
6
 
10
7
  module WebConsole
11
8
  module Testing
12
9
  class FakeMiddleware
13
- I18n.load_path.concat(Dir[Helper.gem_root.join('lib/web_console/locales/*.yml')])
10
+ I18n.load_path.concat(Dir[Helper.gem_root.join("lib/web_console/locales/*.yml")])
14
11
 
15
12
  DEFAULT_HEADERS = { "Content-Type" => "application/javascript" }
16
13
 
@@ -25,7 +22,7 @@ module WebConsole
25
22
  end
26
23
 
27
24
  def view
28
- @view ||= View.new(@view_path)
25
+ @view = View.new(@view_path)
29
26
  end
30
27
 
31
28
  private
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebConsole
2
4
  module Testing
3
5
  module Helper
4
6
  def self.gem_root
5
- Pathname(File.expand_path('../../../../', __FILE__))
7
+ Pathname(File.expand_path("../../../../", __FILE__))
6
8
  end
7
9
  end
8
10
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebConsole
2
- VERSION = '2.3.0'
4
+ VERSION = "4.2.0"
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebConsole
2
4
  class View < ActionView::Base
3
5
  # Execute a block only on error pages.
@@ -5,7 +7,12 @@ module WebConsole
5
7
  # The error pages are special, because they are the only pages that
6
8
  # currently require multiple bindings. We get those from exceptions.
7
9
  def only_on_error_page(*args)
8
- yield if @env['web_console.exception'].present?
10
+ yield if Thread.current[:__web_console_exception].present?
11
+ end
12
+
13
+ # Execute a block only on regular, non-error, pages.
14
+ def only_on_regular_page(*args)
15
+ yield if Thread.current[:__web_console_binding].present?
9
16
  end
10
17
 
11
18
  # Render JavaScript inside a script tag and a closure.
@@ -14,7 +21,9 @@ module WebConsole
14
21
  # script tag and enclosed in a closure, so you don't have to worry for
15
22
  # leaking globals, unless you explicitly want to.
16
23
  def render_javascript(template)
17
- render(template: template, layout: 'layouts/javascript')
24
+ assign(template: template)
25
+ assign(nonce: @env["action_dispatch.content_security_policy_nonce"])
26
+ render(template: template, layout: "layouts/javascript")
18
27
  end
19
28
 
20
29
  # Render inlined string to be used inside of JavaScript code.
@@ -22,7 +31,19 @@ module WebConsole
22
31
  # The inlined string is returned as an actual JavaScript string. You
23
32
  # don't need to wrap the result yourself.
24
33
  def render_inlined_string(template)
25
- render(template: template, layout: 'layouts/inlined_string')
34
+ render(template: template, layout: "layouts/inlined_string")
35
+ end
36
+
37
+ # Custom ActionView::Base#render wrapper which silences all the log
38
+ # printings.
39
+ #
40
+ # Helps to keep the Rails logs clean during errors.
41
+ def render(*)
42
+ if (logger = WebConsole.logger) && logger.respond_to?(:silence)
43
+ WebConsole.logger.silence { super }
44
+ else
45
+ super
46
+ end
26
47
  end
27
48
 
28
49
  # Override method for ActionView::Helpers::TranslationHelper#t.
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebConsole
2
4
  # Noisy wrapper around +Request+.
3
5
  #
4
- # If any calls to +from_whitelisted_ip?+ and +acceptable_content_type?+
6
+ # If any calls to +permitted?+ and +acceptable_content_type?+
5
7
  # return false, an info log message will be displayed in users' logs.
6
8
  class WhinyRequest < SimpleDelegator
7
- def from_whitelited_ip?
8
- whine_unless request.from_whitelited_ip? do
9
- "Cannot render console from #{request.remote_ip}! " \
10
- "Allowed networks: #{request.whitelisted_ips}"
9
+ def permitted?
10
+ whine_unless request.permitted? do
11
+ "Cannot render console from #{request.strict_remote_ip}! " \
12
+ "Allowed networks: #{request.permissions}"
11
13
  end
12
14
  end
13
15
 
@@ -21,7 +23,7 @@ module WebConsole
21
23
  end
22
24
 
23
25
  def logger
24
- env['action_dispatch.logger'] || WebConsole.logger
26
+ env["action_dispatch.logger"] || WebConsole.logger
25
27
  end
26
28
 
27
29
  def request
data/lib/web_console.rb CHANGED
@@ -1,25 +1,33 @@
1
- require 'binding_of_caller'
1
+ # frozen_string_literal: true
2
2
 
3
- require 'active_support/lazy_load_hooks'
4
- require 'active_support/logger'
5
-
6
- require 'web_console/integration'
7
- require 'web_console/railtie'
8
- require 'web_console/errors'
9
- require 'web_console/helper'
10
- require 'web_console/evaluator'
11
- require 'web_console/session'
12
- require 'web_console/template'
13
- require 'web_console/middleware'
14
- require 'web_console/whitelist'
15
- require 'web_console/request'
16
- require 'web_console/response'
17
- require 'web_console/view'
18
- require 'web_console/whiny_request'
3
+ require "active_support/dependencies/autoload"
4
+ require "active_support/logger"
19
5
 
20
6
  module WebConsole
21
- mattr_accessor :logger
22
- @@logger = ActiveSupport::Logger.new($stderr)
7
+ extend ActiveSupport::Autoload
8
+
9
+ autoload :View
10
+ autoload :Evaluator
11
+ autoload :ExceptionMapper
12
+ autoload :Session
13
+ autoload :Injector
14
+ autoload :Interceptor
15
+ autoload :Request
16
+ autoload :WhinyRequest
17
+ autoload :Permissions
18
+ autoload :Template
19
+ autoload :Middleware
20
+ autoload :Context
21
+ autoload :SourceLocation
23
22
 
24
- ActiveSupport.run_load_hooks(:web_console, self)
23
+ autoload_at "web_console/errors" do
24
+ autoload :Error
25
+ autoload :DoubleRenderError
26
+ end
27
+
28
+ def self.logger
29
+ Rails.logger || (@logger ||= ActiveSupport::Logger.new($stderr))
30
+ end
25
31
  end
32
+
33
+ require "web_console/railtie"