tobias-rack-webconsole 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ *.gem
2
+ .bundle
3
+ pkg/*
4
+ graph.png
5
+ .yardoc/*
6
+ doc/*
7
+ coverage/*
8
+ *.rbc
9
+ tags
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use ruby-1.9.3@rack-webconsole
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ # https://github.com/travis-ci/travis-ci/wiki/.travis.yml-options
2
+ rvm:
3
+ - 1.8.7 # (current default)
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - ree
7
+ - ruby-head
8
+ - rbx-18mode
9
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rack-webconsole.gemspec
4
+ gemspec
5
+ gem 'rake'
6
+ gem 'mocha' #, :git => 'git://github.com/floehopper/mocha.git'
data/Gemfile.lock ADDED
@@ -0,0 +1,40 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rack-webconsole (0.1.3)
5
+ multi_json (~> 1.0.3)
6
+ rack
7
+ ripl (~> 0.5.1)
8
+ ripl-multi_line (~> 0.3.0)
9
+
10
+ GEM
11
+ remote: http://rubygems.org/
12
+ specs:
13
+ bluecloth (2.2.0)
14
+ bond (0.4.1)
15
+ metaclass (0.0.1)
16
+ minitest (2.11.4)
17
+ mocha (0.10.5)
18
+ metaclass (~> 0.0.1)
19
+ multi_json (1.0.4)
20
+ purdytest (1.0.0)
21
+ minitest (~> 2.2)
22
+ rack (1.4.1)
23
+ rake (0.9.2.2)
24
+ ripl (0.5.1)
25
+ bond (~> 0.4.0)
26
+ ripl-multi_line (0.3.0)
27
+ ripl (>= 0.3.6)
28
+ yard (0.7.5)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ bluecloth
35
+ minitest
36
+ mocha
37
+ purdytest
38
+ rack-webconsole!
39
+ rake
40
+ yard
data/History ADDED
@@ -0,0 +1,27 @@
1
+ === 0.1.3 / 2012-03-22
2
+
3
+ + Make keycode configurable (Roger Leite)
4
+ + Switch to multi_json (Josh Buddy)
5
+ ! Fix markup to make it work in more browsers
6
+
7
+ === 0.1.2 / 2011-08-01
8
+
9
+ + Change field name to avoid conflicts with other forms (Chris Apolzon)
10
+ + Prevent visual flash of unstyled content (Rob Cameron)
11
+ + Fix minor styling issues (Jeff Kreeftmeijer)
12
+ + Avoid conflicts with libraries other than JQuery (Jo Liss)
13
+
14
+ === 0.1.1 / 2011-07-27
15
+
16
+ ! Fix bug with Content-Length not being calculated appropriately. (Corin Langosch)
17
+ + Refactor JavaScript to avoid messing with prototypes (Corin Langosch)
18
+
19
+ === 0.1.0 / 2011-07-27
20
+
21
+ + The request object is now exposed in the console through #request method
22
+ + Various UI enhancements
23
+ ! Fix bug where Sandbox locals were much more than those defined by the user.
24
+
25
+ === 0.0.5 / 2011-07-26
26
+
27
+ ! Protection against CSRF attacks.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+ desc "Run rack-webconsole specs"
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "spec"
8
+ t.test_files = FileList['spec/**/*_spec.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ require 'yard'
13
+ YARD::Rake::YardocTask.new(:docs) do |t|
14
+ t.files = ['lib/**/*.rb']
15
+ t.options = ['-m', 'markdown', '--no-private', '-r', 'Readme.md', '--title', 'rack-webconsole documentation']
16
+ end
17
+ task :doc => [:docs]
18
+
19
+ desc "Generate and open class diagram (needs Graphviz installed)"
20
+ task :graph do |t|
21
+ `bundle exec yard graph -d --full --no-private | dot -Tpng -o graph.png && open graph.png`
22
+ end
23
+ task :default => [:test]
data/Readme.md ADDED
@@ -0,0 +1,125 @@
1
+ #rack-webconsole [![Build Status](http://travis-ci.org/codegram/rack-webconsole.png)](http://travis-ci.org/codegram/rack-webconsole.png)
2
+
3
+ Rack-webconsole is a Rack-based interactive console (à la Rails console) in
4
+ your web application's frontend. That means you can interact with your
5
+ application's backend from within the browser itself!
6
+
7
+ To get a clearer idea, you can check out this video showing a live example :)
8
+
9
+ [![YouTube video](http://img.youtube.com/vi/yKK5J01Dqts/0.jpg)](http://youtu.be/yKK5J01Dqts?hd=1)
10
+
11
+ Rack-webconsole is a Rack middleware designed to be unobtrusive. With Rails 3,
12
+ for example, you only have to include the gem in your Gemfile and it already
13
+ works. Without any configuration.
14
+
15
+ Tested with MRI versions 1.8.7, 1.9.2, ruby-head, and JRuby 1.6.3.
16
+
17
+ **SECURITY NOTE**: From version v0.0.5 rack-webconsole uses a token system to
18
+ protect against cross-site request forgery.
19
+
20
+ ##Resources
21
+
22
+ * [Example video](http://youtu.be/yKK5J01Dqts?hd=1)
23
+ * [Documentation](http://rubydoc.info/github/codegram/rack-webconsole)
24
+
25
+
26
+ ##Install
27
+
28
+ In your Gemfile:
29
+
30
+ ```ruby
31
+ gem 'rack-webconsole'
32
+ ```
33
+
34
+ Rack-webconsole **needs JQuery**. If you are using Rails 3, JQuery is loaded by
35
+ default. In case you don't want to use JQuery in your application,
36
+ **rack-webconsole can inject it for you** only when it needs it. To do that you
37
+ should put this line somewhere in your application (a Rails initializer, or
38
+ some configuration file):
39
+
40
+ ```ruby
41
+ Rack::Webconsole.inject_jquery = true
42
+ ```
43
+
44
+ You can also change the javascript key_code used to start webconsole:
45
+
46
+ ```ruby
47
+ # ` = 96 (default), ^ = 94, ç = 231 ... etc.
48
+ Rack::Webconsole.key_code = "231"
49
+ ```
50
+
51
+ ##Usage with Rails 3
52
+
53
+ If you are using Rails 3, you have no further steps to do. It works! To give
54
+ it a try, fire up the Rails server and go to any page, press the ` ` ` key and
55
+ the console will show :)
56
+
57
+ ##Usage with Sinatra/Padrino
58
+
59
+ With Sinatra and Padrino you have to tell your application to use the
60
+ middleware:
61
+
62
+ ```ruby
63
+ require 'sinatra'
64
+ require 'rack/webconsole'
65
+
66
+ class MySinatraApp < Sinatra::Application
67
+ use Rack::Webconsole
68
+ # . . .
69
+ end
70
+
71
+ class SamplePadrino < Padrino::Application
72
+ use Rack::Webconsole
73
+ # . . .
74
+ end
75
+ ```
76
+
77
+ NOTE: If you are using Bundler and initializing it from config.ru, you don't
78
+ have to `require 'rack/webconsole'` manually, otherwise you have to.
79
+
80
+ And it works! Fire up the server, go to any page and press the ` ` ` key.
81
+
82
+ ##Usage with Rails 2
83
+
84
+ You need to add the following code to an intializer (i.e. config/initializers/webconsole.rb):
85
+
86
+ ```ruby
87
+ require 'rack/webconsole'
88
+ ActionController::Dispatcher.middleware.insert_after 1, Rack::Webconsole
89
+ ```
90
+
91
+ ##Commands
92
+
93
+ In the console you can issue whatever Ruby commands you want, except multiline commands. Local variables are kept, so you can get a more IRB-esque feeling.
94
+
95
+ * `reload!` resets all local variables
96
+ * `request` returns the current page request object
97
+
98
+ ##Under the hood
99
+
100
+ Run the test suite by typing:
101
+
102
+ rake
103
+
104
+ You can also build the documentation with the following command:
105
+
106
+ rake docs
107
+
108
+ ## Note on Patches/Pull Requests
109
+
110
+ * Fork the project.
111
+ * Make your feature addition or bug fix.
112
+ * Add tests for it. This is important so we don't break it in a
113
+ future version unintentionally.
114
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself we can ignore when we pull)
115
+ * Send us a pull request. Bonus points for topic branches.
116
+
117
+ ## Released under the MIT License
118
+
119
+ Copyright (c) 2011 Codegram.
120
+
121
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
122
+
123
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
124
+
125
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+ require 'rack'
3
+ require 'rack/webconsole'
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+ require 'rack/webconsole/repl'
3
+ require 'rack/webconsole/asset_helpers'
4
+ require 'rack/webconsole/assets'
5
+ require 'rack/webconsole/sandbox'
6
+ require 'rack/webconsole/shell'
7
+
8
+ require 'rack/webconsole/railtie' if defined?(Rails::Railtie)
9
+
10
+ # Rack is a modular webserver interface written by Christian Neukirchen.
11
+ #
12
+ # Learn more at: https://github.com/rack/rack
13
+ #
14
+ module Rack
15
+ # {Rack::Webconsole} is a Rack middleware that provides an interactive
16
+ # console à la Rails console, but for any kind of Rack application (Rails,
17
+ # Sinatra, Padrino...), accessible from your web application's front-end.
18
+ #
19
+ # For every request, it normally passes control to the {Assets} middleware,
20
+ # which injects needed JavaScript, CSS and HTML code for the console to work
21
+ # properly.
22
+ #
23
+ # It also exposes a special route used by the {Repl}, a Ruby evaluator which
24
+ # is responsible of keeping state between requests, remembering local
25
+ # variables and giving a true IRB-esque experience.
26
+ #
27
+ class Webconsole
28
+ @@config = {:inject_jquery => false, :key_code => "96"}
29
+
30
+ class << self
31
+ # Returns whether the Asset injecter must inject JQuery or not.
32
+ #
33
+ # @return [Boolean] whether to inject JQuery or not.
34
+ def inject_jquery
35
+ @@config[:inject_jquery]
36
+ end
37
+
38
+ # Sets whether the Asset injecter must inject JQuery or not.
39
+ #
40
+ # @param [Boolean] value whether to inject JQuery or not.
41
+ def inject_jquery=(value)
42
+ @@config[:inject_jquery] = value
43
+ end
44
+
45
+ # Returns key code used to start web console.
46
+ #
47
+ # @return [String] key code used at keypress event to start web console.
48
+ def key_code
49
+ @@config[:key_code]
50
+ end
51
+
52
+ # Sets key code used to start web console.
53
+ #
54
+ # @param [String] value key code used at keypress event to start web console.
55
+ def key_code=(value)
56
+ value = value.to_s unless value.is_a?(String)
57
+ @@config[:key_code] = value
58
+ end
59
+ end
60
+
61
+ # Honor the Rack contract by saving the passed Rack application in an ivar.
62
+ #
63
+ # @param [Rack::Application] app the previous Rack application in the
64
+ # middleware chain.
65
+ def initialize(app)
66
+ @app = app
67
+ end
68
+
69
+ # Decides where to send the request. In case the path is `/webconsole`
70
+ # (e.g. when calling the {Repl} endpoint), pass the request onto the
71
+ # {Repl}. Otherwise, pass it onto the {Assets} middleware, which will
72
+ # inject the needed assets for the Webconsole to work.
73
+ #
74
+ # @param [Hash] env a Rack request environment.
75
+ def call(env)
76
+ if env['PATH_INFO'] == '/webconsole'
77
+ Repl.new(@app).call(env)
78
+ else
79
+ Assets.new(@app).call(env)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,73 @@
1
+ # encoding: utf-8
2
+ module Rack
3
+ class Webconsole
4
+ # Helper module to encapsulate the asset loading logic used by the {Assets}
5
+ # middleware.
6
+ #
7
+ # For now, the strategy is reading the files from disk. In the future, we
8
+ # should come up with a somewhat more sophisticated strategy, although
9
+ # {Webconsole} is used only in development environments, where performance
10
+ # isn't usually a concern.
11
+ #
12
+ module AssetHelpers
13
+ # Loads the HTML from a file in `/public`.
14
+ #
15
+ # It contains a form and the needed divs to render the console.
16
+ #
17
+ # @return [String] the injectable HTML.
18
+ def html_code
19
+ out = ""
20
+ out << asset('jquery.html') if Webconsole.inject_jquery
21
+ out << asset('webconsole.html')
22
+ out
23
+ end
24
+
25
+ # Loads the CSS from a file in `/public`.
26
+ #
27
+ # It contains the styles for the console.
28
+ #
29
+ # @return [String] the injectable CSS.
30
+ def css_code
31
+ '<style type="text/css">' <<
32
+ asset('webconsole.css') <<
33
+ '</style>'
34
+ end
35
+
36
+ # Loads the JavaScript from a file in `/public`.
37
+ #
38
+ # It contains the JavaScript logic of the webconsole.
39
+ #
40
+ # @return [String] the injectable JavaScript.
41
+ def js_code
42
+ '<script type="text/javascript">' <<
43
+ asset('webconsole.js') <<
44
+ '</script>'
45
+ end
46
+
47
+ # Inteprolates the given variables inside the javascrpt code
48
+ #
49
+ # @param [String] javascript The javascript code to insert the variables
50
+ # @param [Hash] variables A hash containing the variables names (as keys)
51
+ # and its values
52
+ #
53
+ # @return [String] the javascript code with the interpolated variables
54
+ def render(javascript, variables = {})
55
+ javascript_with_variables = javascript.dup
56
+ variables.each_pair do |variable, value|
57
+ javascript_with_variables.gsub!("$#{variable}", value)
58
+ end
59
+ javascript_with_variables
60
+ end
61
+
62
+ private
63
+
64
+ def asset(file)
65
+ @assets ||= {}
66
+ output = ::File.open(::File.join(::File.dirname(__FILE__), '..', '..', '..', 'public', file), 'r:UTF-8') do |f|
67
+ f.read
68
+ end
69
+ @assets[file] ||= output
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,75 @@
1
+ # encoding: utf-8
2
+ module Rack
3
+ class Webconsole
4
+ # {Assets} is a Rack middleware responsible for injecting view code for the
5
+ # console to work properly.
6
+ #
7
+ # It intercepts HTTP requests, detects successful HTML responses and
8
+ # injects HTML, CSS and JavaScript code into those.
9
+ #
10
+ class Assets
11
+ include Webconsole::AssetHelpers
12
+
13
+ # Honor the Rack contract by saving the passed Rack application in an ivar.
14
+ #
15
+ # @param [Rack::Application] app the previous Rack application in the
16
+ # middleware chain.
17
+ def initialize(app)
18
+ @app = app
19
+ end
20
+
21
+ # Checks for successful HTML responses and injects HTML, CSS and
22
+ # JavaScript code into them.
23
+ #
24
+ # @param [Hash] env a Rack request environment.
25
+ def call(env)
26
+ status, headers, response = @app.call(env)
27
+ return [status, headers, response] unless check_html?(headers, response) && status == 200
28
+
29
+ if response.respond_to?(:body)
30
+ response_body = response.body
31
+ else
32
+ response_body = response.first
33
+ end
34
+
35
+ # Regenerate the security token
36
+ Webconsole::Repl.reset_token
37
+
38
+ # Expose the request object to the Repl
39
+ Webconsole::Repl.request = Rack::Request.new(env)
40
+
41
+ # Inject the html, css and js code to the view
42
+ response_body.gsub!('</body>', "#{code(env)}</body>")
43
+
44
+ headers['Content-Length'] = response_body.bytesize.to_s
45
+
46
+ [status, headers, [response_body]]
47
+ end
48
+
49
+ # Returns a string with all the HTML, CSS and JavaScript code needed for
50
+ # the view.
51
+ #
52
+ # It puts the security token inside the JavaScript to make AJAX calls
53
+ # secure.
54
+ #
55
+ # @return [String] the injectable code.
56
+ def code(env)
57
+ html_code <<
58
+ css_code <<
59
+ render(js_code,
60
+ :TOKEN => Webconsole::Repl.token,
61
+ :KEY_CODE => Webconsole.key_code,
62
+ :CONTEXT => env['SCRIPT_NAME'] || "")
63
+ end
64
+
65
+ private
66
+
67
+ def check_html?(headers, response)
68
+ body = response.respond_to?(:body) ? response.body : response.first
69
+ headers['Content-Type'] and
70
+ headers['Content-Type'].include? 'text/html' and
71
+ body =~ %r{<html.*</html>}m
72
+ end
73
+ end
74
+ end
75
+ end