rails-prg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.cane +4 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +3 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +44 -0
  8. data/Rakefile +38 -0
  9. data/lib/rails-prg.rb +5 -0
  10. data/lib/rails/prg.rb +8 -0
  11. data/lib/rails/prg/railtie.rb +13 -0
  12. data/lib/rails/prg/redirected_object_controller.rb +84 -0
  13. data/lib/rails/prg/version.rb +5 -0
  14. data/lib/tasks/quality.rake +15 -0
  15. data/rails-prg.gemspec +43 -0
  16. data/script/spec +22 -0
  17. data/spec/dummy/README.rdoc +28 -0
  18. data/spec/dummy/Rakefile +6 -0
  19. data/spec/dummy/app/assets/images/.keep +0 -0
  20. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  21. data/spec/dummy/app/assets/javascripts/error_duplicator.js +2 -0
  22. data/spec/dummy/app/assets/javascripts/error_duplicators.js +2 -0
  23. data/spec/dummy/app/assets/javascripts/example_prgs.js +2 -0
  24. data/spec/dummy/app/assets/javascripts/post_redirect_gets.js +2 -0
  25. data/spec/dummy/app/assets/javascripts/test_objects.js +2 -0
  26. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  27. data/spec/dummy/app/assets/stylesheets/error_duplicator.css +4 -0
  28. data/spec/dummy/app/assets/stylesheets/error_duplicators.css +4 -0
  29. data/spec/dummy/app/assets/stylesheets/example_prgs.css +4 -0
  30. data/spec/dummy/app/assets/stylesheets/post_redirect_gets.css +4 -0
  31. data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
  32. data/spec/dummy/app/assets/stylesheets/test_objects.css +4 -0
  33. data/spec/dummy/app/controllers/application_controller.rb +19 -0
  34. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  35. data/spec/dummy/app/controllers/error_duplicators_controller.rb +64 -0
  36. data/spec/dummy/app/controllers/example_prgs_controller.rb +74 -0
  37. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  38. data/spec/dummy/app/helpers/error_duplicators_helper.rb +2 -0
  39. data/spec/dummy/app/helpers/example_prgs_helper.rb +2 -0
  40. data/spec/dummy/app/mailers/.keep +0 -0
  41. data/spec/dummy/app/models/.keep +0 -0
  42. data/spec/dummy/app/models/concerns/.keep +0 -0
  43. data/spec/dummy/app/models/error_duplicator.rb +3 -0
  44. data/spec/dummy/app/models/example_prg.rb +3 -0
  45. data/spec/dummy/app/views/error_duplicators/_form.html.erb +29 -0
  46. data/spec/dummy/app/views/error_duplicators/edit.html.erb +6 -0
  47. data/spec/dummy/app/views/error_duplicators/index.html.erb +31 -0
  48. data/spec/dummy/app/views/error_duplicators/new.html.erb +5 -0
  49. data/spec/dummy/app/views/error_duplicators/show.html.erb +19 -0
  50. data/spec/dummy/app/views/example_prgs/_form.html.erb +29 -0
  51. data/spec/dummy/app/views/example_prgs/edit.html.erb +6 -0
  52. data/spec/dummy/app/views/example_prgs/index.html.erb +31 -0
  53. data/spec/dummy/app/views/example_prgs/new.html.erb +5 -0
  54. data/spec/dummy/app/views/example_prgs/show.html.erb +19 -0
  55. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  56. data/spec/dummy/config.ru +4 -0
  57. data/spec/dummy/config/application.rb +29 -0
  58. data/spec/dummy/config/boot.rb +5 -0
  59. data/spec/dummy/config/database.yml +25 -0
  60. data/spec/dummy/config/environment.rb +5 -0
  61. data/spec/dummy/config/environments/development.rb +29 -0
  62. data/spec/dummy/config/environments/production.rb +80 -0
  63. data/spec/dummy/config/environments/test.rb +36 -0
  64. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  65. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  66. data/spec/dummy/config/initializers/inflections.rb +16 -0
  67. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  68. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  69. data/spec/dummy/config/initializers/session_store.rb +3 -0
  70. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  71. data/spec/dummy/config/locales/en.yml +23 -0
  72. data/spec/dummy/config/routes.rb +4 -0
  73. data/spec/dummy/db/migrate/20140225004609_create_error_duplicators.rb +12 -0
  74. data/spec/dummy/db/migrate/20140225070319_create_example_prgs.rb +12 -0
  75. data/spec/dummy/db/schema.rb +36 -0
  76. data/spec/dummy/db/structure.sql +9 -0
  77. data/spec/dummy/lib/assets/.keep +0 -0
  78. data/spec/dummy/public/404.html +58 -0
  79. data/spec/dummy/public/422.html +58 -0
  80. data/spec/dummy/public/500.html +57 -0
  81. data/spec/dummy/public/favicon.ico +0 -0
  82. data/spec/rails/prg/features/error_duplication_spec.rb +100 -0
  83. data/spec/rails/prg/features/redirected_objects_spec.rb +92 -0
  84. data/spec/rails/prg/redirected_object_controller_spec.rb +282 -0
  85. data/spec/spec_helper.rb +36 -0
  86. data/spec/support/selenium_display.rb +78 -0
  87. data/spec/support/use_selenium_display.rb +13 -0
  88. data/spec/support/use_simplecov.rb +30 -0
  89. metadata +392 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1b012c70c0e0c73ddad3f874e4e9da3530fa5ee4
