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 CHANGED
@@ -1,7 +1,7 @@
1
- = Summary
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
- = Installation
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
- = Usage
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
- = Examples
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
- == Whitelisting
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
- == Nested Params
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
- = How does it work?
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
- = Author
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
@@ -22,6 +22,7 @@ task :default => :test
22
22
  desc 'Test the param_protected plugin.'
23
23
  Rake::TestTask.new(:test) do |t|
24
24
  t.libs << 'lib'
25
+ t.libs << 'test'
25
26
  t.pattern = 'test/**/*_test.rb'
26
27
  t.verbose = true
27
28
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
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
- @protections.each do |protected_params, actions, exclusivity|
25
- scope, actions = actions.first, actions[1..-1] # Careful not to modify the actions array in place.
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,
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
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.1.0"
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{2009-09-12}
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.2}
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,4 @@
1
+ class InheritedUsersController < UsersController
2
+ param_accessible :user => :password
3
+ param_protected :user => :name
4
+ end
@@ -0,0 +1,11 @@
1
+ class MergeController < ApplicationController
2
+ param_accessible :a, :only => :first
3
+ param_accessible :b
4
+ param_accessible({ :h => :c}, :except => :first)
5
+ param_accessible :h => :b
6
+
7
+
8
+ def first; end
9
+
10
+ def second; end
11
+ end
@@ -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.1.0
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: 2009-12-04 00:00:00 -06:00
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