param_protected 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +25 -11
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/param_protected/controller_modifications.rb +11 -0
- data/lib/param_protected/protector.rb +40 -4
- data/param_protected.gemspec +14 -6
- data/test/app_root/app/controllers/inherited_users_controller.rb +4 -0
- data/test/app_root/app/controllers/merge_controller.rb +11 -0
- data/test/inherited_users_controller_test.rb +24 -0
- data/test/merge_controller_test.rb +15 -0
- metadata +10 -2
data/README.rdoc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
|
1
|
+
=== Summary
|
2
2
|
This plugin provides two class methods on <tt>ActiveController::Base</tt> that filter the <tt>params</tt> hash for that controller's actions. You can think of them as the controller analog of <tt>attr_protected</tt> and <tt>attr_accessible</tt>.
|
3
3
|
|
4
|
-
|
4
|
+
=== Installation
|
5
5
|
|
6
6
|
Put in your <tt>environment.rb</tt> file...
|
7
7
|
|
@@ -9,7 +9,7 @@ Put in your <tt>environment.rb</tt> file...
|
|
9
9
|
|
10
10
|
Alternatively, just install the gem from the command line and <tt>require "param_protected"</tt> somewhere in your project.
|
11
11
|
|
12
|
-
|
12
|
+
=== Usage
|
13
13
|
class YourController < ActiveController::Base
|
14
14
|
param_protected <param_name> <options>
|
15
15
|
param_accessible <param_name> <options>
|
@@ -20,30 +20,44 @@ Alternatively, just install the gem from the command line and <tt>require "param
|
|
20
20
|
|
21
21
|
<tt>options</tt> is a Hash that has <em>one</em> of two keys: <tt>:only</tt> or <tt>:except</tt>. The value for these keys is a String, Symbol, or Array of Strings and/or Symbols which denotes to the action(s) for which params to protect.
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
== Blacklisting
|
23
|
+
=== Blacklisting
|
26
24
|
Any of these combinations should work.
|
27
25
|
param_protected :client_id
|
28
26
|
param_protected [:client_id, :user_id]
|
29
27
|
param_protected :client_id, :only => 'my_action'
|
30
28
|
param_protected :client_id, :except => [:your_action, :my_action]
|
31
29
|
|
32
|
-
|
30
|
+
=== Whitelisting
|
33
31
|
Any of these combinations should work.
|
34
32
|
param_accessible :client_id
|
35
33
|
param_accessible :[:client_id, :user_id]
|
36
34
|
param_accessible :client_id, :only => 'my_action'
|
37
35
|
param_accessible :client_id, :except => [:your_action, :my_action]
|
38
36
|
|
39
|
-
|
37
|
+
=== Nested Params
|
40
38
|
You can use combinations of arrays and hashes to specify nested params, much the same way <tt>ActiveRecord::Base#find</tt>'s
|
41
39
|
<tt>:include</tt> argument works.
|
42
40
|
param_accessible [:account_name, { :user => [:first_name, :last_name, :address => [:street, :city, :state]] }]
|
43
41
|
param_protected [:id, :password, { :user => [:id, :password] }]
|
44
42
|
|
45
|
-
|
43
|
+
=== Merging
|
44
|
+
If you call <tt>param_protected</tt> or <tt>param_accessible</tt> multiple times for an action or actions, then the protections will be merged. For example...
|
45
|
+
param_protected [:id, :user], :only => :some_action
|
46
|
+
param_protected [{ :user => [:first, :last] }, :password], :only => :some_action
|
47
|
+
Is equivalent to saying...
|
48
|
+
param_protected [:id, { :user => [:first, :last] }, :password], :only => :some_action
|
49
|
+
Credit: Moritz Heidkamp
|
50
|
+
|
51
|
+
=== Inheritance
|
52
|
+
Param protections will be inherited to derived controllers.
|
53
|
+
|
54
|
+
Credit: Moritz Heidkamp
|
55
|
+
|
56
|
+
=== How does it work?
|
46
57
|
It does an <tt>alias_method_chain</tt> on <tt>ActionController::Base#params</tt> that filters (and caches) the params. You can get the unfiltered, pristine params by calling <tt>ActionController::Base#params_without_protection</tt>.
|
47
58
|
|
48
|
-
|
49
|
-
Christopher J. Bottaro
|
59
|
+
=== Author
|
60
|
+
Christopher J. Bottaro - {cjbottaro}[http://github.com/cjbottaro]
|
61
|
+
|
62
|
+
=== Contributors
|
63
|
+
Moritz Heidkamp - {DerGuteMoritz}[http://github.com/DerGuteMoritz]
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.2.0
|
@@ -4,6 +4,7 @@ module ParamProtected
|
|
4
4
|
def self.extended(action_controller)
|
5
5
|
action_controller.class_eval do
|
6
6
|
extend ClassMethods
|
7
|
+
metaclass.alias_method_chain :inherited, :protector
|
7
8
|
include InstanceMethods
|
8
9
|
alias_method_chain :params, :protection
|
9
10
|
end
|
@@ -18,6 +19,16 @@ module ParamProtected
|
|
18
19
|
def param_accessible(params, actions = nil)
|
19
20
|
Protector.instance(self).declare_protection(params, actions, WHITELIST)
|
20
21
|
end
|
22
|
+
|
23
|
+
def inherited_with_protector(controller)
|
24
|
+
inherited_without_protector(controller)
|
25
|
+
|
26
|
+
if defined? @pp_protector
|
27
|
+
controller.instance_variable_set :@pp_protector, @pp_protector.dup
|
28
|
+
controller.class_eval { attr_reader :pp_protector }
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
21
32
|
|
22
33
|
end
|
23
34
|
|
@@ -12,6 +12,10 @@ module ParamProtected
|
|
12
12
|
def initialize
|
13
13
|
@protections = []
|
14
14
|
end
|
15
|
+
|
16
|
+
def initialize_copy(copy)
|
17
|
+
copy.instance_variable_set(:@protections, deep_copy(@protections))
|
18
|
+
end
|
15
19
|
|
16
20
|
def declare_protection(params, actions, exclusivity)
|
17
21
|
params = normalize_params(params)
|
@@ -21,15 +25,47 @@ module ParamProtected
|
|
21
25
|
|
22
26
|
def protect(controller_params, action_name)
|
23
27
|
returning(deep_copy(controller_params)) do |params|
|
24
|
-
|
25
|
-
|
26
|
-
next unless action_matches?(scope, actions, action_name)
|
27
|
-
filter_params(protected_params, params, exclusivity)
|
28
|
+
protections_for_action(action_name).each do |exclusivity, protected_params|
|
29
|
+
filter_params(protected_params, params, exclusivity) unless protected_params.empty?
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
34
|
private
|
35
|
+
|
36
|
+
def protections_for_action(action_name)
|
37
|
+
@protections_for_action ||= { }
|
38
|
+
|
39
|
+
@protections_for_action[action_name] ||= @protections.select do |protected_params, actions, exclusivity|
|
40
|
+
action_matches?(actions[0], actions[1..-1], action_name)
|
41
|
+
end.inject({ WHITELIST => { }, BLACKLIST => { } }) do |result, (protected_params, action_name, exclusivity)|
|
42
|
+
merge_protections(result[exclusivity], protected_params)
|
43
|
+
result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Merge protections for the same params into one so as to allow extension of them
|
48
|
+
# in inheriting controllers.
|
49
|
+
#
|
50
|
+
# Mutating the first argument is okay since this method is used within inject only.
|
51
|
+
#
|
52
|
+
# Example:
|
53
|
+
# merge_protections({ :foo => { :qux => nil }, :bar => { :baz => nil, :qux => nil } },
|
54
|
+
# { :foo => { :baz => nil, :qux => { :foo => nil } } })
|
55
|
+
# =>
|
56
|
+
#
|
57
|
+
# { :foo => { :baz => nil, :qux => { :foo => nil } }, :bar => { :baz =>nil, :qux => nil } }
|
58
|
+
def merge_protections(protections, protected_params)
|
59
|
+
protected_params.each do |k,v|
|
60
|
+
if protections[k].is_a?(Hash)
|
61
|
+
merge_protections(protections[k], v) if v
|
62
|
+
else
|
63
|
+
protections[k] = v
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
protections
|
68
|
+
end
|
33
69
|
|
34
70
|
# When specifying params to protect, we allow a combination of arrays and hashes much like how
|
35
71
|
# ActiveRecord::Base#find's :include options works. This method normalizes that into just nested hashes,
|
data/param_protected.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{param_protected}
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Christopher J. Bottaro"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-02-18}
|
13
13
|
s.description = %q{Provides two class methods on ActiveController::Base that filter the params hash for that controller's actions. You can think of them as the controller analog of attr_protected and attr_accessible.}
|
14
14
|
s.email = %q{cjbottaro@alumni.cs.utexas.edu}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -34,6 +34,8 @@ Gem::Specification.new do |s|
|
|
34
34
|
"test/app_root/app/controllers/accessible_except_controller.rb",
|
35
35
|
"test/app_root/app/controllers/accessible_only_controller.rb",
|
36
36
|
"test/app_root/app/controllers/application_controller.rb",
|
37
|
+
"test/app_root/app/controllers/inherited_users_controller.rb",
|
38
|
+
"test/app_root/app/controllers/merge_controller.rb",
|
37
39
|
"test/app_root/app/controllers/protected_controller.rb",
|
38
40
|
"test/app_root/app/controllers/users_controller.rb",
|
39
41
|
"test/app_root/config/boot.rb",
|
@@ -46,17 +48,18 @@ Gem::Specification.new do |s|
|
|
46
48
|
"test/app_root/config/environments/sqlite3.rb",
|
47
49
|
"test/app_root/config/routes.rb",
|
48
50
|
"test/app_root/lib/console_with_fixtures.rb",
|
51
|
+
"test/inherited_users_controller_test.rb",
|
52
|
+
"test/merge_controller_test.rb",
|
49
53
|
"test/protected_controller_test.rb",
|
50
54
|
"test/protector_test.rb",
|
51
55
|
"test/test_helper.rb",
|
52
56
|
"test/users_controller_test.rb",
|
53
57
|
"uninstall.rb"
|
54
58
|
]
|
55
|
-
s.has_rdoc = true
|
56
59
|
s.homepage = %q{http://github.com/cjbottaro/param_protected}
|
57
60
|
s.rdoc_options = ["--charset=UTF-8"]
|
58
61
|
s.require_paths = ["lib"]
|
59
|
-
s.rubygems_version = %q{1.3.
|
62
|
+
s.rubygems_version = %q{1.3.5}
|
60
63
|
s.summary = %q{Filter unwanted parameters in your controllers and actions.}
|
61
64
|
s.test_files = [
|
62
65
|
"test/accessible_except_test.rb",
|
@@ -64,6 +67,8 @@ Gem::Specification.new do |s|
|
|
64
67
|
"test/app_root/app/controllers/accessible_except_controller.rb",
|
65
68
|
"test/app_root/app/controllers/accessible_only_controller.rb",
|
66
69
|
"test/app_root/app/controllers/application_controller.rb",
|
70
|
+
"test/app_root/app/controllers/inherited_users_controller.rb",
|
71
|
+
"test/app_root/app/controllers/merge_controller.rb",
|
67
72
|
"test/app_root/app/controllers/protected_controller.rb",
|
68
73
|
"test/app_root/app/controllers/users_controller.rb",
|
69
74
|
"test/app_root/config/boot.rb",
|
@@ -75,6 +80,8 @@ Gem::Specification.new do |s|
|
|
75
80
|
"test/app_root/config/environments/sqlite3.rb",
|
76
81
|
"test/app_root/config/routes.rb",
|
77
82
|
"test/app_root/lib/console_with_fixtures.rb",
|
83
|
+
"test/inherited_users_controller_test.rb",
|
84
|
+
"test/merge_controller_test.rb",
|
78
85
|
"test/protected_controller_test.rb",
|
79
86
|
"test/protector_test.rb",
|
80
87
|
"test/test_helper.rb",
|
@@ -91,3 +98,4 @@ Gem::Specification.new do |s|
|
|
91
98
|
else
|
92
99
|
end
|
93
100
|
end
|
101
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class InheritedUsersControllerTest < ActionController::TestCase
|
4
|
+
|
5
|
+
PARAMS = { :user => { :id => 123,
|
6
|
+
:name => { :first => "chris", :middle => "james", :last => "bottaro"},
|
7
|
+
:email => "cjbottaro@blah.com",
|
8
|
+
:password => "SEcReT" },
|
9
|
+
:something => "something" }
|
10
|
+
|
11
|
+
EXPECTED_PARAMS = { "user" => { "email" => "cjbottaro@blah.com",
|
12
|
+
"password" => "SEcReT" } }
|
13
|
+
|
14
|
+
def test_create
|
15
|
+
get :create, PARAMS
|
16
|
+
assert_equal EXPECTED_PARAMS, params
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_update
|
20
|
+
get :update, PARAMS
|
21
|
+
assert_equal EXPECTED_PARAMS, params
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class MergeControllerTest < ActionController::TestCase
|
4
|
+
|
5
|
+
test_action :first do
|
6
|
+
assert_params %w[a b h]
|
7
|
+
assert_equal({"b" => "b"}, params["h"])
|
8
|
+
end
|
9
|
+
|
10
|
+
test_action :second do
|
11
|
+
assert_params %w[b h]
|
12
|
+
assert_equal({"b" => "b", "c" => "c"}, params["h"])
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: param_protected
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher J. Bottaro
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-02-18 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -40,6 +40,8 @@ files:
|
|
40
40
|
- test/app_root/app/controllers/accessible_except_controller.rb
|
41
41
|
- test/app_root/app/controllers/accessible_only_controller.rb
|
42
42
|
- test/app_root/app/controllers/application_controller.rb
|
43
|
+
- test/app_root/app/controllers/inherited_users_controller.rb
|
44
|
+
- test/app_root/app/controllers/merge_controller.rb
|
43
45
|
- test/app_root/app/controllers/protected_controller.rb
|
44
46
|
- test/app_root/app/controllers/users_controller.rb
|
45
47
|
- test/app_root/config/boot.rb
|
@@ -52,6 +54,8 @@ files:
|
|
52
54
|
- test/app_root/config/environments/sqlite3.rb
|
53
55
|
- test/app_root/config/routes.rb
|
54
56
|
- test/app_root/lib/console_with_fixtures.rb
|
57
|
+
- test/inherited_users_controller_test.rb
|
58
|
+
- test/merge_controller_test.rb
|
55
59
|
- test/protected_controller_test.rb
|
56
60
|
- test/protector_test.rb
|
57
61
|
- test/test_helper.rb
|
@@ -91,6 +95,8 @@ test_files:
|
|
91
95
|
- test/app_root/app/controllers/accessible_except_controller.rb
|
92
96
|
- test/app_root/app/controllers/accessible_only_controller.rb
|
93
97
|
- test/app_root/app/controllers/application_controller.rb
|
98
|
+
- test/app_root/app/controllers/inherited_users_controller.rb
|
99
|
+
- test/app_root/app/controllers/merge_controller.rb
|
94
100
|
- test/app_root/app/controllers/protected_controller.rb
|
95
101
|
- test/app_root/app/controllers/users_controller.rb
|
96
102
|
- test/app_root/config/boot.rb
|
@@ -102,6 +108,8 @@ test_files:
|
|
102
108
|
- test/app_root/config/environments/sqlite3.rb
|
103
109
|
- test/app_root/config/routes.rb
|
104
110
|
- test/app_root/lib/console_with_fixtures.rb
|
111
|
+
- test/inherited_users_controller_test.rb
|
112
|
+
- test/merge_controller_test.rb
|
105
113
|
- test/protected_controller_test.rb
|
106
114
|
- test/protector_test.rb
|
107
115
|
- test/test_helper.rb
|