Skip to content

Commit

Permalink
Use ActiveModel::MassAssignmentSecurity for attr_accessible, attr_pro…
Browse files Browse the repository at this point in the history
…tected

This patch requires ActiveModel edge, revision 4b66aab0 or later.
  • Loading branch information
tessro authored and durran committed Jul 27, 2010
1 parent 0f215ad commit e44d9d8
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 28 deletions.
1 change: 1 addition & 0 deletions lib/mongoid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
require "active_model/conversion"
require "active_model/deprecated_error_methods"
require "active_model/errors"
require "active_model/mass_assignment_security"
require "active_model/naming"
require "active_model/serialization"
require "active_model/translation"
Expand Down
3 changes: 2 additions & 1 deletion lib/mongoid/associations/references_many.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def <<(*objects)
def build(attributes = nil)
load_target
name = determine_name
object = @klass.instantiate((attributes || {}).merge(name => @parent))
object = @klass.instantiate(attributes || {})
object.send("#{name}=", @parent)
@target << object
object
end
Expand Down
27 changes: 2 additions & 25 deletions lib/mongoid/attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
module Mongoid #:nodoc:
module Attributes
extend ActiveSupport::Concern
included do
class_inheritable_accessor :_protected_fields
self._protected_fields = []
end

# Get the id associated with this object. This will pull the _id value out
# of the attributes +Hash+.
Expand Down Expand Up @@ -38,10 +34,10 @@ def method_missing(name, *args)
# attributes provided in the suppied +Hash+ so that no extra nil values get
# put into the document's attributes.
def process(attrs = nil)
(attrs || {}).each_pair do |key, value|
sanitize_for_mass_assignment(attrs || {}).each_pair do |key, value|
if set_allowed?(key)
write_attribute(key, value)
elsif write_allowed?(key)
else
if associations.include?(key.to_s) and associations[key.to_s].embedded? and value.is_a?(Hash)
if association = send(key)
association.nested_build(value)
Expand Down Expand Up @@ -188,12 +184,6 @@ def limit(attributes, name, options)
end
end

# Return true if writing to the given field is allowed
def write_allowed?(key)
name = key.to_s
!self._protected_fields.include?(name)
end

module ClassMethods
# Defines attribute setters for the associations specified by the names.
# This will work for a has one or has many association.
Expand Down Expand Up @@ -224,19 +214,6 @@ def accepts_nested_attributes_for(*args)
end
end
end

# Defines fields that cannot be set via mass assignment.
#
# Example:
#
# class Person
# include Mongoid::Document
# field :security_code
# attr_protected :security_code
# end
def attr_protected(*names)
_protected_fields.concat(names.flatten.map(&:to_s))
end
end
end
end
1 change: 1 addition & 0 deletions lib/mongoid/components.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module Components #:nodoc
include ActiveModel::Conversion
include ActiveModel::Naming
include ActiveModel::Serialization
include ActiveModel::MassAssignmentSecurity
include ActiveModel::Serializers::JSON
include ActiveModel::Serializers::Xml
include Mongoid::Associations
Expand Down
5 changes: 5 additions & 0 deletions spec/models/account.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
class Account
include Mongoid::Document
referenced_in :creator, :class_name => "User", :foreign_key => :creator_id
referenced_in :person
field :number
field :balance
field :nickname

attr_accessible :nickname
end
15 changes: 13 additions & 2 deletions spec/unit/mongoid/associations/references_many_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@ def extension
@association.first.person.should == @parent
end
end

it "sets the foreign key when it is protected from mass assignment" do
Account.expects(:all).returns(@criteria)
options = Mongoid::Associations::Options.new(
:name => :accounts,
:foreign_key => "person_id"
)
@association = Mongoid::Associations::ReferencesMany.new(@parent, options)
@association.build(:nickname => "Checking")
@association.first.person_id.should == @parent.id
end
end

describe "#delete_all" do
Expand Down Expand Up @@ -230,7 +241,7 @@ def extension
describe "#create" do

before do
@post = mock
@post = Post.new
@parent = stub(:id => "5", :class => Person, :new_record? => true)
Post.expects(:all).returns([])
@association = Mongoid::Associations::ReferencesMany.new(@parent, options)
Expand All @@ -257,7 +268,7 @@ def extension
describe "#create!" do

before do
@post = mock
@post = Post.new
@parent = stub(:id => "5", :class => Person, :new_record? => true)
Post.expects(:all).returns([])
@association = Mongoid::Associations::ReferencesMany.new(@parent, options)
Expand Down
36 changes: 36 additions & 0 deletions spec/unit/mongoid/attributes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,42 @@
end
end

describe ".attr_accessible" do

context "when the field is not _id" do

before do
@account = Account.new(:balance => 999999)
end

it "prevents setting via mass assignment" do
@account.balance.should be_nil
end
end

context "when the field is _id" do

before do
@account = Account.new(:_id => "ABBA")
end

it "prevents setting via mass assignment" do
@account._id.should_not == "ABBA"
end
end

context "when using instantiate" do

before do
@account = Account.instantiate("_id" => "1", "balance" => "ABBA")
end

it "ignores any protected attribute" do
@account.balance.should == "ABBA"
end
end
end

describe ".attr_protected" do

context "when the field is not _id" do
Expand Down

0 comments on commit e44d9d8

Please sign in to comment.