From 4b66aab00fa0ea6bcc6ec81df19e44de34fd7864 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Thu, 8 Jul 2010 18:16:36 +0200 Subject: mass_assignment_security moved from AR to AMo, and minor test cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- .../mass_assignment_security/black_list_test.rb | 28 +++++++++++ .../permission_set_test.rb | 30 ++++++++++++ .../mass_assignment_security/sanitizer_test.rb | 37 ++++++++++++++ .../mass_assignment_security/white_list_test.rb | 28 +++++++++++ .../test/cases/mass_assignment_security_test.rb | 52 ++++++++++++++++++++ .../test/models/mass_assignment_specific.rb | 57 ++++++++++++++++++++++ 6 files changed, 232 insertions(+) create mode 100644 activemodel/test/cases/mass_assignment_security/black_list_test.rb create mode 100644 activemodel/test/cases/mass_assignment_security/permission_set_test.rb create mode 100644 activemodel/test/cases/mass_assignment_security/sanitizer_test.rb create mode 100644 activemodel/test/cases/mass_assignment_security/white_list_test.rb create mode 100644 activemodel/test/cases/mass_assignment_security_test.rb create mode 100644 activemodel/test/models/mass_assignment_specific.rb (limited to 'activemodel/test') diff --git a/activemodel/test/cases/mass_assignment_security/black_list_test.rb b/activemodel/test/cases/mass_assignment_security/black_list_test.rb new file mode 100644 index 0000000000..ed168bc016 --- /dev/null +++ b/activemodel/test/cases/mass_assignment_security/black_list_test.rb @@ -0,0 +1,28 @@ +require "cases/helper" + +class BlackListTest < ActiveModel::TestCase + + def setup + @black_list = ActiveModel::MassAssignmentSecurity::BlackList.new + @included_key = 'admin' + @black_list += [ @included_key ] + end + + test "deny? is true for included items" do + assert_equal true, @black_list.deny?(@included_key) + end + + test "deny? is false for non-included items" do + assert_equal false, @black_list.deny?('first_name') + end + + test "sanitize attributes" do + original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied', 'admin(1)' => 'denied' } + attributes = @black_list.sanitize(original_attributes) + + assert attributes.key?('first_name'), "Allowed key shouldn't be rejected" + assert !attributes.key?('admin'), "Denied key should be rejected" + assert !attributes.key?('admin(1)'), "Multi-parameter key should be detected" + end + +end diff --git a/activemodel/test/cases/mass_assignment_security/permission_set_test.rb b/activemodel/test/cases/mass_assignment_security/permission_set_test.rb new file mode 100644 index 0000000000..d005b638e4 --- /dev/null +++ b/activemodel/test/cases/mass_assignment_security/permission_set_test.rb @@ -0,0 +1,30 @@ +require "cases/helper" + +class PermissionSetTest < ActiveModel::TestCase + + def setup + @permission_list = ActiveModel::MassAssignmentSecurity::PermissionSet.new + end + + test "+ stringifies added collection values" do + symbol_collection = [ :admin ] + new_list = @permission_list += symbol_collection + + assert new_list.include?('admin'), "did not add collection to #{@permission_list.inspect}}" + end + + test "include? normalizes multi-parameter keys" do + multi_param_key = 'admin(1)' + new_list = @permission_list += [ 'admin' ] + + assert new_list.include?(multi_param_key), "#{multi_param_key} not found in #{@permission_list.inspect}" + end + + test "include? normal keys" do + normal_key = 'admin' + new_list = @permission_list += [ normal_key ] + + assert new_list.include?(normal_key), "#{normal_key} not found in #{@permission_list.inspect}" + end + +end diff --git a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb new file mode 100644 index 0000000000..367207aab3 --- /dev/null +++ b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb @@ -0,0 +1,37 @@ +require "cases/helper" +require 'logger' + +class SanitizerTest < ActiveModel::TestCase + + class SanitizingAuthorizer + include ActiveModel::MassAssignmentSecurity::Sanitizer + + attr_accessor :logger + + def deny?(key) + [ 'admin' ].include?(key) + end + + end + + def setup + @sanitizer = SanitizingAuthorizer.new + end + + test "sanitize attributes" do + original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' } + attributes = @sanitizer.sanitize(original_attributes) + + assert attributes.key?('first_name'), "Allowed key shouldn't be rejected" + assert !attributes.key?('admin'), "Denied key should be rejected" + end + + test "debug mass assignment removal" do + original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' } + log = StringIO.new + @sanitizer.logger = Logger.new(log) + @sanitizer.sanitize(original_attributes) + assert (log.string =~ /admin/), "Should log removed attributes: #{log.string}" + end + +end diff --git a/activemodel/test/cases/mass_assignment_security/white_list_test.rb b/activemodel/test/cases/mass_assignment_security/white_list_test.rb new file mode 100644 index 0000000000..aa3596ad2a --- /dev/null +++ b/activemodel/test/cases/mass_assignment_security/white_list_test.rb @@ -0,0 +1,28 @@ +require "cases/helper" + +class WhiteListTest < ActiveModel::TestCase + + def setup + @white_list = ActiveModel::MassAssignmentSecurity::WhiteList.new + @included_key = 'first_name' + @white_list += [ @included_key ] + end + + test "deny? is false for included items" do + assert_equal false, @white_list.deny?(@included_key) + end + + test "deny? is true for non-included items" do + assert_equal true, @white_list.deny?('admin') + end + + test "sanitize attributes" do + original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied', 'admin(1)' => 'denied' } + attributes = @white_list.sanitize(original_attributes) + + assert attributes.key?('first_name'), "Allowed key shouldn't be rejected" + assert !attributes.key?('admin'), "Denied key should be rejected" + assert !attributes.key?('admin(1)'), "Multi-parameter key should be detected" + end + +end diff --git a/activemodel/test/cases/mass_assignment_security_test.rb b/activemodel/test/cases/mass_assignment_security_test.rb new file mode 100644 index 0000000000..0f7a38b0bc --- /dev/null +++ b/activemodel/test/cases/mass_assignment_security_test.rb @@ -0,0 +1,52 @@ +require "cases/helper" +require 'models/mass_assignment_specific' + +class MassAssignmentSecurityTest < ActiveModel::TestCase + + def test_attribute_protection + user = User.new + expected = { "name" => "John Smith", "email" => "john@smith.com" } + sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true)) + assert_equal expected, sanitized + end + + def test_attributes_accessible + user = Person.new + expected = { "name" => "John Smith", "email" => "john@smith.com" } + sanitized = user.sanitize_for_mass_assignment(expected.merge("super_powers" => true)) + assert_equal expected, sanitized + end + + def test_attributes_protected_by_default + firm = Firm.new + expected = { } + sanitized = firm.sanitize_for_mass_assignment({ "type" => "Client" }) + assert_equal expected, sanitized + end + + def test_mass_assignment_protection_inheritance + assert LoosePerson.accessible_attributes.blank? + assert_equal Set.new([ 'credit_rating', 'administrator']), LoosePerson.protected_attributes + + assert LooseDescendant.accessible_attributes.blank? + assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number']), LooseDescendant.protected_attributes + + assert LooseDescendantSecond.accessible_attributes.blank? + assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number', 'name']), LooseDescendantSecond.protected_attributes, + 'Running attr_protected twice in one class should merge the protections' + + assert (TightPerson.protected_attributes - TightPerson.attributes_protected_by_default).blank? + assert_equal Set.new([ 'name', 'address' ]), TightPerson.accessible_attributes + + assert (TightDescendant.protected_attributes - TightDescendant.attributes_protected_by_default).blank? + assert_equal Set.new([ 'name', 'address', 'phone_number' ]), TightDescendant.accessible_attributes + end + + def test_mass_assignment_multiparameter_protector + task = Task.new + attributes = { "starting(1i)" => "2004", "starting(2i)" => "6", "starting(3i)" => "24" } + sanitized = task.sanitize_for_mass_assignment(attributes) + assert_equal sanitized, { } + end + +end \ No newline at end of file diff --git a/activemodel/test/models/mass_assignment_specific.rb b/activemodel/test/models/mass_assignment_specific.rb new file mode 100644 index 0000000000..2a8fe170c2 --- /dev/null +++ b/activemodel/test/models/mass_assignment_specific.rb @@ -0,0 +1,57 @@ +class User + include ActiveModel::MassAssignmentSecurity + attr_protected :admin + + public :sanitize_for_mass_assignment +end + +class Person + include ActiveModel::MassAssignmentSecurity + attr_accessible :name, :email + + public :sanitize_for_mass_assignment +end + +class Firm + include ActiveModel::MassAssignmentSecurity + + public :sanitize_for_mass_assignment + + def self.attributes_protected_by_default + ["type"] + end +end + +class Task + include ActiveModel::MassAssignmentSecurity + attr_protected :starting + + public :sanitize_for_mass_assignment +end + +class LoosePerson + include ActiveModel::MassAssignmentSecurity + attr_protected :credit_rating, :administrator +end + +class LooseDescendant < LoosePerson + attr_protected :phone_number +end + +class LooseDescendantSecond< LoosePerson + attr_protected :phone_number + attr_protected :name +end + +class TightPerson + include ActiveModel::MassAssignmentSecurity + attr_accessible :name, :address + + def self.attributes_protected_by_default + ["mobile_number"] + end +end + +class TightDescendant < TightPerson + attr_accessible :phone_number +end \ No newline at end of file -- cgit v1.2.3