web-console 2.0.0.beta3 → 2.0.0.beta4
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/README.markdown +16 -31
- data/app/assets/javascripts/web_console/console_sessions.js +16 -6
- data/app/controllers/web_console/console_sessions_controller.rb +8 -4
- data/app/models/web_console/console_session.rb +13 -0
- data/app/views/web_console/console_sessions/index.html.erb +3 -1
- data/lib/action_dispatch/debug_exceptions.rb +4 -8
- data/lib/action_dispatch/exception_wrapper.rb +1 -1
- data/lib/action_dispatch/templates/rescues/_web_console.html.erb +9 -8
- data/lib/action_dispatch/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/templates/routes/_table.html.erb +200 -0
- data/lib/web_console.rb +2 -1
- data/lib/web_console/controller_helpers.rb +44 -0
- data/lib/web_console/core_ext/exception.rb +59 -0
- data/lib/web_console/engine.rb +2 -1
- data/lib/web_console/repl_session.rb +4 -7
- data/lib/web_console/slave.rb +11 -3
- data/lib/web_console/version.rb +1 -1
- data/lib/web_console/view_helpers.rb +2 -5
- data/test/controllers/web_console/console_sessions_controller_test.rb +12 -7
- data/test/dummy/app/controllers/controller_helper_test_controller.rb +7 -0
- data/test/dummy/app/views/controller_helper_test/index.html.erb +1 -0
- data/test/dummy/config/routes.rb +1 -0
- data/test/dummy/log/test.log +257 -8122
- data/test/dummy/tmp/cache/assets/test/sprockets/{cb0065359d3b5b296f71d673f4b276e9 → 0c9b99b1b975b36a5b686845ae729db3} +0 -0
- data/test/dummy/tmp/cache/assets/{development/sprockets/8aa4c7aabff23c8089d41e9e54193483 → test/sprockets/12e9f58adcf819cf65fd68b6859a438f} +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/1fd6abead3df36a4e4a2cb042a551b39 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/33b5eb81b5aaaa1e6dd5dcb6517792b4 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/{d1f6e06bc2f112c4ec3a4c3f68351878 → 3e460b2e021085f88b5597b38d194932} +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/{55b7b76605fdffe31d737d4ac1f1ef7b → 52f04b2ea6e461f4661b6d0be393fa94} +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/{e6d6b8bde546349764be7b44ffcf5807 → 688c344c2919f882338f06c5daaea209} +0 -0
- data/test/dummy/tmp/cache/assets/{development/sprockets/d982412def520c434e2240eae6d29cf2 → test/sprockets/7f079298e19bbef40a5d6a37dc03033a} +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/{7a50a9e605754e99783de95715b976b0 → 91aa709f89e465f58056fabe5f75eef4} +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/{6ad7acc9a22fe2a67ec24a1fc866c20e → 95f4e4e5217aec9f71b2c1a65a9a9231} +0 -0
- data/test/dummy/tmp/cache/assets/{development/sprockets/5ac98782fe3dfd0a766f75ce1801f0a0 → test/sprockets/9c41be9b6625756fbb6d05b7665dd911} +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/a95f64d41fcf8244b8f5b84a55f07822 +0 -0
- data/test/dummy/tmp/cache/assets/{development/sprockets/6ad7acc9a22fe2a67ec24a1fc866c20e → test/sprockets/c5e6bf1efd5929bee63e28ad7c9f6f83} +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d863259e9eeca657a1624135cfe24446 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/e1d2fc4601b6423ec8a42415ee05dd14 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/e82616536a759c2e87d703adc77d65da +0 -0
- data/test/test_helper.rb +52 -0
- data/test/web_console/controller_helpers_test.rb +48 -0
- data/test/web_console/core_ext/exception_test.rb +34 -0
- data/test/web_console/engine_test.rb +9 -0
- data/test/web_console/repl_session_test.rb +4 -4
- data/test/web_console/slave_test.rb +1 -0
- metadata +46 -151
- data/lib/web_console/exception_extension.rb +0 -21
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/log/development.log +0 -61814
- data/test/dummy/tmp/cache/assets/development/sprockets/038461854af2e8bccdb29768efd4768f +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/0ec396634a5f6808b026257fd107c355 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/127a54171eea8d294e4673599861787d +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/17c571144b4e44da39bddb2d2c412414 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/1cb77d8cf661ccbc9de08f347c89b9f1 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/204edd12a29660722d4e0d8de9bd6652 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/2b96b037f3dfeccfe27113eb95b06ea1 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/2c853768baf811357d81d41bdfd05dcf +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/314d48e543146f617c4d3439a4d8d40d +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/34f21019a876722b8c24a6da4f0ef50b +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/36341e42f23669574fa1027d0958ff3e +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/44117154e909436e7eeaf10cdb18d2b4 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/496864a905d53afd8e176f29500f96a8 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/55b7b76605fdffe31d737d4ac1f1ef7b +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/6088d6f344b38303cc8028057d69e0f9 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/676dcf9b2d01b9dc7bd3183d8da88463 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/680381170dc160e358fc28076ea6886c +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/6bdb0d0c602e0e1bc304dc697e2cc6de +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/6dc8d7aa69668fce85683aaad6615432 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/6e4d5b32cc444226f6597198994ccd5e +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/74db0ca5cb8c8c347c9131a3ff516748 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/7999e525c88173c1beb785f002effc1d +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/7a50a9e605754e99783de95715b976b0 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/806b0e33a2fe8e1245534345fa27c30a +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/90396626cba6cbec37e32038e6c54e76 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/976b28910aa72c90a3b30c6e940f51df +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/99e1bd7cbc437505bc8f07bc528c721c +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/aaccf2c9ae2add0863c9a49e0042a097 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/ae4677d24a79d9411f2fced5011d5807 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/b2401118729720034b6f3eda0b4c5025 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/c649837df826fc310cb80f1adafd6b8d +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cac185d59612fae451a12df3fc21bb51 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cb0065359d3b5b296f71d673f4b276e9 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cee8c6b09c33d2b276753e959712724e +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d1f6e06bc2f112c4ec3a4c3f68351878 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d20d83fd7ffa378b1b2b901786d640f3 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d38c7c3aa1e72b55769ccb3607641ef4 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d6b85d8b0b5c569388b89e56e9f6fed7 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/df048a8b0897b9c04acdf59c8f95b18f +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/df600f50f002512c95d93bcfbab891ed +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/e6d6b8bde546349764be7b44ffcf5807 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/eb25265794d2f7afd1684779d84efdac +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/ee8826b12b7d9bfd717df950b58f82ab +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/ef9824789c6ed3483590e0564a12e1d1 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/fc7201c6cbef32453aa4175c520c8eae +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/17c571144b4e44da39bddb2d2c412414 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/36341e42f23669574fa1027d0958ff3e +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/5ac98782fe3dfd0a766f75ce1801f0a0 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/680381170dc160e358fc28076ea6886c +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/6e4d5b32cc444226f6597198994ccd5e +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/8aa4c7aabff23c8089d41e9e54193483 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/b2401118729720034b6f3eda0b4c5025 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d6b85d8b0b5c569388b89e56e9f6fed7 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d982412def520c434e2240eae6d29cf2 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/df048a8b0897b9c04acdf59c8f95b18f +0 -0
- data/test/web_console/exception_extention_test.rb +0 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fc8e319e9b1f84cf82daa49aad866ae6c93c615a
|
|
4
|
+
data.tar.gz: 60bc79a8546eee3b05d9566c1a146267575fd2b6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a2b3ec02cc16ec9ac3ec0ea28ac408e481a31db218dccdd9da149f543052051312133afd6ca690cd1ce581d162c6bb9b3b91f7bd4a6ec058e5b5ba8964dd00bb
|
|
7
|
+
data.tar.gz: bbd5a609a1dcca7cfbf1d95c0ada4ce8cb697720669864996f26d29809ce36c23dca95b54ddb6a67ec422d4d3f533b4200c65fe10e2c6d04842c8d087c5f51f8
|
data/README.markdown
CHANGED
|
@@ -57,7 +57,7 @@ _Web Console_ has been tested on the following rubies.
|
|
|
57
57
|
There is an experimental _JRuby_ 1.7 support. See Installation section for more
|
|
58
58
|
information.
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
_Rubinius_ in 1.9 mode may work, but it hasn't been explicitly tested.
|
|
61
61
|
|
|
62
62
|
_Web Console_ is built explicitly for _Rails 4_. Check out the
|
|
63
63
|
[web-console-rails3] project for a _Rails 3_ compatible build.
|
|
@@ -69,17 +69,7 @@ To install it in your current application, add the following to your `Gemfile`.
|
|
|
69
69
|
|
|
70
70
|
```ruby
|
|
71
71
|
group :development do
|
|
72
|
-
gem 'web-console', '2.0.0.
|
|
73
|
-
end
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
For _JRuby_ support, you need to add an unreleased version of
|
|
77
|
-
`binding_of_caller`.
|
|
78
|
-
|
|
79
|
-
```ruby
|
|
80
|
-
group :development do
|
|
81
|
-
gem 'web-console', '2.0.0.beta2'
|
|
82
|
-
gem 'binding_of_caller', github: 'banister/binding_of_caller'
|
|
72
|
+
gem 'web-console', '2.0.0.beta3'
|
|
83
73
|
end
|
|
84
74
|
```
|
|
85
75
|
|
|
@@ -288,11 +278,18 @@ end
|
|
|
288
278
|
You may also change the font, which is following the CSS font property syntax.
|
|
289
279
|
By default it is `large DejaVu Sans Mono, Liberation Mono, monospace`.
|
|
290
280
|
|
|
291
|
-
|
|
292
|
-
|
|
281
|
+
Credits
|
|
282
|
+
-------
|
|
283
|
+
|
|
284
|
+
* Shoutout to [Charlie Somerville] for [better_errors]! Most of the exception
|
|
285
|
+
binding code is coming straight out of the [better_errors] project.
|
|
286
|
+
|
|
287
|
+
* _Web Console_ wouldn't be possible without the work [John Mair] put in
|
|
288
|
+
[binding_of_caller]. This is the technology that let us execute a console
|
|
289
|
+
right where an error occured.
|
|
293
290
|
|
|
294
|
-
|
|
295
|
-
|
|
291
|
+
* Thanks to [Charles Oliver Nutter] for all the JRuby feedback and support he
|
|
292
|
+
has given us.
|
|
296
293
|
|
|
297
294
|
FAQ
|
|
298
295
|
---
|
|
@@ -307,18 +304,6 @@ is even slower. Read more about the problem at the _JRuby_ [wiki].
|
|
|
307
304
|
|
|
308
305
|
### I'm running JRuby and there's no console on the default error page.
|
|
309
306
|
|
|
310
|
-
_JRuby_ support in the default error page requires the latest is experimental
|
|
311
|
-
and requires an unreleased version of `web-console` and `binding_of_caller`.
|
|
312
|
-
|
|
313
|
-
To try it out, put this in your Gemfile.
|
|
314
|
-
|
|
315
|
-
```ruby
|
|
316
|
-
group :development do
|
|
317
|
-
gem 'web-console', github: 'rails/web-console'
|
|
318
|
-
gem 'binding_of_caller', github: 'banister/binding_of_caller'
|
|
319
|
-
end
|
|
320
|
-
```
|
|
321
|
-
|
|
322
307
|
You would also have to run you Rails server in JRuby's interpreted mode. Enable
|
|
323
308
|
it with code snippet below, then start your development Rails server with
|
|
324
309
|
`rails server`, as usual.
|
|
@@ -330,9 +315,6 @@ export JRUBY_OPTS=-J-Djruby.compile.mode=OFF
|
|
|
330
315
|
# export JRUBY_OPTS=--dev
|
|
331
316
|
```
|
|
332
317
|
|
|
333
|
-
_(Please, note that we don't guarantee master to be stable and we
|
|
334
|
-
will appreciate any issue reports!)_
|
|
335
|
-
|
|
336
318
|
### Changing the colors is broken.
|
|
337
319
|
|
|
338
320
|
Some of the style sheets may be cached on the file system. Run
|
|
@@ -350,4 +332,7 @@ The interactive console executes Ruby code. Invoking `instance_variables` and
|
|
|
350
332
|
[web-console-rails3]: https://github.com/gsamokovarov/web-console-rails3
|
|
351
333
|
[wiki]: https://github.com/jruby/jruby/wiki/Improving-startup-time#avoid-spawning-sub-rubies
|
|
352
334
|
[better_errors]: https://github.com/charliesome/better_errors
|
|
335
|
+
[binding_of_caller]: https://github.com/banister/binding_of_caller
|
|
353
336
|
[Charlie Somerville]: https://github.com/charliesome
|
|
337
|
+
[John Mair]: https://github.com/banister
|
|
338
|
+
[Charles Oliver Nutter]: https://github.com/headius
|
|
@@ -17,6 +17,7 @@ var AJAXTransport = (function(WebConsole) {
|
|
|
17
17
|
configuration: options.url
|
|
18
18
|
} : options.url;
|
|
19
19
|
|
|
20
|
+
this.uid = options.uid;
|
|
20
21
|
this.pendingInput = '';
|
|
21
22
|
|
|
22
23
|
this.initializeEventHandlers();
|
|
@@ -38,8 +39,7 @@ var AJAXTransport = (function(WebConsole) {
|
|
|
38
39
|
AJAXTransport.prototype.createRequest = function(method, url, options) {
|
|
39
40
|
options || (options = {});
|
|
40
41
|
|
|
41
|
-
var
|
|
42
|
-
request.open(method, url);
|
|
42
|
+
var params = '';
|
|
43
43
|
|
|
44
44
|
if (typeof options.form === 'object') {
|
|
45
45
|
var content = [], form = options.form;
|
|
@@ -49,15 +49,25 @@ var AJAXTransport = (function(WebConsole) {
|
|
|
49
49
|
content.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
params = content.join('&');
|
|
53
|
+
if (method === 'GET' ? '?' : '') params = '?' + params;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var request = new XMLHttpRequest;
|
|
57
|
+
request.open(method, method === 'GET' ? url + params : url);
|
|
58
|
+
|
|
59
|
+
if (params && method != 'GET') {
|
|
52
60
|
request.setRequestHeader('Content-Type', FORM_MIME_TYPE);
|
|
53
|
-
request.data =
|
|
61
|
+
request.data = params;
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
return request;
|
|
57
65
|
};
|
|
58
66
|
|
|
59
67
|
AJAXTransport.prototype.pollForPendingOutput = function() {
|
|
60
|
-
var request = this.createRequest('GET', this.url.pendingOutput
|
|
68
|
+
var request = this.createRequest('GET', this.url.pendingOutput, {
|
|
69
|
+
form: { uid: this.uid }
|
|
70
|
+
});
|
|
61
71
|
|
|
62
72
|
var self = this;
|
|
63
73
|
request.onreadystatechange = function() {
|
|
@@ -90,7 +100,7 @@ var AJAXTransport = (function(WebConsole) {
|
|
|
90
100
|
this.sendingInput = true;
|
|
91
101
|
|
|
92
102
|
var request = this.createRequest('PUT', this.url.input, {
|
|
93
|
-
form: { input: this.pendingInput + input }
|
|
103
|
+
form: { input: this.pendingInput + input, uid: this.uid }
|
|
94
104
|
});
|
|
95
105
|
|
|
96
106
|
// Clear the pending input.
|
|
@@ -117,7 +127,7 @@ var AJAXTransport = (function(WebConsole) {
|
|
|
117
127
|
if (this.disconnected) return;
|
|
118
128
|
|
|
119
129
|
var request = this.createRequest('PUT', this.url.configuration, {
|
|
120
|
-
form: { width: cols, height: rows }
|
|
130
|
+
form: { width: cols, height: rows, uid: this.uid }
|
|
121
131
|
});
|
|
122
132
|
|
|
123
133
|
// Just send the configuration and don't care about any output.
|
|
@@ -10,26 +10,30 @@ module WebConsole
|
|
|
10
10
|
render json: exception, status: :unprocessable_entity
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
rescue_from ConsoleSession::Unauthorized do |exception|
|
|
14
|
+
render json: exception, status: :unauthorized
|
|
15
|
+
end
|
|
16
|
+
|
|
13
17
|
def index
|
|
14
18
|
@console_session = ConsoleSession.create
|
|
15
19
|
end
|
|
16
20
|
|
|
17
21
|
def input
|
|
18
|
-
@console_session = ConsoleSession.
|
|
22
|
+
@console_session = ConsoleSession.find_by_pid_and_uid(params[:id], params[:uid])
|
|
19
23
|
@console_session.send_input(console_session_params[:input])
|
|
20
24
|
|
|
21
25
|
render nothing: true
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
def configuration
|
|
25
|
-
@console_session = ConsoleSession.
|
|
29
|
+
@console_session = ConsoleSession.find_by_pid_and_uid(params[:id], params[:uid])
|
|
26
30
|
@console_session.configure(console_session_params)
|
|
27
31
|
|
|
28
32
|
render nothing: true
|
|
29
33
|
end
|
|
30
34
|
|
|
31
35
|
def pending_output
|
|
32
|
-
@console_session = ConsoleSession.
|
|
36
|
+
@console_session = ConsoleSession.find_by_pid_and_uid(params[:id], params[:uid])
|
|
33
37
|
|
|
34
38
|
render json: { output: @console_session.pending_output }
|
|
35
39
|
end
|
|
@@ -37,7 +41,7 @@ module WebConsole
|
|
|
37
41
|
private
|
|
38
42
|
|
|
39
43
|
def console_session_params
|
|
40
|
-
params.permit(:id, :input, :width, :height)
|
|
44
|
+
params.permit(:id, :uid, :input, :width, :height)
|
|
41
45
|
end
|
|
42
46
|
end
|
|
43
47
|
end
|
|
@@ -24,6 +24,9 @@ module WebConsole
|
|
|
24
24
|
# Raised when an operation transition to an invalid state.
|
|
25
25
|
Invalid = Class.new(Error)
|
|
26
26
|
|
|
27
|
+
# Raised when a request doesn't know the slave process uid.
|
|
28
|
+
Unauthorized = Class.new(Error)
|
|
29
|
+
|
|
27
30
|
class << self
|
|
28
31
|
# Finds a session by its pid.
|
|
29
32
|
#
|
|
@@ -32,6 +35,16 @@ module WebConsole
|
|
|
32
35
|
INMEMORY_STORAGE[pid.to_i] or raise Unavailable, 'Session unavailable'
|
|
33
36
|
end
|
|
34
37
|
|
|
38
|
+
# Finds a session by its pid.
|
|
39
|
+
#
|
|
40
|
+
# Raises WebConsole::ConsoleSession::Expired if there is no such session.
|
|
41
|
+
# Raises WebConsole::ConsoleSession::Unauthorized if uid doesn't match.
|
|
42
|
+
def find_by_pid_and_uid(pid, uid)
|
|
43
|
+
find(pid).tap do |console_session|
|
|
44
|
+
raise Unauthorized if console_session.uid != uid
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
35
48
|
# Creates an already persisted consolse session.
|
|
36
49
|
#
|
|
37
50
|
# Use this method if you need to persist a session, without providing it
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
input: "<%= web_console.input_console_session_path(@console_session) %>",
|
|
10
10
|
pendingOutput: "<%= web_console.pending_output_console_session_path(@console_session) %>",
|
|
11
11
|
configuration: "<%= web_console.configuration_console_session_path(@console_session) %>"
|
|
12
|
-
}
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
uid: "<%= @console_session.uid %>"
|
|
13
15
|
}
|
|
14
16
|
};
|
|
15
17
|
</script>
|
|
@@ -5,9 +5,9 @@ module ActionDispatch
|
|
|
5
5
|
def call(env)
|
|
6
6
|
request = Request.new(env)
|
|
7
7
|
|
|
8
|
-
if request.put? && m = env["PATH_INFO"].match(%r{/repl_sessions/(?<id>.+?)\z})
|
|
8
|
+
if request.put? && request.xhr? && m = env["PATH_INFO"].match(%r{/repl_sessions/(?<id>.+?)\z})
|
|
9
9
|
update_repl_session(m[:id], request.params[:input])
|
|
10
|
-
elsif request.post? && m = env["PATH_INFO"].match(%r{/repl_sessions/(?<id>.+?)/trace\z})
|
|
10
|
+
elsif request.post? && request.xhr? && m = env["PATH_INFO"].match(%r{/repl_sessions/(?<id>.+?)/trace\z})
|
|
11
11
|
change_stack_trace(m[:id], request.params[:frame_id])
|
|
12
12
|
else
|
|
13
13
|
middleware_call(env)
|
|
@@ -52,8 +52,8 @@ module ActionDispatch
|
|
|
52
52
|
traces = traces_from_wrapper(wrapper)
|
|
53
53
|
extract_sources = wrapper.extract_sources
|
|
54
54
|
console_session = WebConsole::REPLSession.create(
|
|
55
|
-
binding:
|
|
56
|
-
binding_stack: exception.
|
|
55
|
+
binding: exception.bindings.first,
|
|
56
|
+
binding_stack: exception.bindings
|
|
57
57
|
)
|
|
58
58
|
log_error(env, wrapper)
|
|
59
59
|
|
|
@@ -107,9 +107,5 @@ module ActionDispatch
|
|
|
107
107
|
full_trace: application_trace + framework_trace
|
|
108
108
|
}
|
|
109
109
|
end
|
|
110
|
-
|
|
111
|
-
def binding_from_exception(exception)
|
|
112
|
-
exception.__web_console_bindings_stack[0]
|
|
113
|
-
end
|
|
114
110
|
end
|
|
115
111
|
end
|
|
@@ -36,11 +36,12 @@
|
|
|
36
36
|
// Add CSS styles dynamically. This probably doesnt work for IE <8.
|
|
37
37
|
var style = document.createElement('style');
|
|
38
38
|
style.type = 'text/css';
|
|
39
|
-
style.innerHTML =
|
|
40
|
-
"#console
|
|
41
|
-
"#console div.console-
|
|
42
|
-
"#console div.console-
|
|
43
|
-
"#console div.console-
|
|
39
|
+
style.innerHTML =
|
|
40
|
+
"#console { position: fixed; left: 0; bottom: 0; width: 100%; height: 150px; border: 1px solid; padding-bottom: 20px; } " +
|
|
41
|
+
"#console div.console-inner { font-family: monospace; font-size: 11px; height: 100%; overflow: auto; background: #333; padding: 10px; } " +
|
|
42
|
+
"#console div.console-prompt-box { color: #FFF; } " +
|
|
43
|
+
"#console div.console-message { color: #1AD027; } " +
|
|
44
|
+
"#console div.console-focus span.console-cursor { background: #FEFEFE; color: #333; font-weight: bold; }";
|
|
44
45
|
document.getElementsByTagName('head')[0].appendChild(style);
|
|
45
46
|
|
|
46
47
|
/**
|
|
@@ -361,16 +362,16 @@
|
|
|
361
362
|
var _this = this;
|
|
362
363
|
var xhr = new XMLHttpRequest();
|
|
363
364
|
var url = consoleDiv.dataset.remotePath;
|
|
364
|
-
var params = "input=" + line;
|
|
365
|
+
var params = "input=" + encodeURIComponent(line);
|
|
365
366
|
|
|
366
367
|
xhr.open("PUT", url, true);
|
|
367
|
-
xhr.setRequestHeader("Content-
|
|
368
|
+
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
|
369
|
+
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
|
368
370
|
xhr.send(params);
|
|
369
371
|
|
|
370
372
|
xhr.onreadystatechange = function() {
|
|
371
373
|
if(xhr.readyState == 4 && xhr.status == 200) {
|
|
372
374
|
var response = JSON.parse(xhr.responseText);
|
|
373
|
-
console.log(response.output);
|
|
374
375
|
_this.writeOutput(response.output);
|
|
375
376
|
}
|
|
376
377
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<tr class='route_row' data-helper='path'>
|
|
2
|
+
<td data-route-name='<%= route[:name] %>'>
|
|
3
|
+
<% if route[:name].present? %>
|
|
4
|
+
<%= route[:name] %><span class='helper'>_path</span>
|
|
5
|
+
<% end %>
|
|
6
|
+
</td>
|
|
7
|
+
<td data-route-verb='<%= route[:verb] %>'>
|
|
8
|
+
<%= route[:verb] %>
|
|
9
|
+
</td>
|
|
10
|
+
<td data-route-path='<%= route[:path] %>' data-regexp='<%= route[:regexp] %>'>
|
|
11
|
+
<%= route[:path] %>
|
|
12
|
+
</td>
|
|
13
|
+
<td data-route-reqs='<%= route[:reqs] %>'>
|
|
14
|
+
<%= route[:reqs] %>
|
|
15
|
+
</td>
|
|
16
|
+
</tr>
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<% content_for :style do %>
|
|
2
|
+
#route_table {
|
|
3
|
+
margin: 0 auto 0;
|
|
4
|
+
border-collapse: collapse;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
#route_table thead tr {
|
|
8
|
+
border-bottom: 2px solid #ddd;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
#route_table thead tr.bottom {
|
|
12
|
+
border-bottom: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
#route_table thead tr.bottom th {
|
|
16
|
+
padding: 10px 0;
|
|
17
|
+
line-height: 15px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#route_table tbody tr {
|
|
21
|
+
border-bottom: 1px solid #ddd;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#route_table tbody tr:nth-child(odd) {
|
|
25
|
+
background: #f2f2f2;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#route_table tbody.exact_matches,
|
|
29
|
+
#route_table tbody.fuzzy_matches {
|
|
30
|
+
background-color: LightGoldenRodYellow;
|
|
31
|
+
border-bottom: solid 2px SlateGrey;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#route_table tbody.exact_matches tr,
|
|
35
|
+
#route_table tbody.fuzzy_matches tr {
|
|
36
|
+
background: none;
|
|
37
|
+
border-bottom: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#route_table td {
|
|
41
|
+
padding: 4px 30px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#path_search {
|
|
45
|
+
width: 80%;
|
|
46
|
+
font-size: inherit;
|
|
47
|
+
}
|
|
48
|
+
<% end %>
|
|
49
|
+
|
|
50
|
+
<table id='route_table' class='route_table'>
|
|
51
|
+
<thead>
|
|
52
|
+
<tr>
|
|
53
|
+
<th>Helper</th>
|
|
54
|
+
<th>HTTP Verb</th>
|
|
55
|
+
<th>Path</th>
|
|
56
|
+
<th>Controller#Action</th>
|
|
57
|
+
</tr>
|
|
58
|
+
<tr class='bottom'>
|
|
59
|
+
<th><%# Helper %>
|
|
60
|
+
<%= link_to "Path", "#", 'data-route-helper' => '_path',
|
|
61
|
+
title: "Returns a relative path (without the http or domain)" %> /
|
|
62
|
+
<%= link_to "Url", "#", 'data-route-helper' => '_url',
|
|
63
|
+
title: "Returns an absolute url (with the http and domain)" %>
|
|
64
|
+
</th>
|
|
65
|
+
<th><%# HTTP Verb %>
|
|
66
|
+
</th>
|
|
67
|
+
<th><%# Path %>
|
|
68
|
+
<%= search_field(:path, nil, id: 'search', placeholder: "Path Match") %>
|
|
69
|
+
</th>
|
|
70
|
+
<th><%# Controller#action %>
|
|
71
|
+
</th>
|
|
72
|
+
</tr>
|
|
73
|
+
</thead>
|
|
74
|
+
<tbody class='exact_matches' id='exact_matches'>
|
|
75
|
+
</tbody>
|
|
76
|
+
<tbody class='fuzzy_matches' id='fuzzy_matches'>
|
|
77
|
+
</tbody>
|
|
78
|
+
<tbody>
|
|
79
|
+
<%= yield %>
|
|
80
|
+
</tbody>
|
|
81
|
+
</table>
|
|
82
|
+
|
|
83
|
+
<script type='text/javascript'>
|
|
84
|
+
// Iterates each element through a function
|
|
85
|
+
function each(elems, func) {
|
|
86
|
+
if (!elems instanceof Array) { elems = [elems]; }
|
|
87
|
+
for (var i = 0, len = elems.length; i < len; i++) {
|
|
88
|
+
func(elems[i]);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Sets innerHTML for an element
|
|
93
|
+
function setContent(elem, text) {
|
|
94
|
+
elem.innerHTML = text;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Enables path search functionality
|
|
98
|
+
function setupMatchPaths() {
|
|
99
|
+
// Check if the user input (sanitized as a path) matches the regexp data attribute
|
|
100
|
+
function checkExactMatch(section, elem, value) {
|
|
101
|
+
var string = sanitizePath(value),
|
|
102
|
+
regexp = elem.getAttribute("data-regexp");
|
|
103
|
+
|
|
104
|
+
showMatch(string, regexp, section, elem);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Check if the route path data attribute contains the user input
|
|
108
|
+
function checkFuzzyMatch(section, elem, value) {
|
|
109
|
+
var string = elem.getAttribute("data-route-path"),
|
|
110
|
+
regexp = value;
|
|
111
|
+
|
|
112
|
+
showMatch(string, regexp, section, elem);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Display the parent <tr> element in the appropriate section when there's a match
|
|
116
|
+
function showMatch(string, regexp, section, elem) {
|
|
117
|
+
if(string.match(RegExp(regexp))) {
|
|
118
|
+
section.appendChild(elem.parentNode.cloneNode(true));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Check if there are any matched results in a section
|
|
123
|
+
function checkNoMatch(section, defaultText, noMatchText) {
|
|
124
|
+
if (section.innerHTML === defaultText) {
|
|
125
|
+
setContent(section, defaultText + noMatchText);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Ensure path always starts with a slash "/" and remove params or fragments
|
|
130
|
+
function sanitizePath(path) {
|
|
131
|
+
var path = path.charAt(0) == '/' ? path : "/" + path;
|
|
132
|
+
return path.replace(/\#.*|\?.*/, '');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
var regexpElems = document.querySelectorAll('#route_table [data-regexp]'),
|
|
136
|
+
searchElem = document.querySelector('#search'),
|
|
137
|
+
exactMatches = document.querySelector('#exact_matches'),
|
|
138
|
+
fuzzyMatches = document.querySelector('#fuzzy_matches');
|
|
139
|
+
|
|
140
|
+
// Remove matches when no search value is present
|
|
141
|
+
searchElem.onblur = function(e) {
|
|
142
|
+
if (searchElem.value === "") {
|
|
143
|
+
setContent(exactMatches, "");
|
|
144
|
+
setContent(fuzzyMatches, "");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// On key press perform a search for matching paths
|
|
149
|
+
searchElem.onkeyup = function(e){
|
|
150
|
+
var userInput = searchElem.value,
|
|
151
|
+
defaultExactMatch = '<tr><th colspan="4">Paths Matching (' + escape(sanitizePath(userInput)) +'):</th></tr>',
|
|
152
|
+
defaultFuzzyMatch = '<tr><th colspan="4">Paths Containing (' + escape(userInput) +'):</th></tr>',
|
|
153
|
+
noExactMatch = '<tr><th colspan="4">No Exact Matches Found</th></tr>',
|
|
154
|
+
noFuzzyMatch = '<tr><th colspan="4">No Fuzzy Matches Found</th></tr>';
|
|
155
|
+
|
|
156
|
+
// Clear out results section
|
|
157
|
+
setContent(exactMatches, defaultExactMatch);
|
|
158
|
+
setContent(fuzzyMatches, defaultFuzzyMatch);
|
|
159
|
+
|
|
160
|
+
// Display exact matches and fuzzy matches
|
|
161
|
+
each(regexpElems, function(elem) {
|
|
162
|
+
checkExactMatch(exactMatches, elem, userInput);
|
|
163
|
+
checkFuzzyMatch(fuzzyMatches, elem, userInput);
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// Display 'No Matches' message when no matches are found
|
|
167
|
+
checkNoMatch(exactMatches, defaultExactMatch, noExactMatch);
|
|
168
|
+
checkNoMatch(fuzzyMatches, defaultFuzzyMatch, noFuzzyMatch);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Enables functionality to toggle between `_path` and `_url` helper suffixes
|
|
173
|
+
function setupRouteToggleHelperLinks() {
|
|
174
|
+
|
|
175
|
+
// Sets content for each element
|
|
176
|
+
function setValOn(elems, val) {
|
|
177
|
+
each(elems, function(elem) {
|
|
178
|
+
setContent(elem, val);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Sets onClick event for each element
|
|
183
|
+
function onClick(elems, func) {
|
|
184
|
+
each(elems, function(elem) {
|
|
185
|
+
elem.onclick = func;
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
var toggleLinks = document.querySelectorAll('#route_table [data-route-helper]');
|
|
190
|
+
onClick(toggleLinks, function(){
|
|
191
|
+
var helperTxt = this.getAttribute("data-route-helper"),
|
|
192
|
+
helperElems = document.querySelectorAll('[data-route-name] span.helper');
|
|
193
|
+
|
|
194
|
+
setValOn(helperElems, helperTxt);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
setupMatchPaths();
|
|
199
|
+
setupRouteToggleHelperLinks();
|
|
200
|
+
</script>
|