params_patrol 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9e285483550dc61d2224a801aac09e09e0411385
4
+ data.tar.gz: 9bf6dfd7f0793f5def7830fc0f02356609945c8e
5
+ SHA512:
6
+ metadata.gz: 291b813c7bfe13105baffc0703c7dbf68abc069e28e99de384f83e8e8d531b4de30386f192d7fca846aaa4b348f851583fa4c96f73b90bb3c359f01ea93be080
7
+ data.tar.gz: 24a4a63489cf47edef6e146a9136c21a77b35ba1ef39de76838d0ded51c49be6f8a5dc6db5f8525ba845ca54003db4f053d8c3cc21f6f211fd4e50b255218780
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .idea
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ params-patrol
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.1.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in params_patrol.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Will Bendix
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.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # Params Patrol
2
+
3
+ ![Call for backup!](http://www.security-guard.ca/wp-content/uploads/2015/01/security-guard-patrol-service.jpg)
4
+
5
+ Keeps an eye out for suspicious parameters... and then calls for backup
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'params_patrol'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install params_patrol
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Contributing
28
+
29
+ 1. Fork it ( https://github.com/IndieGoGo/params_patrol/fork )
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'lib'
6
+ t.libs << 'test'
7
+ t.pattern = 'test/**/*_test.rb'
8
+ t.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,39 @@
1
+ module ActionController
2
+ class DecoratesParameters
3
+ attr_reader :params
4
+
5
+ methods_to_delegate = (ActionController::Parameters.new.methods - Object.new.methods - [:permit, :[]]) + [:to_s, :is_a?, :kind_of?]
6
+ delegate *methods_to_delegate, :to => :params
7
+
8
+ def initialize(params)
9
+ @params = params
10
+ end
11
+
12
+ def [](key)
13
+ result = params[key]
14
+ result.is_a?(Hash) ? DecoratesParameters.new(result) : result
15
+ end
16
+
17
+ def require(key)
18
+ result = params[key].presence || raise(ActionController::ParameterMissing.new(key))
19
+ result.is_a?(Hash) ? DecoratesParameters.new(result) : result
20
+ end
21
+
22
+ def permit(*filters)
23
+ params.permit(*filters)
24
+ rescue => e
25
+ ParamsPatrol.handle(error: e, parameters: params, cgi_data: ENV.to_hash)
26
+ self
27
+ end
28
+ end
29
+
30
+ module HandleUnpermittedParameters
31
+ def params
32
+ @_params ||= DecoratesParameters.new(Parameters.new(request.parameters))
33
+ end
34
+
35
+ def params=(val)
36
+ @_params = val.is_a?(Hash) ? DecoratesParameters.new(Parameters.new(val)) : val
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveModel
2
+ module SuppressForbiddenAttributes
3
+ def sanitize_for_mass_assignment(*options)
4
+ new_attributes = options.first
5
+ if new_attributes.respond_to?(:permitted?) && !new_attributes.permitted?
6
+ ParamsPatrol.handle(error: ActiveModel::ForbiddenAttributes.new,
7
+ parameters: options.try(:first),
8
+ cgi_data: ENV.to_hash)
9
+ # help surface these kinds of issues in the test env
10
+ # raise(ActiveModel::ForbiddenAttributes) if Rails.env.test?
11
+ end
12
+
13
+ ActiveModel::MassAssignmentSecurity.instance_method(:sanitize_for_mass_assignment).bind(self).call(*options)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ require "active_model/suppress_forbidden_attributes"
2
+ require "action_controller/handle_unpermitted_parameters"
3
+ require "params_patrol/version"
4
+
5
+ module ParamsPatrol
6
+ def self.handler
7
+ @handler
8
+ end
9
+
10
+ def self.handler=(handler)
11
+ @handler = handler
12
+ end
13
+
14
+ def self.handle(*options)
15
+ if @handler.nil?
16
+ @handler = lambda { |x| Logger.new(STDOUT).info(x) }
17
+ end
18
+ @handler.call(options)
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module ParamsPatrol
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'params_patrol/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "params_patrol"
8
+ spec.version = ParamsPatrol::VERSION
9
+ spec.authors = ["Will Bendix", "Blaine Gilbreth"]
10
+ spec.email = %w(wcbendix@gmail.com bgilb@seas.upenn.edu)
11
+ spec.summary = %q{Keeps an eye out for suspicious parameters... and then calls for backup}
12
+ spec.description = %q{Use whatever monitor service you would like to track strong parameter errors.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport", "~> 3.0"
22
+ spec.add_dependency "actionpack", "~> 3.0"
23
+ spec.add_dependency "activemodel", "~> 3.0"
24
+ spec.add_dependency "railties", "~> 3.0"
25
+ spec.add_dependency "strong_parameters"
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.7"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "mocha"
30
+ end
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+
3
+ class UsersController < ActionController::Base
4
+ include ActionController::HandleUnpermittedParameters
5
+
6
+ def create
7
+ params.permit(:user)
8
+ head :ok
9
+ end
10
+ end
11
+
12
+ class ActionControllerHandleUnpermittedParamsTest < ActionController::TestCase
13
+ tests UsersController
14
+
15
+ def setup
16
+ @log = StringIO.new
17
+ ParamsPatrol.handler= lambda { |x| Logger.new(@log).info(x) }
18
+ end
19
+
20
+ test 'missing required parameters will not raise an exception' do
21
+ post :create, { fishing: true }
22
+ assert_response :ok
23
+ end
24
+
25
+ test 'missing required parameters will log' do
26
+ post :create, { fishing: true }
27
+ @log.rewind
28
+ assert_block do
29
+ /ActionController::UnpermittedParameters/.match(@log.read)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ require 'test_helper'
2
+
3
+ class Person
4
+ include ActiveModel::MassAssignmentSecurity
5
+ include ActiveModel::SuppressForbiddenAttributes
6
+
7
+ public :sanitize_for_mass_assignment
8
+ end
9
+
10
+ class ActiveModelSuppressForbiddenAttributesTest < ActiveSupport::TestCase
11
+ def setup
12
+ @log = StringIO.new
13
+ ParamsPatrol.handler= lambda { |x| Logger.new(@log).info(x) }
14
+ end
15
+
16
+ test 'forbidden attributes are logged' do
17
+ Person.new.sanitize_for_mass_assignment(ActionController::Parameters.new(a: 'b'))
18
+ @log.rewind
19
+ assert_block do
20
+ /ActiveModel::ForbiddenAttributes/.match(@log.read)
21
+ end
22
+ end
23
+
24
+ test 'no error is thrown' do
25
+ assert_nothing_thrown do
26
+ Person.new.sanitize_for_mass_assignment(ActionController::Parameters.new(a: 'b'))
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ class DecoratesParamsActuallyLogsOnUnpermittedParamsTest < ActiveSupport::TestCase
4
+ def setup
5
+ ActionController::Parameters.action_on_unpermitted_parameters = :raise
6
+ end
7
+
8
+ def teardown
9
+ ActionController::Parameters.action_on_unpermitted_parameters = false
10
+ end
11
+
12
+ test 'does not raise on unexpected params and returns the params object' do
13
+ params = ActionController::DecoratesParameters.new(ActionController::Parameters.new({
14
+ :book => { :pages => 65 },
15
+ :fishing => 'Turnips'
16
+ }))
17
+
18
+ ParamsPatrol.expects(:handle)
19
+ result = params.permit(:book => [:pages])
20
+ assert_equal(params, result)
21
+ end
22
+
23
+ test 'does not raise on unexpected params after a require and returns the params object' do
24
+ params = ActionController::DecoratesParameters.new(ActionController::Parameters.new({
25
+ :book => { :pages => 65, :fishing => 'Turnips' },
26
+ }))
27
+
28
+ ParamsPatrol.expects(:handle)
29
+ result = params.require(:book).permit(:pages)
30
+ assert_equal(params[:book].to_s, result.to_s)
31
+ end
32
+
33
+ test 'does not raise on unexpected params after fetching a sub hash by key and returns the sub hash object' do
34
+ params = ActionController::DecoratesParameters.new(ActionController::Parameters.new({
35
+ :book => { :pages => 65, :fishing => 'Turnips' },
36
+ }))
37
+
38
+ ParamsPatrol.expects(:handle)
39
+ result = params[:book].permit(:pages)
40
+ assert_equal(params[:book].to_s, result.to_s)
41
+ end
42
+
43
+ test 'does not raise on unexpected nested params' do
44
+ params = ActionController::DecoratesParameters.new(ActionController::Parameters.new({
45
+ :book => { :pages => 65, :title => 'Green Cats and where to find then.' }
46
+ }))
47
+
48
+ ParamsPatrol.expects(:handle)
49
+ params.permit(:book => [:pages])
50
+ end
51
+ end
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ class DecoratesParametersTest < ActiveSupport::TestCase
4
+
5
+ def params
6
+ ActionController::DecoratesParameters.new(
7
+ ActionController::Parameters.new(
8
+ {
9
+ :book => { :pages => 65 },
10
+ :fishing => 'Turnips'
11
+ }
12
+ )
13
+ )
14
+ end
15
+
16
+ test 'is_a? masquerades as a Hash or HashWithIndifferentAccess' do
17
+ assert(params.is_a?(HashWithIndifferentAccess), 'not is_a? HashWithIndifferentAccess')
18
+ assert(params.is_a?(Hash), 'not is_a? Hash')
19
+ end
20
+
21
+ test 'kind_of? masquerades as a Hash or HashWithIndifferentAccess' do
22
+ assert(params.kind_of?(HashWithIndifferentAccess), 'not kind_of? HashWithIndifferentAccess')
23
+ assert(params.kind_of?(Hash), 'not kind_of? Hash')
24
+ end
25
+
26
+ test 'require returns a string or another Decorates parameters object' do
27
+ assert_equal(params.require(:book).class, ActionController::DecoratesParameters)
28
+ assert_equal(params.require(:fishing).class, String)
29
+ end
30
+ end
@@ -0,0 +1,16 @@
1
+ require 'test_helper'
2
+
3
+ class ParamsPatrolTest < Test::Unit::TestCase
4
+ def test_handler=
5
+ logger = lambda { |x| Logger.new(StringIO.new).info(x) }
6
+ ParamsPatrol.handler = logger
7
+ assert_equal(logger, ParamsPatrol.handler)
8
+ end
9
+
10
+ def test_handle
11
+ logger = lambda { |x| Logger.new(StringIO.new).info(x) }
12
+ ParamsPatrol.handler = logger
13
+ logger.expects(:call)
14
+ ParamsPatrol.handle('unpermitted params!')
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ # Configure Rails Environment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require 'test/unit'
5
+ require 'rails'
6
+
7
+ class FakeApplication < Rails::Application; end
8
+
9
+ Rails.application = FakeApplication
10
+ Rails.configuration.action_controller = ActiveSupport::OrderedOptions.new
11
+
12
+ require 'strong_parameters'
13
+ require 'params_patrol'
14
+
15
+ module ActionController
16
+ SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
17
+ SharedTestRoutes.draw do
18
+ match ':controller(/:action)'
19
+ end
20
+
21
+ class Base
22
+ include ActionController::Testing
23
+ include SharedTestRoutes.url_helpers
24
+ end
25
+
26
+ class ActionController::TestCase
27
+ setup do
28
+ @routes = SharedTestRoutes
29
+ end
30
+ end
31
+ end
32
+
33
+ ActionController::Parameters.action_on_unpermitted_parameters = :raise
34
+
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: params_patrol
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Will Bendix
8
+ - Blaine Gilbreth
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-04-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '3.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '3.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: actionpack
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '3.0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '3.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: activemodel
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '3.0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '3.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: railties
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: strong_parameters
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: bundler
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '1.7'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '1.7'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rake
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '10.0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '10.0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: mocha
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: Use whatever monitor service you would like to track strong parameter
127
+ errors.
128
+ email:
129
+ - wcbendix@gmail.com
130
+ - bgilb@seas.upenn.edu
131
+ executables: []
132
+ extensions: []
133
+ extra_rdoc_files: []
134
+ files:
135
+ - ".gitignore"
136
+ - ".ruby-gemset"
137
+ - ".ruby-version"
138
+ - Gemfile
139
+ - LICENSE.txt
140
+ - README.md
141
+ - Rakefile
142
+ - lib/action_controller/handle_unpermitted_parameters.rb
143
+ - lib/active_model/suppress_forbidden_attributes.rb
144
+ - lib/params_patrol.rb
145
+ - lib/params_patrol/version.rb
146
+ - params_patrol.gemspec
147
+ - test/action_controller_handle_unpermitted_parameters_test.rb
148
+ - test/active_model_suppress_forbidden_attributes_test.rb
149
+ - test/decorates_parameters_logging_test.rb
150
+ - test/decorates_parameters_test.rb
151
+ - test/params_patrol_test.rb
152
+ - test/test_helper.rb
153
+ homepage: ''
154
+ licenses:
155
+ - MIT
156
+ metadata: {}
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubyforge_project:
173
+ rubygems_version: 2.2.2
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: Keeps an eye out for suspicious parameters... and then calls for backup
177
+ test_files:
178
+ - test/action_controller_handle_unpermitted_parameters_test.rb
179
+ - test/active_model_suppress_forbidden_attributes_test.rb
180
+ - test/decorates_parameters_logging_test.rb
181
+ - test/decorates_parameters_test.rb
182
+ - test/params_patrol_test.rb
183
+ - test/test_helper.rb