protected_attributes 1.0.9 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/lib/active_model/mass_assignment_security.rb +9 -0
- data/lib/protected_attributes/version.rb +1 -1
- metadata +3 -49
- data/test/abstract_unit.rb +0 -165
- data/test/accessible_params_wrapper_test.rb +0 -76
- data/test/ar_helper.rb +0 -74
- data/test/attribute_sanitization_test.rb +0 -1077
- data/test/mass_assignment_security/black_list_test.rb +0 -21
- data/test/mass_assignment_security/permission_set_test.rb +0 -37
- data/test/mass_assignment_security/sanitizer_test.rb +0 -51
- data/test/mass_assignment_security/white_list_test.rb +0 -20
- data/test/mass_assignment_security_test.rb +0 -118
- data/test/models/battle.rb +0 -5
- data/test/models/company.rb +0 -17
- data/test/models/group.rb +0 -6
- data/test/models/keyboard.rb +0 -3
- data/test/models/mass_assignment_specific.rb +0 -76
- data/test/models/membership.rb +0 -8
- data/test/models/person.rb +0 -46
- data/test/models/pirate.rb +0 -5
- data/test/models/subscriber.rb +0 -5
- data/test/models/task.rb +0 -5
- data/test/models/team.rb +0 -5
- data/test/models/vampire.rb +0 -4
- data/test/models/wolf.rb +0 -4
- data/test/test_helper.rb +0 -4
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'active_model/mass_assignment_security'
|
3
|
-
|
4
|
-
class BlackListTest < ActiveModel::TestCase
|
5
|
-
|
6
|
-
def setup
|
7
|
-
@black_list = ActiveModel::MassAssignmentSecurity::BlackList.new
|
8
|
-
@included_key = 'admin'
|
9
|
-
@black_list += [ @included_key ]
|
10
|
-
end
|
11
|
-
|
12
|
-
test "deny? is true for included items" do
|
13
|
-
assert_equal true, @black_list.deny?(@included_key)
|
14
|
-
end
|
15
|
-
|
16
|
-
test "deny? is false for non-included items" do
|
17
|
-
assert_equal false, @black_list.deny?('first_name')
|
18
|
-
end
|
19
|
-
|
20
|
-
|
21
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'active_model/mass_assignment_security'
|
3
|
-
|
4
|
-
class PermissionSetTest < ActiveModel::TestCase
|
5
|
-
|
6
|
-
def setup
|
7
|
-
@permission_list = ActiveModel::MassAssignmentSecurity::PermissionSet.new
|
8
|
-
end
|
9
|
-
|
10
|
-
test "+ stringifies added collection values" do
|
11
|
-
symbol_collection = [ :admin ]
|
12
|
-
new_list = @permission_list += symbol_collection
|
13
|
-
|
14
|
-
assert new_list.include?('admin'), "did not add collection to #{@permission_list.inspect}}"
|
15
|
-
end
|
16
|
-
|
17
|
-
test "+ compacts added collection values" do
|
18
|
-
added_collection = [ nil ]
|
19
|
-
new_list = @permission_list + added_collection
|
20
|
-
assert_equal new_list, @permission_list, "did not add collection to #{@permission_list.inspect}}"
|
21
|
-
end
|
22
|
-
|
23
|
-
test "include? normalizes multi-parameter keys" do
|
24
|
-
multi_param_key = 'admin(1)'
|
25
|
-
new_list = @permission_list += [ 'admin' ]
|
26
|
-
|
27
|
-
assert new_list.include?(multi_param_key), "#{multi_param_key} not found in #{@permission_list.inspect}"
|
28
|
-
end
|
29
|
-
|
30
|
-
test "include? normal keys" do
|
31
|
-
normal_key = 'admin'
|
32
|
-
new_list = @permission_list += [ normal_key ]
|
33
|
-
|
34
|
-
assert new_list.include?(normal_key), "#{normal_key} not found in #{@permission_list.inspect}"
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'active_model/mass_assignment_security'
|
3
|
-
require 'active_support/logger'
|
4
|
-
|
5
|
-
class SanitizerTest < ActiveModel::TestCase
|
6
|
-
attr_accessor :logger
|
7
|
-
|
8
|
-
class Authorizer < ActiveModel::MassAssignmentSecurity::PermissionSet
|
9
|
-
def deny?(key)
|
10
|
-
['admin', 'id'].include?(key)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def setup
|
15
|
-
@logger_sanitizer = ActiveModel::MassAssignmentSecurity::LoggerSanitizer.new(self)
|
16
|
-
@strict_sanitizer = ActiveModel::MassAssignmentSecurity::StrictSanitizer.new(self)
|
17
|
-
@authorizer = Authorizer.new
|
18
|
-
end
|
19
|
-
|
20
|
-
test "sanitize attributes" do
|
21
|
-
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
|
22
|
-
attributes = @logger_sanitizer.sanitize(self.class, original_attributes, @authorizer)
|
23
|
-
|
24
|
-
assert attributes.key?('first_name'), "Allowed key shouldn't be rejected"
|
25
|
-
assert !attributes.key?('admin'), "Denied key should be rejected"
|
26
|
-
end
|
27
|
-
|
28
|
-
test "debug mass assignment removal with LoggerSanitizer" do
|
29
|
-
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
|
30
|
-
log = StringIO.new
|
31
|
-
self.logger = ActiveSupport::Logger.new(log)
|
32
|
-
@logger_sanitizer.sanitize(self.class, original_attributes, @authorizer)
|
33
|
-
assert_match(/admin/, log.string, "Should log removed attributes: #{log.string}")
|
34
|
-
end
|
35
|
-
|
36
|
-
test "debug mass assignment removal with StrictSanitizer" do
|
37
|
-
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
|
38
|
-
assert_raise ActiveModel::MassAssignmentSecurity::Error do
|
39
|
-
@strict_sanitizer.sanitize(self.class, original_attributes, @authorizer)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
test "mass assignment insensitive attributes" do
|
44
|
-
original_attributes = {'id' => 1, 'first_name' => 'allowed'}
|
45
|
-
|
46
|
-
assert_nothing_raised do
|
47
|
-
@strict_sanitizer.sanitize(self.class, original_attributes, @authorizer)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'active_model/mass_assignment_security'
|
3
|
-
|
4
|
-
class WhiteListTest < ActiveModel::TestCase
|
5
|
-
|
6
|
-
def setup
|
7
|
-
@white_list = ActiveModel::MassAssignmentSecurity::WhiteList.new
|
8
|
-
@included_key = 'first_name'
|
9
|
-
@white_list += [ @included_key ]
|
10
|
-
end
|
11
|
-
|
12
|
-
test "deny? is false for included items" do
|
13
|
-
assert_equal false, @white_list.deny?(@included_key)
|
14
|
-
end
|
15
|
-
|
16
|
-
test "deny? is true for non-included items" do
|
17
|
-
assert_equal true, @white_list.deny?('admin')
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
@@ -1,118 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'active_model/mass_assignment_security'
|
3
|
-
require 'models/mass_assignment_specific'
|
4
|
-
|
5
|
-
class CustomSanitizer < ActiveModel::MassAssignmentSecurity::Sanitizer
|
6
|
-
|
7
|
-
def process_removed_attributes(klass, attrs)
|
8
|
-
raise StandardError
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
class MassAssignmentSecurityTest < ActiveModel::TestCase
|
14
|
-
def test_attribute_protection
|
15
|
-
user = User.new
|
16
|
-
expected = { "name" => "John Smith", "email" => "john@smith.com" }
|
17
|
-
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true))
|
18
|
-
assert_equal expected, sanitized
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_attribute_protection_when_role_is_nil
|
22
|
-
user = User.new
|
23
|
-
expected = { "name" => "John Smith", "email" => "john@smith.com" }
|
24
|
-
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true), nil)
|
25
|
-
assert_equal expected, sanitized
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_only_moderator_role_attribute_accessible
|
29
|
-
user = SpecialUser.new
|
30
|
-
expected = { "name" => "John Smith", "email" => "john@smith.com" }
|
31
|
-
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true), :moderator)
|
32
|
-
assert_equal expected, sanitized
|
33
|
-
|
34
|
-
sanitized = user.sanitize_for_mass_assignment({ "name" => "John Smith", "email" => "john@smith.com", "admin" => true })
|
35
|
-
assert_equal({}, sanitized)
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_attributes_accessible
|
39
|
-
user = Person.new
|
40
|
-
expected = { "name" => "John Smith", "email" => "john@smith.com" }
|
41
|
-
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true))
|
42
|
-
assert_equal expected, sanitized
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_attributes_accessible_with_admin_role
|
46
|
-
user = Person.new
|
47
|
-
expected = { "name" => "John Smith", "email" => "john@smith.com", "admin" => true }
|
48
|
-
sanitized = user.sanitize_for_mass_assignment(expected.merge("super_powers" => true), :admin)
|
49
|
-
assert_equal expected, sanitized
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_attributes_accessible_with_roles_given_as_array
|
53
|
-
user = Account.new
|
54
|
-
expected = { "name" => "John Smith", "email" => "john@smith.com" }
|
55
|
-
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true))
|
56
|
-
assert_equal expected, sanitized
|
57
|
-
end
|
58
|
-
|
59
|
-
def test_attributes_accessible_with_admin_role_when_roles_given_as_array
|
60
|
-
user = Account.new
|
61
|
-
expected = { "name" => "John Smith", "email" => "john@smith.com", "admin" => true }
|
62
|
-
sanitized = user.sanitize_for_mass_assignment(expected.merge("super_powers" => true), :admin)
|
63
|
-
assert_equal expected, sanitized
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_attributes_protected_by_default
|
67
|
-
firm = Firm.new
|
68
|
-
expected = { }
|
69
|
-
sanitized = firm.sanitize_for_mass_assignment({ "type" => "Client" })
|
70
|
-
assert_equal expected, sanitized
|
71
|
-
end
|
72
|
-
|
73
|
-
def test_mass_assignment_protection_inheritance
|
74
|
-
assert SpecialLoosePerson.accessible_attributes.blank?
|
75
|
-
assert_equal Set.new(['credit_rating', 'administrator']), SpecialLoosePerson.protected_attributes
|
76
|
-
|
77
|
-
assert SpecialLoosePerson.accessible_attributes.blank?
|
78
|
-
assert_equal Set.new(['credit_rating']), SpecialLoosePerson.protected_attributes(:admin)
|
79
|
-
|
80
|
-
assert LooseDescendant.accessible_attributes.blank?
|
81
|
-
assert_equal Set.new(['credit_rating', 'administrator', 'phone_number']), LooseDescendant.protected_attributes
|
82
|
-
|
83
|
-
assert LooseDescendantSecond.accessible_attributes.blank?
|
84
|
-
assert_equal Set.new(['credit_rating', 'administrator', 'phone_number', 'name']), LooseDescendantSecond.protected_attributes,
|
85
|
-
'Running attr_protected twice in one class should merge the protections'
|
86
|
-
|
87
|
-
assert((SpecialTightPerson.protected_attributes - SpecialTightPerson.attributes_protected_by_default).blank?)
|
88
|
-
assert_equal Set.new(['name', 'address']), SpecialTightPerson.accessible_attributes
|
89
|
-
|
90
|
-
assert((SpecialTightPerson.protected_attributes(:admin) - SpecialTightPerson.attributes_protected_by_default).blank?)
|
91
|
-
assert_equal Set.new(['name', 'address', 'admin']), SpecialTightPerson.accessible_attributes(:admin)
|
92
|
-
|
93
|
-
assert((TightDescendant.protected_attributes - TightDescendant.attributes_protected_by_default).blank?)
|
94
|
-
assert_equal Set.new(['name', 'address', 'phone_number']), TightDescendant.accessible_attributes
|
95
|
-
|
96
|
-
assert((TightDescendant.protected_attributes(:admin) - TightDescendant.attributes_protected_by_default).blank?)
|
97
|
-
assert_equal Set.new(['name', 'address', 'admin', 'super_powers']), TightDescendant.accessible_attributes(:admin)
|
98
|
-
end
|
99
|
-
|
100
|
-
def test_mass_assignment_multiparameter_protector
|
101
|
-
task = Task.new
|
102
|
-
attributes = { "starting(1i)" => "2004", "starting(2i)" => "6", "starting(3i)" => "24" }
|
103
|
-
sanitized = task.sanitize_for_mass_assignment(attributes)
|
104
|
-
assert_equal sanitized, { }
|
105
|
-
end
|
106
|
-
|
107
|
-
def test_custom_sanitizer
|
108
|
-
old_sanitizer = User._mass_assignment_sanitizer
|
109
|
-
|
110
|
-
user = User.new
|
111
|
-
User.mass_assignment_sanitizer = CustomSanitizer.new
|
112
|
-
assert_raise StandardError do
|
113
|
-
user.sanitize_for_mass_assignment("admin" => true)
|
114
|
-
end
|
115
|
-
ensure
|
116
|
-
User.mass_assignment_sanitizer = old_sanitizer
|
117
|
-
end
|
118
|
-
end
|
data/test/models/battle.rb
DELETED
data/test/models/company.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
class AbstractCompany < ActiveRecord::Base
|
2
|
-
self.abstract_class = true
|
3
|
-
end
|
4
|
-
|
5
|
-
class Company < AbstractCompany
|
6
|
-
attr_protected :rating
|
7
|
-
end
|
8
|
-
|
9
|
-
class Firm < Company
|
10
|
-
end
|
11
|
-
|
12
|
-
class Corporation < Company
|
13
|
-
attr_accessible :type, :name, :description
|
14
|
-
end
|
15
|
-
|
16
|
-
class SpecialCorporation < Corporation
|
17
|
-
end
|
data/test/models/group.rb
DELETED
data/test/models/keyboard.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
class User
|
2
|
-
include ActiveModel::MassAssignmentSecurity
|
3
|
-
attr_protected :admin
|
4
|
-
|
5
|
-
public :sanitize_for_mass_assignment
|
6
|
-
end
|
7
|
-
|
8
|
-
class SpecialUser
|
9
|
-
include ActiveModel::MassAssignmentSecurity
|
10
|
-
attr_accessible :name, :email, :as => :moderator
|
11
|
-
|
12
|
-
public :sanitize_for_mass_assignment
|
13
|
-
end
|
14
|
-
|
15
|
-
class Person
|
16
|
-
include ActiveModel::MassAssignmentSecurity
|
17
|
-
attr_accessible :name, :email
|
18
|
-
attr_accessible :name, :email, :admin, :as => :admin
|
19
|
-
|
20
|
-
public :sanitize_for_mass_assignment
|
21
|
-
end
|
22
|
-
|
23
|
-
class Account
|
24
|
-
include ActiveModel::MassAssignmentSecurity
|
25
|
-
attr_accessible :name, :email, :as => [:default, :admin]
|
26
|
-
attr_accessible :admin, :as => :admin
|
27
|
-
|
28
|
-
public :sanitize_for_mass_assignment
|
29
|
-
end
|
30
|
-
|
31
|
-
class Firm
|
32
|
-
include ActiveModel::MassAssignmentSecurity
|
33
|
-
|
34
|
-
public :sanitize_for_mass_assignment
|
35
|
-
|
36
|
-
def self.attributes_protected_by_default
|
37
|
-
["type"]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
class Task
|
42
|
-
include ActiveModel::MassAssignmentSecurity
|
43
|
-
attr_protected :starting
|
44
|
-
|
45
|
-
public :sanitize_for_mass_assignment
|
46
|
-
end
|
47
|
-
|
48
|
-
class SpecialLoosePerson
|
49
|
-
include ActiveModel::MassAssignmentSecurity
|
50
|
-
attr_protected :credit_rating, :administrator
|
51
|
-
attr_protected :credit_rating, :as => :admin
|
52
|
-
end
|
53
|
-
|
54
|
-
class LooseDescendant < SpecialLoosePerson
|
55
|
-
attr_protected :phone_number
|
56
|
-
end
|
57
|
-
|
58
|
-
class LooseDescendantSecond< SpecialLoosePerson
|
59
|
-
attr_protected :phone_number
|
60
|
-
attr_protected :name
|
61
|
-
end
|
62
|
-
|
63
|
-
class SpecialTightPerson
|
64
|
-
include ActiveModel::MassAssignmentSecurity
|
65
|
-
attr_accessible :name, :address
|
66
|
-
attr_accessible :name, :address, :admin, :as => :admin
|
67
|
-
|
68
|
-
def self.attributes_protected_by_default
|
69
|
-
["mobile_number"]
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
class TightDescendant < SpecialTightPerson
|
74
|
-
attr_accessible :phone_number
|
75
|
-
attr_accessible :super_powers, :as => :admin
|
76
|
-
end
|
data/test/models/membership.rb
DELETED
data/test/models/person.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
class LoosePerson < ActiveRecord::Base
|
2
|
-
self.table_name = 'people'
|
3
|
-
|
4
|
-
attr_protected :comments, :best_friend_id, :best_friend_of_id
|
5
|
-
attr_protected :as => :admin
|
6
|
-
|
7
|
-
has_one :best_friend, :class_name => 'LoosePerson', :foreign_key => :best_friend_id
|
8
|
-
belongs_to :best_friend_of, :class_name => 'LoosePerson', :foreign_key => :best_friend_of_id
|
9
|
-
has_many :best_friends, :class_name => 'LoosePerson', :foreign_key => :best_friend_id
|
10
|
-
|
11
|
-
accepts_nested_attributes_for :best_friend, :best_friend_of, :best_friends
|
12
|
-
end
|
13
|
-
|
14
|
-
class TightPerson < ActiveRecord::Base
|
15
|
-
self.table_name = 'people'
|
16
|
-
|
17
|
-
attr_accessible :first_name, :gender
|
18
|
-
attr_accessible :first_name, :gender, :comments, :as => :admin
|
19
|
-
attr_accessible :best_friend_attributes, :best_friend_of_attributes, :best_friends_attributes
|
20
|
-
attr_accessible :best_friend_attributes, :best_friend_of_attributes, :best_friends_attributes, :as => :admin
|
21
|
-
|
22
|
-
has_one :best_friend, :class_name => 'TightPerson', :foreign_key => :best_friend_id
|
23
|
-
belongs_to :best_friend_of, :class_name => 'TightPerson', :foreign_key => :best_friend_of_id
|
24
|
-
has_many :best_friends, :class_name => 'TightPerson', :foreign_key => :best_friend_id
|
25
|
-
|
26
|
-
accepts_nested_attributes_for :best_friend, :best_friend_of, :best_friends
|
27
|
-
end
|
28
|
-
|
29
|
-
class NestedPerson < ActiveRecord::Base
|
30
|
-
self.table_name = 'people'
|
31
|
-
|
32
|
-
attr_accessible :first_name, :best_friend_first_name, :best_friend_attributes
|
33
|
-
attr_accessible :first_name, :gender, :comments, :as => :admin
|
34
|
-
attr_accessible :best_friend_attributes, :best_friend_first_name, :as => :admin
|
35
|
-
|
36
|
-
has_one :best_friend, :class_name => 'NestedPerson', :foreign_key => :best_friend_id
|
37
|
-
accepts_nested_attributes_for :best_friend, :update_only => true, :reject_if => :all_blank
|
38
|
-
|
39
|
-
def comments=(new_comments)
|
40
|
-
raise RuntimeError
|
41
|
-
end
|
42
|
-
|
43
|
-
def best_friend_first_name=(new_name)
|
44
|
-
assign_attributes({ :best_friend_attributes => { :first_name => new_name } })
|
45
|
-
end
|
46
|
-
end
|
data/test/models/pirate.rb
DELETED
data/test/models/subscriber.rb
DELETED
data/test/models/task.rb
DELETED
data/test/models/team.rb
DELETED
@@ -1,5 +0,0 @@
|
|
1
|
-
class Team < ActiveRecord::Base
|
2
|
-
has_many :battles
|
3
|
-
has_many :wolf_battles, :through => :battles, :class_name => 'Wolf', :source => :battle, :source_type => 'Wolf'
|
4
|
-
has_many :vampire_battles, :through => :battles, :class_name => 'Vampire', :source => :battle, :source_type => 'Vampire'
|
5
|
-
end
|