param_protected 1.1.0 → 1.2.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.
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