parameter_filter 1.0.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.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in activerecord-parameter_filter.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Alex McHale
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,43 @@
1
+ parameter_filter
2
+ ================
3
+
4
+ Summary
5
+ -------
6
+
7
+ ParameterFilter is a module to mix into ActionController subclasses. It inserts
8
+ a before_filter which will automatically remove any fields in params that are
9
+ not explicitly allowed.
10
+
11
+ Installation
12
+ ------------
13
+
14
+ Include the following in your Gemfile:
15
+
16
+ gem "parameter_filter"
17
+
18
+ Usage
19
+ -----
20
+
21
+ For global security, include the following in your ApplicationController:
22
+
23
+ include ParameterFilter
24
+
25
+ Then, inside each of you controllers, specify what fields you want each action
26
+ to receive:
27
+
28
+ # Accept user[email] and user[password] on the create and update actions.
29
+ accepts :fields => { :user => [ :email, :password ] }, :on => [ :create, :update ]
30
+
31
+ # Accept user[email] and user[password] on all actions.
32
+ accepts fields: { user: %w( email password ) }
33
+
34
+ # Accept q on the search action.
35
+ accepts field: "q", on: "search"
36
+
37
+ # Accept q and sort on the search and index actions.
38
+ accepts fields: [ :q, :sort ], on: %w( search index )
39
+
40
+ ParameterFilter should be pretty flexible in what you throw at it.
41
+
42
+ NOTE: All actions are automatically allowed to receive :controller, :action and
43
+ :id.
@@ -0,0 +1,9 @@
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
@@ -0,0 +1,98 @@
1
+ require "parameter_filter/version"
2
+
3
+ # When a controller has ParameterFilter included, it will by default remove
4
+ # everything from params. The way to receive parameters is to specifically
5
+ # allow them with accept_fields.
6
+
7
+ module ParameterFilter
8
+
9
+ module ClassMethods
10
+
11
+ def accept_fields_parser fields
12
+ table = {}
13
+
14
+ [fields].flatten.compact.uniq.each do |field|
15
+ case field
16
+
17
+ when Symbol, String
18
+ table[field.to_s] = {}
19
+
20
+ when Hash
21
+ field.each do |key, value|
22
+ table[key.to_s] = accept_fields_parser value
23
+ end
24
+
25
+ end
26
+ end
27
+
28
+ table
29
+ end
30
+
31
+ def accepts options = {}
32
+ @_accepted_fields ||= { nil => { "controller" => {}, "action" => {}, "id" => {} } }
33
+ fields = options[:fields] || options[:field] || {}
34
+
35
+ case options[:on]
36
+ when Array
37
+ options[:on].each do |k|
38
+ @_accepted_fields[k.to_s] = accept_fields_parser fields
39
+ end
40
+
41
+ when Symbol, String
42
+ @_accepted_fields[options[:on].to_s] = accept_fields_parser fields
43
+
44
+ else
45
+ @_accepted_fields[nil] ||= {}
46
+ @_accepted_fields[nil].merge! accept_fields_parser fields
47
+
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ module InstanceMethods
54
+
55
+ def remove_filtered_parameters accepted_fields = nil, parameters = nil
56
+ if !accepted_fields && !parameters
57
+ accepted_fields = self.class.instance_variable_get("@_accepted_fields") || {}
58
+ fields = (accepted_fields[nil] || {}).merge(accepted_fields[self.action_name] || {})
59
+ remove_filtered_parameters fields, self.params
60
+ elsif parameters
61
+ accepted_keys = ParameterFilter.field_keys accepted_fields
62
+ accepted_keys += [ :controller, :action, :id ] if parameters == params
63
+ parameters.slice! *accepted_keys
64
+
65
+ ParameterFilter.each_field accepted_fields do |k, v|
66
+ remove_filtered_parameters v, parameters[k] if parameters[k].kind_of? Hash
67
+ end
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ def self.each_field fields
74
+ [ fields ].flatten.compact.uniq.each do |f|
75
+ case f
76
+ when Hash then f.each { |k, v| yield k, v }
77
+ when String, Symbol then yield f
78
+ end
79
+ end
80
+ end
81
+
82
+ def self.field_keys fields
83
+ fields.map do |field|
84
+ case field
85
+ when Array then field_keys field
86
+ when Hash then field.keys
87
+ else field
88
+ end
89
+ end.flatten.compact.uniq
90
+ end
91
+
92
+ def self.included base
93
+ base.send :extend, ClassMethods
94
+ base.send :include, InstanceMethods
95
+ base.send :before_filter, :remove_filtered_parameters
96
+ end
97
+
98
+ end
@@ -0,0 +1,5 @@
1
+ module Activerecord
2
+ module ParameterFilter
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "parameter_filter/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "parameter_filter"
7
+ s.version = Activerecord::ParameterFilter::VERSION
8
+ s.authors = ["Alex McHale"]
9
+ s.email = ["alex@anticlever.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{A gem to easily filter out unwanted parameters in ActionController.}
12
+ s.description = %q{A gem to easily filter out unwanted parameters in ActionController.}
13
+
14
+ s.rubyforge_project = "parameter_filter"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ end
@@ -0,0 +1,57 @@
1
+ require "test_helper"
2
+
3
+ class ParamterFilterTest < MiniTest::Unit::TestCase
4
+
5
+ def test_class_with_parameter_filter
6
+ klass = Class.new
7
+ klass.expects(:before_filter).with(:remove_filtered_parameters).once
8
+ klass.send :include, ParameterFilter
9
+ end
10
+
11
+ def test_allowing_core_parameters
12
+ controller = self.filtered_controller
13
+ controller.params = { controller: "users", action: "index", id: 123 }
14
+ controller.remove_filtered_parameters
15
+ assert_equal [ :controller, :action, :id ], controller.params.keys
16
+ end
17
+
18
+ def test_removing_noncore_parameters
19
+ controller = self.filtered_controller
20
+ controller.params = { foo: 999 }
21
+ assert_equal 999, controller.params[:foo]
22
+ controller.remove_filtered_parameters
23
+ assert_equal nil, controller.params[:foo]
24
+ end
25
+
26
+ def test_allowing_nested_fields
27
+ controller = self.filtered_controller fields: { user: "email" }
28
+ controller.params = { "user" => { "email" => "joe@example.com" } }
29
+ assert_equal "joe@example.com", controller.params["user"]["email"]
30
+ controller.remove_filtered_parameters
31
+ assert_equal "joe@example.com", controller.params["user"]["email"]
32
+ end
33
+
34
+ def test_removing_nested_fields
35
+ controller = self.filtered_controller
36
+ controller.params = { "user" => { "email" => "joe@example.com" } }
37
+ assert_equal "joe@example.com", controller.params["user"]["email"]
38
+ controller.remove_filtered_parameters
39
+ assert_equal nil, controller.params["user"]
40
+ end
41
+
42
+ protected
43
+
44
+ def filtered_controller options = {}
45
+ klass = Class.new
46
+ klass.stubs :before_filter
47
+ klass.send :include, ParameterFilter
48
+ klass.send :accepts, options
49
+
50
+ klass.new.tap do |controller|
51
+ def controller.action_name; "index"; end
52
+ def controller.params; @params ||= {}; end
53
+ def controller.params= p; @params = p; end
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,39 @@
1
+ require "parameter_filter"
2
+ require "minitest/autorun"
3
+ require "minitest/mock"
4
+ require "turn/autorun"
5
+ require "mocha"
6
+
7
+ # Taken from Rails for testing purposes, as they're the what the entire gem leans.
8
+ class Hash
9
+ # Slice a hash to include only the given keys. This is useful for
10
+ # limiting an options hash to valid keys before passing to a method:
11
+ #
12
+ # def search(criteria = {})
13
+ # assert_valid_keys(:mass, :velocity, :time)
14
+ # end
15
+ #
16
+ # search(options.slice(:mass, :velocity, :time))
17
+ #
18
+ # If you have an array of keys you want to limit to, you should splat them:
19
+ #
20
+ # valid_keys = [:mass, :velocity, :time]
21
+ # search(options.slice(*valid_keys))
22
+ def slice(*keys)
23
+ keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
24
+ hash = self.class.new
25
+ keys.each { |k| hash[k] = self[k] if has_key?(k) }
26
+ hash
27
+ end
28
+
29
+ # Replaces the hash with only the given keys.
30
+ # Returns a hash contained the removed key/value pairs
31
+ # {:a => 1, :b => 2, :c => 3, :d => 4}.slice!(:a, :b) # => {:c => 3, :d => 4}
32
+ def slice!(*keys)
33
+ keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
34
+ omit = slice(*self.keys - keys)
35
+ hash = slice(*keys)
36
+ replace(hash)
37
+ omit
38
+ end
39
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: parameter_filter
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alex McHale
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-26 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A gem to easily filter out unwanted parameters in ActionController.
15
+ email:
16
+ - alex@anticlever.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - LICENSE
24
+ - README.markdown
25
+ - Rakefile
26
+ - lib/parameter_filter.rb
27
+ - lib/parameter_filter/version.rb
28
+ - parameter_filter.gemspec
29
+ - test/parameter_filter_test.rb
30
+ - test/test_helper.rb
31
+ homepage: ''
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project: parameter_filter
51
+ rubygems_version: 1.8.11
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: A gem to easily filter out unwanted parameters in ActionController.
55
+ test_files:
56
+ - test/parameter_filter_test.rb
57
+ - test/test_helper.rb