aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
authorJosh Kalderimis <josh.kalderimis@gmail.com>2010-07-08 18:16:36 +0200
committerJosé Valim <jose.valim@gmail.com>2010-07-08 18:28:45 +0200
commit4b66aab00fa0ea6bcc6ec81df19e44de34fd7864 (patch)
treeff870b932c26869d6a27a6a058d37baa6c289e0a /activerecord/lib/active_record
parent7c86e8e21ba6a1f88226ddd0cf012a563f234d06 (diff)
downloadrails-4b66aab00fa0ea6bcc6ec81df19e44de34fd7864.tar.gz
rails-4b66aab00fa0ea6bcc6ec81df19e44de34fd7864.tar.bz2
rails-4b66aab00fa0ea6bcc6ec81df19e44de34fd7864.zip
mass_assignment_security moved from AR to AMo, and minor test cleanup
Signed-off-by: José Valim <jose.valim@gmail.com>
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/base.rb2
-rw-r--r--activerecord/lib/active_record/mass_assignment_security.rb142
-rw-r--r--activerecord/lib/active_record/mass_assignment_security/permission_set.rb41
-rw-r--r--activerecord/lib/active_record/mass_assignment_security/sanitizer.rb29
4 files changed, 1 insertions, 213 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 56b4ba8260..f22a9de7b1 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1797,7 +1797,7 @@ MSG
include AttributeMethods::PrimaryKey
include AttributeMethods::TimeZoneConversion
include AttributeMethods::Dirty
- include MassAssignmentSecurity
+ include ActiveModel::MassAssignmentSecurity
include Callbacks, ActiveModel::Observing, Timestamp
include Associations, AssociationPreload, NamedScope
diff --git a/activerecord/lib/active_record/mass_assignment_security.rb b/activerecord/lib/active_record/mass_assignment_security.rb
deleted file mode 100644
index 8f4d6e1c74..0000000000
--- a/activerecord/lib/active_record/mass_assignment_security.rb
+++ /dev/null
@@ -1,142 +0,0 @@
-require 'active_record/mass_assignment_security/permission_set'
-
-module ActiveRecord
- # = Active Record Mass-Assignment Security
- module MassAssignmentSecurity
- extend ActiveSupport::Concern
-
- included do
- class_attribute :_accessible_attributes
- class_attribute :_protected_attributes
- class_attribute :_active_authorizer
- end
-
- # Mass assignment security provides an interface for protecting attributes
- # from end-user assignment. For more complex permissions, mass assignment security
- # may be handled outside the model by extending a non-ActiveRecord class,
- # such as a controller, with this behavior.
- #
- # For example, a logged in user may need to assign additional attributes depending
- # on their role:
- #
- # class AccountsController < ApplicationController
- # include ActiveRecord::MassAssignmentSecurity
- #
- # attr_accessible :first_name, :last_name
- #
- # def self.admin_accessible_attributes
- # accessible_attributes + [ :plan_id ]
- # end
- #
- # def update
- # ...
- # @account.update_attributes(account_params)
- # ...
- # end
- #
- # protected
- #
- # def account_params
- # sanitize_for_mass_assignment(params[:account])
- # end
- #
- # def mass_assignment_authorizer
- # admin ? admin_accessible_attributes : super
- # end
- #
- # end
- #
- module ClassMethods
- # Attributes named in this macro are protected from mass-assignment,
- # such as <tt>new(attributes)</tt>,
- # <tt>update_attributes(attributes)</tt>, or
- # <tt>attributes=(attributes)</tt>.
- #
- # Mass-assignment to these attributes will simply be ignored, to assign
- # to them you can use direct writer methods. This is meant to protect
- # sensitive attributes from being overwritten by malicious users
- # tampering with URLs or forms.
- #
- # class Customer < ActiveRecord::Base
- # attr_protected :credit_rating
- # end
- #
- # customer = Customer.new("name" => David, "credit_rating" => "Excellent")
- # customer.credit_rating # => nil
- # customer.attributes = { "description" => "Jolly fellow", "credit_rating" => "Superb" }
- # customer.credit_rating # => nil
- #
- # customer.credit_rating = "Average"
- # customer.credit_rating # => "Average"
- #
- # To start from an all-closed default and enable attributes as needed,
- # have a look at +attr_accessible+.
- #
- # Note that using <tt>Hash#except</tt> or <tt>Hash#slice</tt> in place of +attr_protected+
- # to sanitize attributes won't provide sufficient protection.
- def attr_protected(*names)
- self._protected_attributes = self.protected_attributes + names
- self._active_authorizer = self._protected_attributes
- end
-
- # Specifies a white list of model attributes that can be set via
- # mass-assignment, such as <tt>new(attributes)</tt>,
- # <tt>update_attributes(attributes)</tt>, or
- # <tt>attributes=(attributes)</tt>
- #
- # This is the opposite of the +attr_protected+ macro: Mass-assignment
- # will only set attributes in this list, to assign to the rest of
- # attributes you can use direct writer methods. This is meant to protect
- # sensitive attributes from being overwritten by malicious users
- # tampering with URLs or forms. If you'd rather start from an all-open
- # default and restrict attributes as needed, have a look at
- # +attr_protected+.
- #
- # class Customer < ActiveRecord::Base
- # attr_accessible :name, :nickname
- # end
- #
- # customer = Customer.new(:name => "David", :nickname => "Dave", :credit_rating => "Excellent")
- # customer.credit_rating # => nil
- # customer.attributes = { :name => "Jolly fellow", :credit_rating => "Superb" }
- # customer.credit_rating # => nil
- #
- # customer.credit_rating = "Average"
- # customer.credit_rating # => "Average"
- #
- # Note that using <tt>Hash#except</tt> or <tt>Hash#slice</tt> in place of +attr_accessible+
- # to sanitize attributes won't provide sufficient protection.
- def attr_accessible(*names)
- self._accessible_attributes = self.accessible_attributes + names
- self._active_authorizer = self._accessible_attributes
- end
-
- def protected_attributes
- self._protected_attributes ||= BlackList.new(attributes_protected_by_default).tap { |w| w.logger = logger }
- end
-
- def accessible_attributes
- self._accessible_attributes ||= WhiteList.new.tap { |w| w.logger = logger }
- end
-
- def active_authorizer
- self._active_authorizer ||= protected_attributes
- end
-
- def attributes_protected_by_default
- []
- end
- end
-
- protected
-
- def sanitize_for_mass_assignment(attributes)
- mass_assignment_authorizer.sanitize(attributes)
- end
-
- def mass_assignment_authorizer
- self.class.active_authorizer
- end
-
- end
-end
diff --git a/activerecord/lib/active_record/mass_assignment_security/permission_set.rb b/activerecord/lib/active_record/mass_assignment_security/permission_set.rb
deleted file mode 100644
index 8446a4103b..0000000000
--- a/activerecord/lib/active_record/mass_assignment_security/permission_set.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require 'active_record/mass_assignment_security/sanitizer'
-
-module ActiveRecord
- module MassAssignmentSecurity
-
- class PermissionSet < Set
- attr_accessor :logger
-
- def +(values)
- super(values.map(&:to_s))
- end
-
- def include?(key)
- super(remove_multiparameter_id(key))
- end
-
- protected
-
- def remove_multiparameter_id(key)
- key.gsub(/\(.+/, '')
- end
- end
-
- class WhiteList < PermissionSet
- include Sanitizer
-
- def deny?(key)
- !include?(key)
- end
- end
-
- class BlackList < PermissionSet
- include Sanitizer
-
- def deny?(key)
- include?(key)
- end
- end
-
- end
-end \ No newline at end of file
diff --git a/activerecord/lib/active_record/mass_assignment_security/sanitizer.rb b/activerecord/lib/active_record/mass_assignment_security/sanitizer.rb
deleted file mode 100644
index 11de35f9d6..0000000000
--- a/activerecord/lib/active_record/mass_assignment_security/sanitizer.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-module ActiveRecord
- module MassAssignmentSecurity
- module Sanitizer
-
- # Returns all attributes not denied by the authorizer.
- def sanitize(attributes)
- sanitized_attributes = attributes.reject { |key, value| deny?(key) }
- debug_protected_attribute_removal(attributes, sanitized_attributes) if debug?
- sanitized_attributes
- end
-
- protected
-
- def debug_protected_attribute_removal(attributes, sanitized_attributes)
- removed_keys = attributes.keys - sanitized_attributes.keys
- warn!(removed_keys) if removed_keys.any?
- end
-
- def debug?
- logger.present?
- end
-
- def warn!(attrs)
- logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}"
- end
-
- end
- end
-end