Permalink
Browse files

Disable mass assignment protection by default

The problem with this was that the activemodel
module used under the hood, breaks if it gets
included into any other module (!). This is because
it relies on the Class#class_attribute method
added by active_support/core_ext/class/attribute.rb

I do find it kinda strange that activemodel provides
a module that definitely breaks when being included
into another module, but well.

A long term solution might be to come up with a patch
for activemodel or to provide our own implementation.

For now, I see no other way around that problem, apart
from advising people to only include the module into
the classes they actually want to use it in (mentioned
in the README).

This commit also moved our mass assignment support
module around.

  old: Rails::DataMapper::MassAssignmentSecurity
  new: DataMapper::MassAssignmentSecurity

The idea behind that was move was that there's no
reason to touch the Rails namespace for something
we might as well want to provide in none rails
situations.
  • Loading branch information...
1 parent 7b91ba9 commit ccffe949edb5ac0ed2eacdca625bfe5a25828f30 @snusnu snusnu committed Oct 24, 2010
Showing with 72 additions and 38 deletions.
  1. +34 −1 README.rdoc
  2. +35 −36 lib/dm-rails/mass_assignment_security.rb
  3. +3 −1 lib/dm-rails/railtie.rb
View
@@ -489,7 +489,40 @@ For more detailed documentation about DataMapper naming conventions and the ones
== Mass assignment protection
-The `attr_protected` and `attr_accessible` methods are available to your models. They work like their activerecord counterparts, and allow you to set fine grained control over what attributes may be assigned in one go by users of your app.
+By default, `dm-rails` doesn't activate any support for mass assignment protection.
+You can however activate it for your application by including the relevant module
+either globally into all known models, or on a per model basis (the latter being
+advised, for reasons explained below).
+
+ # Global installation (config/application.rb is a good place for adding this)
+ #
+ # Make .attr_protected and .attr_accessible available to all models
+ # NOTE: This won't work if you have code that includes DataMapper::Resource
+ # into any other module. This is done by dm-is-remixable for example, so to
+ # be safe, you should only do that if you really know what you're doing.
+ # Quite some plugins make use of dm-is-remixable, so be sure to check that out
+ # before you go ahead and do the following in your config/application.rb
+ DataMapper::Model.append_inclusions(Rails::DataMapper::MassAssignmentSecurity)
+
+ # Local installation (recommended)
+ #
+ # Include the mass assignment protection only into models that actually need it
+ # This is the preferred way of doing things, at least for now. You will only
+ # have the functionality available where you actually need it, and you don't run
+ # into problems with third party code including DataMapper::Resource into other
+ # modules.
+
+ class Person
+
+ include DataMapper::Resource
+ include DataMapper::MassAssignmentSecurity
+
+ property :id, Serial
+ property :login, String
+
+ attr_protected :login
+
+ end
== Using additional datamapper plugins
@@ -20,47 +20,46 @@ def sanitize(attributes)
end
end
-module Rails
- module DataMapper
- # = Active Model Mass-Assignment Security
- module MassAssignmentSecurity
- extend ::ActiveSupport::Concern
- include ::ActiveModel::MassAssignmentSecurity
-
- module ClassMethods
- extend ::ActiveModel::MassAssignmentSecurity::ClassMethods
+module DataMapper
+ # = Active Model Mass-Assignment Security
+ module MassAssignmentSecurity
+ extend ::ActiveSupport::Concern
+ include ::ActiveModel::MassAssignmentSecurity
- def logger
- @logger ||= ::DataMapper.logger
- end
+ module ClassMethods
+ extend ::ActiveModel::MassAssignmentSecurity::ClassMethods
+ def logger
+ @logger ||= ::DataMapper.logger
end
- # Allows you to set all the attributes at once by passing in a hash with keys
- # matching the attribute names (which again matches the column names).
- #
- # If +guard_protected_attributes+ is true (the default), then sensitive
- # attributes can be protected from this form of mass-assignment by using
- # the +attr_protected+ macro. Or you can alternatively specify which
- # attributes *can* be accessed with the +attr_accessible+ macro. Then all the
- # attributes not included in that won't be allowed to be mass-assigned.
- #
- # class User < ActiveRecord::Base
- # attr_protected :is_admin
- # end
- #
- # user = User.new
- # user.attributes = { :username => 'Phusion', :is_admin => true }
- # user.username # => "Phusion"
- # user.is_admin? # => false
- #
- # user.send(:attributes=, { :username => 'Phusion', :is_admin => true }, false)
- # user.is_admin? # => true
- def attributes=(attributes, guard_protected_attributes = true)
- attributes = sanitize_for_mass_assignment(attributes) if guard_protected_attributes
- super(attributes)
- end
+ end
+ # Allows you to set all the attributes at once by passing in a hash with keys
+ # matching the attribute names (which again matches the column names).
+ #
+ # If +guard_protected_attributes+ is true (the default), then sensitive
+ # attributes can be protected from this form of mass-assignment by using
+ # the +attr_protected+ macro. Or you can alternatively specify which
+ # attributes *can* be accessed with the +attr_accessible+ macro. Then all the
+ # attributes not included in that won't be allowed to be mass-assigned.
+ #
+ # class User < ActiveRecord::Base
+ # attr_protected :is_admin
+ # end
+ #
+ # user = User.new
+ # user.attributes = { :username => 'Phusion', :is_admin => true }
+ # user.username # => "Phusion"
+ # user.is_admin? # => false
+ #
+ # user.send(:attributes=, { :username => 'Phusion', :is_admin => true }, false)
+ # user.is_admin? # => true
+ def attributes=(attributes, guard_protected_attributes = true)
+ attributes = sanitize_for_mass_assignment(attributes) if guard_protected_attributes
+ super(attributes)
end
+
end
end
+
@@ -16,8 +16,10 @@
require "dm-rails/railties/log_subscriber"
require "dm-rails/railties/i18n_support"
+# The module provided in there is made available
+# but users will still need to include it into the
+# models they want it to use it in.
require 'dm-rails/mass_assignment_security'
-DataMapper::Model.append_inclusions(Rails::DataMapper::MassAssignmentSecurity)
module Rails
module DataMapper

0 comments on commit ccffe94

Please sign in to comment.