require 'dm-core' require 'active_support/core_ext/class/attribute' require 'active_support/concern' require 'active_model' module ActiveModel module MassAssignmentSecurity # Provides a patched version of the Sanitizer used in Rails to handle property # and relationship objects as keys. There is no way to inject a custom sanitizer # without reimplementing the permission sets. Sanitizer.send(Sanitizer.is_a?(Module) ? :module_eval : :class_eval) do # Returns all attributes not denied by the authorizer. # # @param [Hash{Symbol,String,::DataMapper::Property,::DataMapper::Relationship=>Object}] attributes # Names and values of attributes to sanitize. # @return [Hash] # Sanitized hash of attributes. def sanitize(attributes, authorizer = nil) sanitized_attributes = attributes.reject do |key, value| key_name = key.name rescue key authorizer ? authorizer.deny?(key_name) : deny?(key_name) end debug_protected_attribute_removal(attributes, sanitized_attributes) sanitized_attributes end end end end module DataMapper # Include this module into a DataMapper model to enable ActiveModel's mass # assignment security. # # To use second parameter of {#attributes=} make sure to include this module # last. module MassAssignmentSecurity extend ::ActiveSupport::Concern include ::ActiveModel::MassAssignmentSecurity module ClassMethods extend ::ActiveModel::MassAssignmentSecurity::ClassMethods def logger @logger ||= ::DataMapper.logger end end # Sanitizes the specified +attributes+ according to the defined mass-assignment # security rules and calls +super+ with the result. # # Use either +attr_accessible+ to specify which attributes are allowed to be # assigned via {#attributes=}, or +attr_protected+ to specify which attributes # are *not* allowed to be assigned via {#attributes=}. # # +attr_accessible+ and +attr_protected+ are mutually exclusive. # # @param [Hash{Symbol,String,::DataMapper::Property,::DataMapper::Relationship=>Object}] attributes # Names and values of attributes to sanitize. # @param [Boolean] guard_protected_attributes # Determines whether mass-security rules are applied (when +true+) or not. # @return [Hash] # Sanitized hash of attributes. # @api public # # @example [Usage] # class User # include DataMapper::Resource # include DataMapper::MassAssignmentSecurity # # property :name, String # property :is_admin, Boolean # # # Only allow name to be set via #attributes= # attr_accessible :name # 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