web-console 3.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +48 -0
- data/MIT-LICENSE +1 -1
- data/README.markdown +25 -24
- data/lib/web_console/evaluator.rb +11 -4
- data/lib/web_console/exception_mapper.rb +23 -2
- data/lib/web_console/extensions.rb +10 -23
- data/lib/web_console/injector.rb +5 -3
- data/lib/web_console/interceptor.rb +18 -0
- data/lib/web_console/middleware.rb +6 -9
- data/lib/web_console/{whitelist.rb → permissions.rb} +5 -9
- data/lib/web_console/railtie.rb +19 -4
- data/lib/web_console/request.rb +4 -20
- data/lib/web_console/session.rb +11 -9
- data/lib/web_console/source_location.rb +15 -0
- data/lib/web_console/template.rb +2 -3
- data/lib/web_console/templates/console.js.erb +29 -8
- data/lib/web_console/templates/error_page.js.erb +4 -3
- data/lib/web_console/templates/layouts/inlined_string.erb +1 -1
- data/lib/web_console/templates/layouts/javascript.erb +1 -1
- data/lib/web_console/templates/style.css.erb +182 -34
- data/lib/web_console/testing/fake_middleware.rb +0 -1
- data/lib/web_console/version.rb +1 -1
- data/lib/web_console/view.rb +1 -0
- data/lib/web_console/whiny_request.rb +4 -4
- data/lib/web_console.rb +3 -1
- metadata +19 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a491428cda19f89cf20ad5ef83558e948feecb7acb7f46b453c5644ad419131b
|
|
4
|
+
data.tar.gz: 3e3d2902466fc03684b00591b294df2c19af06db31e43f58f1f9e8de14cb731f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d949e602f1056bda92b2e7e13e030a78bd856befeb52ccd89c57c27a5341bab30830e27969f3fd9bf8e3d5e4467de381cb788cd9d5809ad6f5d662b2a00b3993
|
|
7
|
+
data.tar.gz: a17229c83c77f2fdc2b06ca4d25674391e9318490da932de015d0d8ebc59bf652ccb010577eea9d95c357fcd703ba6b5fb8f2afc8343ad79306e80834f52d77d
|
data/CHANGELOG.markdown
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
## master (unreleased)
|
|
4
4
|
|
|
5
|
+
## 4.2.0
|
|
6
|
+
|
|
7
|
+
* [#308](https://github.com/rails/web-console/pull/308) Fix web-console inline templates rendering ([@voxik])
|
|
8
|
+
* [#306](https://github.com/rails/web-console/pull/306) Support Ruby 3.0 and above ([@ruanwood])
|
|
9
|
+
|
|
10
|
+
## 4.1.0
|
|
11
|
+
|
|
12
|
+
* [#304](https://github.com/rails/web-console/pull/304) Add support for Rails 6.1 ([@stephannv])
|
|
13
|
+
* [#298](https://github.com/rails/web-console/pull/298) Prevent deprecation warnings by removing template formats ([@mikelkew])
|
|
14
|
+
* [#297](https://github.com/rails/web-console/pull/297) Use MutationObserver instead of Mutation Events ([@mikelkew])
|
|
15
|
+
* [#296](https://github.com/rails/web-console/pull/296) Add CSP nonce to injected scripts and styles ([@mikelkew])
|
|
16
|
+
|
|
17
|
+
## 4.0.4
|
|
18
|
+
|
|
19
|
+
* [fb483743](https://github.com/rails/web-console/commit/fb483743a6a2a4168cdc0b2e03f48fc393991b73) Fix a crash on webrick with Rack 2.2.3 ([@gsamokovarov])
|
|
20
|
+
|
|
21
|
+
## 4.0.3
|
|
22
|
+
|
|
23
|
+
* [#291](https://github.com/rails/web-console/pull/291) Deprecate config.web_console.whitelisted_ips ([@JuanitoFatas])
|
|
24
|
+
* [#290](https://github.com/rails/web-console/pull/290) Fix Content-Length for rack >= 2.1.0 ([@p8])
|
|
25
|
+
|
|
26
|
+
## 4.0.2
|
|
27
|
+
|
|
28
|
+
* [#285](https://github.com/rails/web-console/pull/285) Increase timeout on paste ([@celvro])
|
|
29
|
+
|
|
30
|
+
## 4.0.1
|
|
31
|
+
|
|
32
|
+
* [#279](https://github.com/rails/web-console/pull/279) Fix initial config.web_console.permissions value ([@patorash])
|
|
33
|
+
|
|
34
|
+
## 4.0.0
|
|
35
|
+
|
|
36
|
+
* [61ce65b5](https://github.com/rails/web-console/commit/61ce65b599f56809de1bd8da6590a80acbd92017) Move to config.web_console.permissions ([@gsamokovarov])
|
|
37
|
+
* [96127ac1](https://github.com/rails/web-console/commit/96127aac143e1e653fffdc4bb65e1ce0b5ff342d) Introduce Binding#console as an alternative interface ([@gsamokovarov])
|
|
38
|
+
* [d4591ca5](https://github.com/rails/web-console/commit/d4591ca5396ed15a08818f3da11134852a485b27) Introduce Rails 6 support ([@gsamokovarov])
|
|
39
|
+
* [f97d8a88](https://github.com/rails/web-console/commit/f97d8a889a38366485e5c5e8985995c19bf61d13) Introduce Ruby 2.6 support ([@gsamokovarov])
|
|
40
|
+
* [d6deacd9](https://github.com/rails/web-console/commit/d6deacd9d5fcaabf3e3051d6985b53f924f86956) Drop Rails 5 support ([@gsamokovarov])
|
|
41
|
+
* [90fda878](https://github.com/rails/web-console/commit/90fda8789d402f05647c18f8cdf8e5c3d01692dd) Drop Ruby 2.4 support ([@gsamokovarov])
|
|
42
|
+
* [#265](https://github.com/rails/web-console/pull/265) Add support for nested exceptions ([@yuki24])
|
|
43
|
+
|
|
5
44
|
## 3.7.0
|
|
6
45
|
|
|
7
46
|
* [#263](https://github.com/rails/web-console/pull/263) Show binding changes ([@causztic])
|
|
@@ -118,6 +157,8 @@ go to 3.1.0 instead.
|
|
|
118
157
|
* [#84](https://github.com/rails/web-console/pull/84) Allow Rails 5 as dependency in gemspec ([@jonatack])
|
|
119
158
|
* [#69](https://github.com/rails/web-console/pull/69) Introduce middleware for request dispatch and console rendering ([@gsamokovarov])
|
|
120
159
|
|
|
160
|
+
[@stephannv]: https://github.com/stephannv
|
|
161
|
+
[@mikelkew]: https://github.com/mikelkew
|
|
121
162
|
[@jonatack]: https://github.com/jonatack
|
|
122
163
|
[@ryandao]: https://github.com/ryandao
|
|
123
164
|
[@jeffnv]: https://github.com/jeffnv
|
|
@@ -138,3 +179,10 @@ go to 3.1.0 instead.
|
|
|
138
179
|
[@fl0l0u]: https://github.com/fl0l0u
|
|
139
180
|
[@timomeh]: https://github.com/timomeh
|
|
140
181
|
[@causztic]: https://github.com/causztic
|
|
182
|
+
[@yuki24]: https://github.com/yuki24
|
|
183
|
+
[@patorash]: https://github.com/patorash
|
|
184
|
+
[@celvro]: https://github.com/celvro
|
|
185
|
+
[@JuanitoFatas]: https://github.com/JuanitoFatas
|
|
186
|
+
[@p8]: https://github.com/p8
|
|
187
|
+
[@voxik]: https://github.com/voxik
|
|
188
|
+
[@ryanwood]: https://github.com/ryanwood
|
data/MIT-LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright 2014-2016
|
|
1
|
+
Copyright 2014-2016 Hailey Somerville, Genadi Samokovarov, Guillermo Iguaran and Ryan Dao
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
4
|
a copy of this software and associated documentation files (the
|
data/README.markdown
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<p align=right>
|
|
2
|
-
Documentation for:
|
|
2
|
+
<strong>Current version: 4.1.0</strong> | Documentation for:
|
|
3
3
|
<a href=https://github.com/rails/web-console/tree/v1.0.4>v1.0.4</a>
|
|
4
4
|
<a href=https://github.com/rails/web-console/tree/v2.2.1>v2.2.1</a>
|
|
5
|
+
<a href=https://github.com/rails/web-console/tree/v3.7.0>v3.7.0</a>
|
|
5
6
|
</p>
|
|
6
7
|
|
|
7
8
|
# Web Console [](https://travis-ci.org/rails/web-console)
|
|
@@ -16,7 +17,7 @@ _Web Console_ is a debugging tool for your Ruby on Rails applications.
|
|
|
16
17
|
|
|
17
18
|
## Installation
|
|
18
19
|
|
|
19
|
-
Add the following to your `Gemfile
|
|
20
|
+
Add the following to your `Gemfile`:
|
|
20
21
|
|
|
21
22
|
```ruby
|
|
22
23
|
group :development do
|
|
@@ -27,8 +28,8 @@ end
|
|
|
27
28
|
## Usage
|
|
28
29
|
|
|
29
30
|
The web console allows you to create an interactive Ruby session in your
|
|
30
|
-
browser. Those sessions are launched automatically in case of an error
|
|
31
|
-
|
|
31
|
+
browser. Those sessions are launched automatically in case of an error and can
|
|
32
|
+
also be launched manually in any page.
|
|
32
33
|
|
|
33
34
|
For example, calling `console` in a view will display a console in the current
|
|
34
35
|
page in the context of the view binding.
|
|
@@ -56,30 +57,30 @@ have multiple ones, `WebConsole::DoubleRenderError` will be raised.
|
|
|
56
57
|
|
|
57
58
|
## Configuration
|
|
58
59
|
|
|
59
|
-
_Web Console_ allows you to execute arbitrary code on the server,
|
|
60
|
-
|
|
60
|
+
_Web Console_ allows you to execute arbitrary code on the server. Therefore, be
|
|
61
|
+
very careful who you give access to.
|
|
61
62
|
|
|
62
|
-
### config.web_console.
|
|
63
|
+
### config.web_console.permissions
|
|
63
64
|
|
|
64
65
|
By default, only requests coming from IPv4 and IPv6 localhosts are allowed.
|
|
65
66
|
|
|
66
|
-
`config.web_console.
|
|
67
|
+
`config.web_console.permissions` lets you control which IP's have access to
|
|
67
68
|
the console.
|
|
68
69
|
|
|
69
|
-
You can
|
|
70
|
-
console with `192.168.0.100
|
|
70
|
+
You can allow single IP's or whole networks. Say you want to share your
|
|
71
|
+
console with `192.168.0.100`:
|
|
71
72
|
|
|
72
73
|
```ruby
|
|
73
74
|
class Application < Rails::Application
|
|
74
|
-
config.web_console.
|
|
75
|
+
config.web_console.permissions = '192.168.0.100'
|
|
75
76
|
end
|
|
76
77
|
```
|
|
77
78
|
|
|
78
|
-
If you want to
|
|
79
|
+
If you want to allow the whole private network:
|
|
79
80
|
|
|
80
81
|
```ruby
|
|
81
82
|
Rails.application.configure do
|
|
82
|
-
config.web_console.
|
|
83
|
+
config.web_console.permissions = '192.168.0.0/16'
|
|
83
84
|
end
|
|
84
85
|
```
|
|
85
86
|
|
|
@@ -88,8 +89,8 @@ case in 2.0.
|
|
|
88
89
|
|
|
89
90
|
### config.web_console.whiny_requests
|
|
90
91
|
|
|
91
|
-
When a console cannot be shown for a given IP address or content type,
|
|
92
|
-
messages
|
|
92
|
+
When a console cannot be shown for a given IP address or content type,
|
|
93
|
+
messages such as the following is printed in the server logs:
|
|
93
94
|
|
|
94
95
|
> Cannot render console from 192.168.1.133! Allowed networks:
|
|
95
96
|
> 127.0.0.0/127.255.255.255, ::1
|
|
@@ -104,7 +105,7 @@ end
|
|
|
104
105
|
|
|
105
106
|
### config.web_console.template_paths
|
|
106
107
|
|
|
107
|
-
If you want to style the console yourself, you can place `style.css` at a
|
|
108
|
+
If you want to style the console yourself, then you can place `style.css` at a
|
|
108
109
|
directory pointed by `config.web_console.template_paths`:
|
|
109
110
|
|
|
110
111
|
```ruby
|
|
@@ -119,8 +120,8 @@ may override.
|
|
|
119
120
|
### config.web_console.mount_point
|
|
120
121
|
|
|
121
122
|
Usually the middleware of _Web Console_ is mounted at `/__web_console`.
|
|
122
|
-
If
|
|
123
|
-
|
|
123
|
+
If there is a need to change the path, then you can specify it by
|
|
124
|
+
`config.web_console.mount_point`:
|
|
124
125
|
|
|
125
126
|
```ruby
|
|
126
127
|
Rails.application.configure do
|
|
@@ -132,7 +133,7 @@ end
|
|
|
132
133
|
|
|
133
134
|
### Where did /console go?
|
|
134
135
|
|
|
135
|
-
The remote terminal emulator was extracted in its own gem
|
|
136
|
+
The remote terminal emulator was extracted in its own gem which is no longer
|
|
136
137
|
bundled with _Web Console_.
|
|
137
138
|
|
|
138
139
|
If you miss this feature, check out [rvt].
|
|
@@ -140,11 +141,11 @@ If you miss this feature, check out [rvt].
|
|
|
140
141
|
### Why do I constantly get unavailable session errors?
|
|
141
142
|
|
|
142
143
|
All of _Web Console_ sessions are stored in memory. If you happen to run on a
|
|
143
|
-
multi-process server (like Unicorn) you may
|
|
144
|
+
multi-process server (like Unicorn), you may encounter unavailable session errors
|
|
144
145
|
while the server is still running. This is because a request may hit a
|
|
145
146
|
different worker (process) that doesn't have the desired session in memory.
|
|
146
147
|
To avoid that, if you use such servers in development, configure them so they
|
|
147
|
-
|
|
148
|
+
serve requests only out of one process.
|
|
148
149
|
|
|
149
150
|
#### Passenger
|
|
150
151
|
|
|
@@ -174,15 +175,15 @@ Make sure your configuration lives in `config/environments/development.rb`.
|
|
|
174
175
|
|
|
175
176
|
## Credits
|
|
176
177
|
|
|
177
|
-
* Shoutout to [
|
|
178
|
+
* Shoutout to [Hailey Somerville] for [better_errors].
|
|
178
179
|
* Kudos to [John Mair] for [binding_of_caller] and [debug_inspector].
|
|
179
180
|
* Thanks to [Charles Oliver Nutter] for all the _JRuby_ feedback.
|
|
180
181
|
* Hugs and kisses to all of our [contributors]!
|
|
181
182
|
|
|
182
|
-
[better_errors]: https://github.com/
|
|
183
|
+
[better_errors]: https://github.com/BetterErrors/better_errors
|
|
183
184
|
[debug_inspector]: https://github.com/banister/debug_inspector
|
|
184
185
|
[binding_of_caller]: https://github.com/banister/binding_of_caller
|
|
185
|
-
[
|
|
186
|
+
[Hailey Somerville]: https://github.com/haileys
|
|
186
187
|
[John Mair]: https://github.com/banister
|
|
187
188
|
[Charles Oliver Nutter]: https://github.com/headius
|
|
188
189
|
[templates]: https://github.com/rails/web-console/tree/master/lib/web_console/templates
|
|
@@ -8,16 +8,23 @@ module WebConsole
|
|
|
8
8
|
# return a string and will format exception output.
|
|
9
9
|
class Evaluator
|
|
10
10
|
# Cleanses exceptions raised inside #eval.
|
|
11
|
-
cattr_reader :cleaner
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
cattr_reader :cleaner, default: begin
|
|
12
|
+
cleaner = ActiveSupport::BacktraceCleaner.new
|
|
13
|
+
cleaner.add_silencer { |line| line.start_with?(File.expand_path("..", __FILE__)) }
|
|
14
|
+
cleaner
|
|
15
|
+
end
|
|
14
16
|
|
|
15
17
|
def initialize(binding = TOPLEVEL_BINDING)
|
|
16
18
|
@binding = binding
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def eval(input)
|
|
20
|
-
|
|
22
|
+
# Binding#source_location is available since Ruby 2.6.
|
|
23
|
+
if @binding.respond_to? :source_location
|
|
24
|
+
"=> #{@binding.eval(input, *@binding.source_location).inspect}\n"
|
|
25
|
+
else
|
|
26
|
+
"=> #{@binding.eval(input).inspect}\n"
|
|
27
|
+
end
|
|
21
28
|
rescue Exception => exc
|
|
22
29
|
format_exception(exc)
|
|
23
30
|
end
|
|
@@ -2,9 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
module WebConsole
|
|
4
4
|
class ExceptionMapper
|
|
5
|
+
attr_reader :exc
|
|
6
|
+
|
|
7
|
+
def self.follow(exc)
|
|
8
|
+
mappers = [new(exc)]
|
|
9
|
+
|
|
10
|
+
while cause = (cause || exc).cause
|
|
11
|
+
mappers << new(cause)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
mappers
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.find_binding(mappers, exception_object_id)
|
|
18
|
+
mappers.detect do |exception_mapper|
|
|
19
|
+
exception_mapper.exc.object_id == exception_object_id.to_i
|
|
20
|
+
end || mappers.first
|
|
21
|
+
end
|
|
22
|
+
|
|
5
23
|
def initialize(exception)
|
|
6
24
|
@backtrace = exception.backtrace
|
|
7
25
|
@bindings = exception.bindings
|
|
26
|
+
@exc = exception
|
|
8
27
|
end
|
|
9
28
|
|
|
10
29
|
def first
|
|
@@ -22,13 +41,15 @@ module WebConsole
|
|
|
22
41
|
line = line.to_i
|
|
23
42
|
|
|
24
43
|
@bindings.find do |binding|
|
|
25
|
-
|
|
44
|
+
source_location = SourceLocation.new(binding)
|
|
45
|
+
source_location.path == file && source_location.lineno == line
|
|
26
46
|
end
|
|
27
47
|
end
|
|
28
48
|
|
|
29
49
|
def guess_the_first_application_binding
|
|
30
50
|
@bindings.find do |binding|
|
|
31
|
-
|
|
51
|
+
source_location = SourceLocation.new(binding)
|
|
52
|
+
source_location.path.to_s.start_with?(Rails.root.to_s)
|
|
32
53
|
end
|
|
33
54
|
end
|
|
34
55
|
end
|
|
@@ -8,8 +8,8 @@ module Kernel
|
|
|
8
8
|
# If +binding+ isn't explicitly given it will default to the binding of the
|
|
9
9
|
# previous frame. E.g. the one that invoked +console+.
|
|
10
10
|
#
|
|
11
|
-
# Raises DoubleRenderError if a
|
|
12
|
-
# detected.
|
|
11
|
+
# Raises +DoubleRenderError+ if a more than one +console+ invocation per
|
|
12
|
+
# request is detected.
|
|
13
13
|
def console(binding = Bindex.current_bindings.second)
|
|
14
14
|
raise WebConsole::DoubleRenderError if Thread.current[:__web_console_binding]
|
|
15
15
|
|
|
@@ -22,26 +22,13 @@ module Kernel
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Thread.current[:__web_console_exception] = error
|
|
34
|
-
|
|
35
|
-
# ActionView::Template::Error bypass ExceptionWrapper original
|
|
36
|
-
# exception following. The backtrace in the view is generated from
|
|
37
|
-
# reaching out to original_exception in the view.
|
|
38
|
-
if error.is_a?(ActionView::Template::Error)
|
|
39
|
-
Thread.current[:__web_console_exception] = error.cause
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
alias_method :render_exception_without_web_console, :render_exception
|
|
45
|
-
alias_method :render_exception, :render_exception_with_web_console
|
|
25
|
+
class Binding
|
|
26
|
+
# Instructs Web Console to render a console in the current binding, without
|
|
27
|
+
# the need to unroll the stack.
|
|
28
|
+
#
|
|
29
|
+
# Raises +DoubleRenderError+ if a more than one +console+ invocation per
|
|
30
|
+
# request is detected.
|
|
31
|
+
def console
|
|
32
|
+
Kernel.console(self)
|
|
46
33
|
end
|
|
47
34
|
end
|
data/lib/web_console/injector.rb
CHANGED
|
@@ -13,9 +13,11 @@ module WebConsole
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def inject(content)
|
|
16
|
-
#
|
|
17
|
-
# the
|
|
18
|
-
@headers
|
|
16
|
+
# Set Content-Length header to the size of the current body
|
|
17
|
+
# + the extra content. Otherwise the response will be truncated.
|
|
18
|
+
if @headers["Content-Length"]
|
|
19
|
+
@headers["Content-Length"] = (@body.bytesize + content.bytesize).to_s
|
|
20
|
+
end
|
|
19
21
|
|
|
20
22
|
[
|
|
21
23
|
if position = @body.rindex("</body>")
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module WebConsole
|
|
2
|
+
module Interceptor
|
|
3
|
+
def self.call(request, exception)
|
|
4
|
+
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
|
|
5
|
+
error = ActionDispatch::ExceptionWrapper.new(backtrace_cleaner, exception).exception
|
|
6
|
+
|
|
7
|
+
# Get the original exception if ExceptionWrapper decides to follow it.
|
|
8
|
+
Thread.current[:__web_console_exception] = error
|
|
9
|
+
|
|
10
|
+
# ActionView::Template::Error bypass ExceptionWrapper original
|
|
11
|
+
# exception following. The backtrace in the view is generated from
|
|
12
|
+
# reaching out to original_exception in the view.
|
|
13
|
+
if error.is_a?(ActionView::Template::Error)
|
|
14
|
+
Thread.current[:__web_console_exception] = error.cause
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -6,11 +6,8 @@ module WebConsole
|
|
|
6
6
|
class Middleware
|
|
7
7
|
TEMPLATES_PATH = File.expand_path("../templates", __FILE__)
|
|
8
8
|
|
|
9
|
-
cattr_accessor :mount_point
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
cattr_accessor :whiny_requests
|
|
13
|
-
@@whiny_requests = true
|
|
9
|
+
cattr_accessor :mount_point, default: "/__web_console"
|
|
10
|
+
cattr_accessor :whiny_requests, default: true
|
|
14
11
|
|
|
15
12
|
def initialize(app)
|
|
16
13
|
@app = app
|
|
@@ -19,7 +16,7 @@ module WebConsole
|
|
|
19
16
|
def call(env)
|
|
20
17
|
app_exception = catch :app_exception do
|
|
21
18
|
request = create_regular_or_whiny_request(env)
|
|
22
|
-
return call_app(env) unless request.
|
|
19
|
+
return call_app(env) unless request.permitted?
|
|
23
20
|
|
|
24
21
|
if id = id_for_repl_session_update(request)
|
|
25
22
|
return update_repl_session(id, request)
|
|
@@ -27,6 +24,7 @@ module WebConsole
|
|
|
27
24
|
return change_stack_trace(id, request)
|
|
28
25
|
end
|
|
29
26
|
|
|
27
|
+
|
|
30
28
|
status, headers, body = call_app(env)
|
|
31
29
|
|
|
32
30
|
if (session = Session.from(Thread.current)) && acceptable_content_type?(headers)
|
|
@@ -54,7 +52,7 @@ module WebConsole
|
|
|
54
52
|
private
|
|
55
53
|
|
|
56
54
|
def acceptable_content_type?(headers)
|
|
57
|
-
|
|
55
|
+
headers["Content-Type"].to_s.include?("html")
|
|
58
56
|
end
|
|
59
57
|
|
|
60
58
|
def json_response(opts = {})
|
|
@@ -66,7 +64,6 @@ module WebConsole
|
|
|
66
64
|
end
|
|
67
65
|
|
|
68
66
|
def json_response_with_session(id, request, opts = {})
|
|
69
|
-
return respond_with_unacceptable_request unless request.acceptable?
|
|
70
67
|
return respond_with_unavailable_session(id) unless session = Session.find(id)
|
|
71
68
|
|
|
72
69
|
json_response(opts) { yield session }
|
|
@@ -113,7 +110,7 @@ module WebConsole
|
|
|
113
110
|
|
|
114
111
|
def change_stack_trace(id, request)
|
|
115
112
|
json_response_with_session(id, request) do |session|
|
|
116
|
-
session.switch_binding_to(request.params[:frame_id])
|
|
113
|
+
session.switch_binding_to(request.params[:frame_id], request.params[:exception_object_id])
|
|
117
114
|
|
|
118
115
|
{ ok: true }
|
|
119
116
|
end
|
|
@@ -3,20 +3,16 @@
|
|
|
3
3
|
require "ipaddr"
|
|
4
4
|
|
|
5
5
|
module WebConsole
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# networks.
|
|
10
|
-
class Whitelist
|
|
11
|
-
# IPv4 and IPv6 localhost should be always whitelisted.
|
|
12
|
-
ALWAYS_WHITELISTED_NETWORKS = %w( 127.0.0.0/8 ::1 )
|
|
6
|
+
class Permissions
|
|
7
|
+
# IPv4 and IPv6 localhost should be always allowed.
|
|
8
|
+
ALWAYS_PERMITTED_NETWORKS = %w( 127.0.0.0/8 ::1 )
|
|
13
9
|
|
|
14
10
|
def initialize(networks = nil)
|
|
15
11
|
@networks = normalize_networks(networks).map(&method(:coerce_network_to_ipaddr)).uniq
|
|
16
12
|
end
|
|
17
13
|
|
|
18
14
|
def include?(network)
|
|
19
|
-
@networks.any? { |
|
|
15
|
+
@networks.any? { |permission| permission.include?(network.to_s) }
|
|
20
16
|
rescue IPAddr::InvalidAddressError
|
|
21
17
|
false
|
|
22
18
|
end
|
|
@@ -28,7 +24,7 @@ module WebConsole
|
|
|
28
24
|
private
|
|
29
25
|
|
|
30
26
|
def normalize_networks(networks)
|
|
31
|
-
Array(networks).concat(
|
|
27
|
+
Array(networks).concat(ALWAYS_PERMITTED_NETWORKS)
|
|
32
28
|
end
|
|
33
29
|
|
|
34
30
|
def coerce_network_to_ipaddr(network)
|
data/lib/web_console/railtie.rb
CHANGED
|
@@ -5,11 +5,12 @@ require "rails/railtie"
|
|
|
5
5
|
module WebConsole
|
|
6
6
|
class Railtie < ::Rails::Railtie
|
|
7
7
|
config.web_console = ActiveSupport::OrderedOptions.new
|
|
8
|
-
config.web_console.whitelisted_ips = %w( 127.0.0.1 ::1 )
|
|
9
8
|
|
|
10
9
|
initializer "web_console.initialize" do
|
|
11
10
|
require "bindex"
|
|
12
11
|
require "web_console/extensions"
|
|
12
|
+
|
|
13
|
+
ActionDispatch::DebugExceptions.register_interceptor(Interceptor)
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
initializer "web_console.development_only" do
|
|
@@ -50,9 +51,23 @@ module WebConsole
|
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
|
|
53
|
-
initializer "web_console.
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
initializer "web_console.permissions" do
|
|
55
|
+
permissions = web_console_permissions
|
|
56
|
+
Request.permissions = Permissions.new(permissions)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def web_console_permissions
|
|
60
|
+
case
|
|
61
|
+
when config.web_console.permissions
|
|
62
|
+
config.web_console.permissions
|
|
63
|
+
when config.web_console.allowed_ips
|
|
64
|
+
config.web_console.allowed_ips
|
|
65
|
+
when config.web_console.whitelisted_ips
|
|
66
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
|
67
|
+
The config.web_console.whitelisted_ips is deprecated and will be ignored in future release of web_console.
|
|
68
|
+
Please use config.web_console.allowed_ips instead.
|
|
69
|
+
MSG
|
|
70
|
+
config.web_console.whitelisted_ips
|
|
56
71
|
end
|
|
57
72
|
end
|
|
58
73
|
|
data/lib/web_console/request.rb
CHANGED
|
@@ -1,35 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module WebConsole
|
|
4
|
-
# Web Console tailored request object.
|
|
5
4
|
class Request < ActionDispatch::Request
|
|
6
|
-
|
|
7
|
-
cattr_accessor :whitelisted_ips
|
|
8
|
-
@@whitelisted_ips = Whitelist.new
|
|
5
|
+
cattr_accessor :permissions, default: Permissions.new
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# Returns whether a request came from a whitelisted IP.
|
|
14
|
-
#
|
|
15
|
-
# For a request to hit Web Console features, it needs to come from a white
|
|
16
|
-
# listed IP.
|
|
17
|
-
def from_whitelisted_ip?
|
|
18
|
-
whitelisted_ips.include?(strict_remote_ip)
|
|
7
|
+
def permitted?
|
|
8
|
+
permissions.include?(strict_remote_ip)
|
|
19
9
|
end
|
|
20
10
|
|
|
21
|
-
# Determines the remote IP using our much stricter whitelist.
|
|
22
11
|
def strict_remote_ip
|
|
23
|
-
GetSecureIp.new(self,
|
|
12
|
+
GetSecureIp.new(self, permissions).to_s
|
|
24
13
|
rescue ActionDispatch::RemoteIp::IpSpoofAttackError
|
|
25
14
|
"[Spoofed]"
|
|
26
15
|
end
|
|
27
16
|
|
|
28
|
-
# Returns whether the request is acceptable.
|
|
29
|
-
def acceptable?
|
|
30
|
-
xhr? && accepts.any? { |mime| Mime[:web_console_v2] == mime }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
17
|
private
|
|
34
18
|
|
|
35
19
|
class GetSecureIp < ActionDispatch::RemoteIp::GetIp
|
data/lib/web_console/session.rb
CHANGED
|
@@ -11,8 +11,7 @@ module WebConsole
|
|
|
11
11
|
# error pages only, as currently, this is the only client that needs to do
|
|
12
12
|
# that.
|
|
13
13
|
class Session
|
|
14
|
-
cattr_reader :inmemory_storage
|
|
15
|
-
@@inmemory_storage = {}
|
|
14
|
+
cattr_reader :inmemory_storage, default: {}
|
|
16
15
|
|
|
17
16
|
class << self
|
|
18
17
|
# Finds a persisted session in memory by its id.
|
|
@@ -32,9 +31,9 @@ module WebConsole
|
|
|
32
31
|
# storage.
|
|
33
32
|
def from(storage)
|
|
34
33
|
if exc = storage[:__web_console_exception]
|
|
35
|
-
new(ExceptionMapper.
|
|
34
|
+
new(ExceptionMapper.follow(exc))
|
|
36
35
|
elsif binding = storage[:__web_console_binding]
|
|
37
|
-
new([binding])
|
|
36
|
+
new([[binding]])
|
|
38
37
|
end
|
|
39
38
|
end
|
|
40
39
|
end
|
|
@@ -42,10 +41,11 @@ module WebConsole
|
|
|
42
41
|
# An unique identifier for every REPL.
|
|
43
42
|
attr_reader :id
|
|
44
43
|
|
|
45
|
-
def initialize(
|
|
44
|
+
def initialize(exception_mappers)
|
|
46
45
|
@id = SecureRandom.hex(16)
|
|
47
|
-
|
|
48
|
-
@
|
|
46
|
+
|
|
47
|
+
@exception_mappers = exception_mappers
|
|
48
|
+
@evaluator = Evaluator.new(@current_binding = exception_mappers.first.first)
|
|
49
49
|
|
|
50
50
|
store_into_memory
|
|
51
51
|
end
|
|
@@ -60,8 +60,10 @@ module WebConsole
|
|
|
60
60
|
# Switches the current binding to the one at specified +index+.
|
|
61
61
|
#
|
|
62
62
|
# Returns nothing.
|
|
63
|
-
def switch_binding_to(index)
|
|
64
|
-
|
|
63
|
+
def switch_binding_to(index, exception_object_id)
|
|
64
|
+
bindings = ExceptionMapper.find_binding(@exception_mappers, exception_object_id)
|
|
65
|
+
|
|
66
|
+
@evaluator = Evaluator.new(@current_binding = bindings[index.to_i])
|
|
65
67
|
end
|
|
66
68
|
|
|
67
69
|
# Returns context of the current binding
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class SourceLocation
|
|
4
|
+
def initialize(binding)
|
|
5
|
+
@binding = binding
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
if RUBY_VERSION >= "2.6"
|
|
9
|
+
def path() @binding.source_location.first end
|
|
10
|
+
def lineno() @binding.source_location.last end
|
|
11
|
+
else
|
|
12
|
+
def path() @binding.eval("__FILE__") end
|
|
13
|
+
def lineno() @binding.eval("__LINE__") end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/web_console/template.rb
CHANGED
|
@@ -7,8 +7,7 @@ module WebConsole
|
|
|
7
7
|
# Rails error pages.
|
|
8
8
|
class Template
|
|
9
9
|
# Lets you customize the default templates folder location.
|
|
10
|
-
cattr_accessor :template_paths
|
|
11
|
-
@@template_paths = [ File.expand_path("../templates", __FILE__) ]
|
|
10
|
+
cattr_accessor :template_paths, default: [ File.expand_path("../templates", __FILE__) ]
|
|
12
11
|
|
|
13
12
|
def initialize(env, session)
|
|
14
13
|
@env = env
|
|
@@ -18,7 +17,7 @@ module WebConsole
|
|
|
18
17
|
|
|
19
18
|
# Render a template (inferred from +template_paths+) as a plain string.
|
|
20
19
|
def render(template)
|
|
21
|
-
view = View.
|
|
20
|
+
view = View.with_empty_template_cache.with_view_paths(template_paths, instance_values)
|
|
22
21
|
view.render(template: template, layout: false)
|
|
23
22
|
end
|
|
24
23
|
end
|
|
@@ -251,12 +251,14 @@ Autocomplete.prototype.removeView = function() {
|
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
// HTML strings for dynamic elements.
|
|
254
|
-
var consoleInnerHtml = <%= render_inlined_string '_inner_console_markup
|
|
255
|
-
var promptBoxHtml = <%= render_inlined_string '_prompt_box_markup
|
|
254
|
+
var consoleInnerHtml = <%= render_inlined_string '_inner_console_markup' %>;
|
|
255
|
+
var promptBoxHtml = <%= render_inlined_string '_prompt_box_markup' %>;
|
|
256
256
|
// CSS
|
|
257
|
-
var consoleStyleCss = <%= render_inlined_string 'style
|
|
257
|
+
var consoleStyleCss = <%= render_inlined_string 'style' %>;
|
|
258
258
|
// Insert a style element with the unique ID
|
|
259
259
|
var styleElementId = 'sr02459pvbvrmhco';
|
|
260
|
+
// Nonce to use for CSP
|
|
261
|
+
var styleElementNonce = '<%= @nonce %>';
|
|
260
262
|
|
|
261
263
|
// REPLConsole Constructor
|
|
262
264
|
function REPLConsole(config) {
|
|
@@ -380,8 +382,13 @@ REPLConsole.prototype.install = function(container) {
|
|
|
380
382
|
var clientHeightStart = consoleOuter.clientHeight;
|
|
381
383
|
|
|
382
384
|
var doDrag = function(e) {
|
|
383
|
-
|
|
385
|
+
var height = startHeight + startY - e.clientY;
|
|
384
386
|
consoleOuter.scrollTop = scrollTopStart + (clientHeightStart - consoleOuter.clientHeight);
|
|
387
|
+
if (height > document.documentElement.clientHeight) {
|
|
388
|
+
container.style.height = document.documentElement.clientHeight;
|
|
389
|
+
} else {
|
|
390
|
+
container.style.height = height + 'px';
|
|
391
|
+
}
|
|
385
392
|
shiftConsoleActions();
|
|
386
393
|
};
|
|
387
394
|
|
|
@@ -411,6 +418,14 @@ REPLConsole.prototype.install = function(container) {
|
|
|
411
418
|
}
|
|
412
419
|
}
|
|
413
420
|
|
|
421
|
+
var observer = new MutationObserver(function(mutationsList) {
|
|
422
|
+
for (let mutation of mutationsList) {
|
|
423
|
+
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
|
|
424
|
+
shiftConsoleActions();
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
414
429
|
// Initialize
|
|
415
430
|
this.container = container;
|
|
416
431
|
this.outer = consoleOuter;
|
|
@@ -422,7 +437,7 @@ REPLConsole.prototype.install = function(container) {
|
|
|
422
437
|
|
|
423
438
|
findChild(container, 'resizer').addEventListener('mousedown', resizeContainer);
|
|
424
439
|
findChild(consoleActions, 'close-button').addEventListener('click', closeContainer);
|
|
425
|
-
|
|
440
|
+
observer.observe(consoleOuter, { childList: true, subtree: true });
|
|
426
441
|
|
|
427
442
|
REPLConsole.currentSession = this;
|
|
428
443
|
};
|
|
@@ -436,6 +451,9 @@ REPLConsole.prototype.insertCss = function() {
|
|
|
436
451
|
style.type = 'text/css';
|
|
437
452
|
style.innerHTML = consoleStyleCss;
|
|
438
453
|
style.id = styleElementId;
|
|
454
|
+
if (styleElementNonce.length > 0) {
|
|
455
|
+
style.nonce = styleElementNonce;
|
|
456
|
+
}
|
|
439
457
|
document.getElementsByTagName('head')[0].appendChild(style);
|
|
440
458
|
};
|
|
441
459
|
|
|
@@ -755,7 +773,7 @@ REPLConsole.prototype.onKeyDown = function(ev) {
|
|
|
755
773
|
_this.addToInput(_this.clipboard.value);
|
|
756
774
|
_this.clipboard.value = "";
|
|
757
775
|
_this.clipboard.blur();
|
|
758
|
-
},
|
|
776
|
+
}, 100);
|
|
759
777
|
}
|
|
760
778
|
}
|
|
761
779
|
|
|
@@ -871,10 +889,14 @@ REPLConsole.prototype.scrollToBottom = function() {
|
|
|
871
889
|
};
|
|
872
890
|
|
|
873
891
|
// Change the binding of the console.
|
|
874
|
-
REPLConsole.prototype.switchBindingTo = function(frameId, callback) {
|
|
892
|
+
REPLConsole.prototype.switchBindingTo = function(frameId, exceptionObjectId, callback) {
|
|
875
893
|
var url = this.getSessionUrl('trace');
|
|
876
894
|
var params = "frame_id=" + encodeURIComponent(frameId);
|
|
877
895
|
|
|
896
|
+
if (exceptionObjectId) {
|
|
897
|
+
params = params + "&exception_object_id=" + encodeURIComponent(exceptionObjectId);
|
|
898
|
+
}
|
|
899
|
+
|
|
878
900
|
var _this = this;
|
|
879
901
|
postRequest(url, params, function() {
|
|
880
902
|
var text = "Context has changed to: " + callback();
|
|
@@ -915,7 +937,6 @@ REPLConsole.request = function request(method, url, params, callback) {
|
|
|
915
937
|
xhr.open(method, url, true);
|
|
916
938
|
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
|
917
939
|
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
|
918
|
-
xhr.setRequestHeader("Accept", "<%= Mime[:web_console_v2] %>");
|
|
919
940
|
xhr.send(params);
|
|
920
941
|
|
|
921
942
|
xhr.onreadystatechange = function() {
|
|
@@ -8,9 +8,10 @@ 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
|
+
changeBinding(frameId, exceptionObjectId, function() {
|
|
14
15
|
// Rails already handles toggling the select class
|
|
15
16
|
selectedFrame = target;
|
|
16
17
|
return target.innerHTML;
|
|
@@ -22,8 +23,8 @@ for (var i = 0; i < traceFrames.length; i++) {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
// Change the binding of the current session and prompt the user.
|
|
25
|
-
function changeBinding(frameId, callback) {
|
|
26
|
-
REPLConsole.currentSession.switchBindingTo(frameId, callback);
|
|
26
|
+
function changeBinding(frameId, exceptionObjectId, callback) {
|
|
27
|
+
REPLConsole.currentSession.switchBindingTo(frameId, exceptionObjectId, callback);
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
function changeSourceExtract(frameId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
`<%= j yield %>`
|
|
@@ -1,34 +1,182 @@
|
|
|
1
|
-
.console .pos-absolute {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
.console .
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
.console .
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
.console .
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
.console .
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
.console .
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
.console .
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
.console
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
+
}
|
data/lib/web_console/version.rb
CHANGED
data/lib/web_console/view.rb
CHANGED
|
@@ -22,6 +22,7 @@ module WebConsole
|
|
|
22
22
|
# leaking globals, unless you explicitly want to.
|
|
23
23
|
def render_javascript(template)
|
|
24
24
|
assign(template: template)
|
|
25
|
+
assign(nonce: @env["action_dispatch.content_security_policy_nonce"])
|
|
25
26
|
render(template: template, layout: "layouts/javascript")
|
|
26
27
|
end
|
|
27
28
|
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
module WebConsole
|
|
4
4
|
# Noisy wrapper around +Request+.
|
|
5
5
|
#
|
|
6
|
-
# If any calls to +
|
|
6
|
+
# If any calls to +permitted?+ and +acceptable_content_type?+
|
|
7
7
|
# return false, an info log message will be displayed in users' logs.
|
|
8
8
|
class WhinyRequest < SimpleDelegator
|
|
9
|
-
def
|
|
10
|
-
whine_unless request.
|
|
9
|
+
def permitted?
|
|
10
|
+
whine_unless request.permitted? do
|
|
11
11
|
"Cannot render console from #{request.strict_remote_ip}! " \
|
|
12
|
-
"Allowed networks: #{request.
|
|
12
|
+
"Allowed networks: #{request.permissions}"
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
data/lib/web_console.rb
CHANGED
|
@@ -11,12 +11,14 @@ module WebConsole
|
|
|
11
11
|
autoload :ExceptionMapper
|
|
12
12
|
autoload :Session
|
|
13
13
|
autoload :Injector
|
|
14
|
+
autoload :Interceptor
|
|
14
15
|
autoload :Request
|
|
15
16
|
autoload :WhinyRequest
|
|
16
|
-
autoload :
|
|
17
|
+
autoload :Permissions
|
|
17
18
|
autoload :Template
|
|
18
19
|
autoload :Middleware
|
|
19
20
|
autoload :Context
|
|
21
|
+
autoload :SourceLocation
|
|
20
22
|
|
|
21
23
|
autoload_at "web_console/errors" do
|
|
22
24
|
autoload :Error
|
metadata
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: web-console
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 4.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- Hailey Somerville
|
|
8
8
|
- Genadi Samokovarov
|
|
9
9
|
- Guillermo Iguaran
|
|
10
10
|
- Ryan Dao
|
|
11
|
-
autorequire:
|
|
11
|
+
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date:
|
|
14
|
+
date: 2021-11-17 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: railties
|
|
@@ -19,42 +19,42 @@ dependencies:
|
|
|
19
19
|
requirements:
|
|
20
20
|
- - ">="
|
|
21
21
|
- !ruby/object:Gem::Version
|
|
22
|
-
version:
|
|
22
|
+
version: 6.0.0
|
|
23
23
|
type: :runtime
|
|
24
24
|
prerelease: false
|
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
26
|
requirements:
|
|
27
27
|
- - ">="
|
|
28
28
|
- !ruby/object:Gem::Version
|
|
29
|
-
version:
|
|
29
|
+
version: 6.0.0
|
|
30
30
|
- !ruby/object:Gem::Dependency
|
|
31
31
|
name: activemodel
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
|
33
33
|
requirements:
|
|
34
34
|
- - ">="
|
|
35
35
|
- !ruby/object:Gem::Version
|
|
36
|
-
version:
|
|
36
|
+
version: 6.0.0
|
|
37
37
|
type: :runtime
|
|
38
38
|
prerelease: false
|
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
40
|
requirements:
|
|
41
41
|
- - ">="
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
|
-
version:
|
|
43
|
+
version: 6.0.0
|
|
44
44
|
- !ruby/object:Gem::Dependency
|
|
45
45
|
name: actionview
|
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
|
47
47
|
requirements:
|
|
48
48
|
- - ">="
|
|
49
49
|
- !ruby/object:Gem::Version
|
|
50
|
-
version:
|
|
50
|
+
version: 6.0.0
|
|
51
51
|
type: :runtime
|
|
52
52
|
prerelease: false
|
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
|
54
54
|
requirements:
|
|
55
55
|
- - ">="
|
|
56
56
|
- !ruby/object:Gem::Version
|
|
57
|
-
version:
|
|
57
|
+
version: 6.0.0
|
|
58
58
|
- !ruby/object:Gem::Dependency
|
|
59
59
|
name: bindex
|
|
60
60
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -69,9 +69,9 @@ dependencies:
|
|
|
69
69
|
- - ">="
|
|
70
70
|
- !ruby/object:Gem::Version
|
|
71
71
|
version: 0.4.0
|
|
72
|
-
description:
|
|
72
|
+
description:
|
|
73
73
|
email:
|
|
74
|
-
-
|
|
74
|
+
- hailey@hailey.lol
|
|
75
75
|
- gsamokovarov@gmail.com
|
|
76
76
|
- guilleiguaran@gmail.com
|
|
77
77
|
- daoduyducduong@gmail.com
|
|
@@ -91,11 +91,14 @@ files:
|
|
|
91
91
|
- lib/web_console/exception_mapper.rb
|
|
92
92
|
- lib/web_console/extensions.rb
|
|
93
93
|
- lib/web_console/injector.rb
|
|
94
|
+
- lib/web_console/interceptor.rb
|
|
94
95
|
- lib/web_console/locales/en.yml
|
|
95
96
|
- lib/web_console/middleware.rb
|
|
97
|
+
- lib/web_console/permissions.rb
|
|
96
98
|
- lib/web_console/railtie.rb
|
|
97
99
|
- lib/web_console/request.rb
|
|
98
100
|
- lib/web_console/session.rb
|
|
101
|
+
- lib/web_console/source_location.rb
|
|
99
102
|
- lib/web_console/tasks/extensions.rake
|
|
100
103
|
- lib/web_console/tasks/templates.rake
|
|
101
104
|
- lib/web_console/template.rb
|
|
@@ -116,12 +119,11 @@ files:
|
|
|
116
119
|
- lib/web_console/version.rb
|
|
117
120
|
- lib/web_console/view.rb
|
|
118
121
|
- lib/web_console/whiny_request.rb
|
|
119
|
-
- lib/web_console/whitelist.rb
|
|
120
122
|
homepage: https://github.com/rails/web-console
|
|
121
123
|
licenses:
|
|
122
124
|
- MIT
|
|
123
125
|
metadata: {}
|
|
124
|
-
post_install_message:
|
|
126
|
+
post_install_message:
|
|
125
127
|
rdoc_options: []
|
|
126
128
|
require_paths:
|
|
127
129
|
- lib
|
|
@@ -129,16 +131,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
129
131
|
requirements:
|
|
130
132
|
- - ">="
|
|
131
133
|
- !ruby/object:Gem::Version
|
|
132
|
-
version: 2.
|
|
134
|
+
version: '2.5'
|
|
133
135
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
136
|
requirements:
|
|
135
137
|
- - ">="
|
|
136
138
|
- !ruby/object:Gem::Version
|
|
137
139
|
version: '0'
|
|
138
140
|
requirements: []
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
signing_key:
|
|
141
|
+
rubygems_version: 3.1.6
|
|
142
|
+
signing_key:
|
|
142
143
|
specification_version: 4
|
|
143
144
|
summary: A debugging tool for your Ruby on Rails applications.
|
|
144
145
|
test_files: []
|