4
+ data.tar.gz: b0ff3de2236d99c9df5806101d3d5761fd134da3
5
+ SHA512:
6
+ metadata.gz: 6bc32193437e830f0120fcb49e1b2140b45b2918b248777515e13aec01fc808e22b1dbe03e190b704050db46e70b1e162d807481ce6d1d7b0540b75cb846cff7
7
+ data.tar.gz: 3928df8b355fe672b452f3dd5a1a7f0fc5682ab67410776e7ea15468f29e98a535ec48f31033892658499a5f7c368e2ed4bbdaccbfa5ebf610db4668ba2155d9
data/.cane ADDED
@@ -0,0 +1,4 @@
1
+ --abc-max 10
2
+ --gte coverage/covered_percent,100
3
+ --no-style
4
+ --color
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ spec/dummy/log
19
+ spec/dummy/db/*.sqlite3
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --profile
3
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rails-prg.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Tom Meier
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,44 @@
1
+ # Rails::Prg
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rails-prg'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rails-prg
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( http://github.com/<my-github-username>/rails-prg/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
30
+
31
+
32
+ ## Note how to generate dummy rails app
33
+
34
+ * Command for dummy rails app
35
+ * Scaffolding request objects:
36
+ * `rails generate scaffold ExamplePrg subject:text:uniq body:text published:boolean`
37
+ * `rails generate scaffold ErrorDuplicator subject:text:uniq body:text published:boolean`
38
+
39
+ ## TODO
40
+ * Write up README
41
+ * Add steps to install chromedriver to readme
42
+ * When Open sourced:
43
+ * Add Travis-CI
44
+ * use sauce labs 'Open Sauce' to check in multiple browsers for result and remove 'selenium_display' (or only enable for manual local run, run script/ci for travis, script/spec for local)
@@ -0,0 +1,38 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ require 'cane/rake_task'
5
+
6
+ Dir.glob("lib/tasks/*.rake").all? do |rake_file|
7
+ load(rake_file)
8
+ end
9
+
10
+ RSpec::Core::RakeTask.new(:spec)
11
+
12
+ namespace :spec do
13
+ desc "Run all unit specs"
14
+ RSpec::Core::RakeTask.new(:unit) do |t|
15
+ t.pattern = "spec/**/*_spec.rb"
16
+ t.rspec_opts = <<-SPEC_OPTS \
17
+ --require spec_helper \
18
+ --format progress \
19
+ --tag ~capybara_feature \
20
+ --colour
21
+ SPEC_OPTS
22
+ end
23
+
24
+ desc "Run all feature specs"
25
+ RSpec::Core::RakeTask.new(:features) do |t|
26
+ t.pattern = "spec/**/*_spec.rb"
27
+ t.rspec_opts = <<-SPEC_OPTS \
28
+ --require spec_helper \
29
+ --format documentation \
30
+ --tag capybara_feature \
31
+ --colour
32
+ SPEC_OPTS
33
+ end
34
+ end
35
+
36
+ task :default => :spec
37
+
38
+
@@ -0,0 +1,5 @@
1
+ require "rails/prg/version"
2
+ require "rails/prg"
3
+
4
+
5
+
@@ -0,0 +1,8 @@
1
+ require "rails/prg/version"
2
+ require "rails/prg/railtie"
3
+
4
+ module Rails
5
+ module Prg
6
+ autoload :RedirectedObjectController, 'rails/prg/redirected_object_controller'
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ require 'rails/railtie'
2
+
3
+ module Rails
4
+ module Prg
5
+ class Railtie < Rails::Railtie
6
+ initializer "rails-prg.action_controller" do
7
+ ActiveSupport.on_load(:action_controller) do
8
+ include Rails::Prg::RedirectedObjectController
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,84 @@
1
+ module Rails
2
+ # Post-Redirect-Get
3
+ module Prg
4
+ # Allow full POST-REDIRECT-GET pattern, instead of rendering an error, on change of object
5
+ # redirect back and load errors on to object. This prevents issues with a fully
6
+ # secure browser environment (no-cache, no-store), when the user clicks back
7
+ # Note: The filter *must* be loaded after the object instance is loaded for dynamic
8
+ # lookup without having to find it again.
9
+ # eg:
10
+ # class ObjectController
11
+ # before_filter :find_object, only: [:edit,:update]
12
+ # before_filter :load_redirected_objects!, only: [:edit]
13
+ # def update
14
+ # if errors;
15
+ # set_redirected_object!('@object', @object, clean_params)
16
+ # redirect_to edit_object_path(@object)
17
+ module RedirectedObjectController
18
+ extend ActiveSupport::Concern
19
+
20
+ # Load any redirected objects present in flash
21
+ # Loaded on any view where an error redirect has occured
22
+ def load_redirected_objects!
23
+ if flash[:redirected_objects]
24
+ flash[:redirected_objects].each do |instance_reference, attributes|
25
+ object_instance = instance_variable_get(instance_reference)
26
+ # Apply errors to instance
27
+ set_errors_to_redirected_instance(object_instance, attributes[:errors])
28
+ # Apply any params (ie: changed form fields to be corrected)
29
+ set_params_to_redirected_instance(object_instance, attributes[:params])
30
+ end
31
+ end
32
+ ensure
33
+ flash.delete(:redirected_objects)
34
+ end
35
+
36
+ # Allow Post-Redirect-Get on errors & submitted details
37
+ # passing details to redirected page for display
38
+ def set_redirected_object!(instance_reference, instance, instance_params)
39
+ ensure_redirected_params_are_safe!(instance_params)
40
+
41
+ flash[:redirected_objects] ||= {}
42
+ flash[:redirected_objects][instance_reference] = {
43
+ errors: instance.errors.messages,
44
+ params: instance_params
45
+ }
46
+ end
47
+
48
+ private
49
+
50
+ # Compare passed params for redirected object
51
+ # - raise error if not strong parameters or not marked as safe
52
+ def ensure_redirected_params_are_safe!(passed_params)
53
+ unless passed_params.is_a?(ActionController::Parameters) && passed_params.permitted?
54
+ error_message = if passed_params.is_a?(ActionController::Parameters)
55
+ unsafe_parameters = passed_params.send(:unpermitted_keys, params)
56
+ "[Rails::Prg] Error - Must use permitted strong parameters. Unsafe: #{unsafe_parameters.join(', ')}"
57
+ else
58
+ "[Rails::Prg] Error - Must pass strong parameters."
59
+ end
60
+ raise error_message
61
+ end
62
+ end
63
+
64
+ # Assign any errors to redirected instance
65
+ def set_errors_to_redirected_instance(instance, error_hash = {})
66
+ error_hash.each do |attribute, errors|
67
+ errors.each do |error_for_attribute|
68
+ instance.errors.add(attribute, error_for_attribute)
69
+ end
70
+ end
71
+ end
72
+
73
+ # Assign any provided params to redirected instance
74
+ # - Only clean params should be passed through
75
+ def set_params_to_redirected_instance(instance, instance_params)
76
+ ensure_redirected_params_are_safe!(instance_params)
77
+
78
+ instance_params.each do |attribute, value|
79
+ instance.public_send("#{attribute}=", value)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,5 @@
1
+ module Rails
2
+ module Prg
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ if defined? RSpec
2
+ namespace :spec do
3
+ begin
4
+ require 'cane/rake_task'
5
+
6
+ desc "Run cane to check quality metrics"
7
+ Cane::RakeTask.new(:quality) do |cane|
8
+ cane.canefile = ".cane"
9
+ cane.add_threshold 'coverage/covered_percent', :>=, 100
10
+ end
11
+ rescue LoadError
12
+ warn "cane not available, quality task not provided."
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,43 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "rails/prg/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rails-prg"
8
+ spec.version = Rails::Prg::VERSION
9
+ spec.authors = ["Tom Meier"]
10
+ spec.email = ["tom@venombytes.com"]
11
+ spec.summary = %q{Allow Rails to use full POST-REDIRECT-GET pattern on errors.}
12
+ spec.description = %q{
13
+ Secure applications must not use browser history or cache, this can cause problems
14
+ with some browsers when following standard Rails pattern for POST -> Error -> Render -> Success -> Redirect.
15
+ For full protection from ERR_CACHE_MISS (in Chrome with no-cache, no-store),
16
+ Rails should redirect on errors as well as on success,
17
+ always following full POST-REDIRECT-GET pattern.
18
+ This way the browser will always have a consistent back-button history to traverse without
19
+ triggering browser errors unable to display form submission pages.
20
+ }
21
+ spec.homepage = "https://github.com/tommeier/rails-prg"
22
+ spec.license = "MIT"
23
+
24
+ spec.files = `git ls-files`.split($/)
25
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
26
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_dependency "actionpack"
30
+ spec.add_dependency "railties"
31
+
32
+ spec.add_development_dependency "activerecord"
33
+ spec.add_development_dependency "bundler", "~> 1.5"
34
+ spec.add_development_dependency "cane"
35
+ spec.add_development_dependency "capybara"
36
+ spec.add_development_dependency "database_cleaner"
37
+ spec.add_development_dependency "rake"
38
+ spec.add_development_dependency "rspec-rails"
39
+ spec.add_development_dependency "selenium-webdriver"
40
+ spec.add_development_dependency "simplecov"
41
+ spec.add_development_dependency "sqlite3"
42
+ spec.add_development_dependency "sprockets-rails"
43
+ end
@@ -0,0 +1,22 @@
1
+ #!/bin/sh -xe
2
+
3
+ # Install packages.
4
+ bundle --quiet --binstubs
5
+
6
+ DUMMY_APP_PATH="spec/dummy"
7
+
8
+ # Prep dummy app db
9
+ pushd "$DUMMY_APP_PATH"
10
+ rake db:drop db:setup
11
+ rake db:test:load
12
+ popd
13
+
14
+ rm -rf coverage
15
+
16
+ # Enable to check spec coverage - only 'elses' should be uncovered
17
+ export CHECK_SPEC_COVERAGE=${CHECK_SPEC_COVERAGE:-false}
18
+
19
+ COVERAGE_GROUP="unit-tests" bin/rake "spec:unit"
20
+ COVERAGE_GROUP="firefox-features" BROWSER=firefox bin/rake "spec:features"
21
+ COVERAGE_GROUP="chrome-features" BROWSER=chrome bin/rake "spec:features"
22
+ bin/rake "spec:quality"
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Dummy::Application.load_tasks
File without changes
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */