Module: ActiveModel::MassAssignmentSecurity::ClassMethods
- Defined in:
- lib/active_model/mass_assignment_security.rb
Instance Method Summary collapse
-
#accessible_attributes(role = :default) ⇒ Object
Returns an instance of
ActiveModel::MassAssignmentSecurity::WhiteList
with the attributes protected by #attr_accessible method. -
#active_authorizers ⇒ Object
(also: #active_authorizer)
Returns a hash with the protected attributes (by #attr_accessible or #attr_protected) per role.
-
#attr_accessible(*args) ⇒ Object
Specifies a white list of model attributes that can be set via mass-assignment.
-
#attr_protected(*args) ⇒ Object
Attributes named in this macro are protected from mass-assignment whenever attributes are sanitized before assignment.
-
#attributes_protected_by_default ⇒ Object
Returns an empty array by default.
-
#mass_assignment_sanitizer=(value) ⇒ Object
Defines sanitize method.
-
#protected_attributes(role = :default) ⇒ Object
Returns an instance of
ActiveModel::MassAssignmentSecurity::BlackList
with the attributes protected by #attr_protected method.
Instance Method Details
#accessible_attributes(role = :default) ⇒ Object
Returns an instance of ActiveModel::MassAssignmentSecurity::WhiteList
with the attributes protected by #attr_accessible method. If no role
is provided, then :default
is used.
class Customer
include ActiveModel::MassAssignmentSecurity
attr_accessor :name, :credit_rating
attr_accessible :name, as: [:admin, :default]
attr_accessible :credit_rating, as: :admin
end
Customer.accessible_attributes
# => #<ActiveModel::MassAssignmentSecurity::WhiteList: {"name"}>
Customer.accessible_attributes(:default)
# => #<ActiveModel::MassAssignmentSecurity::WhiteList: {"name"}>
Customer.accessible_attributes(:admin)
# => #<ActiveModel::MassAssignmentSecurity::WhiteList: {"name", "credit_rating"}>
246 247 248 |
# File 'lib/active_model/mass_assignment_security.rb', line 246 def accessible_attributes(role = :default) accessible_attributes_configs[role] end |
#active_authorizers ⇒ Object Also known as:
Returns a hash with the protected attributes (by #attr_accessible or #attr_protected) per role.
class Customer
include ActiveModel::MassAssignmentSecurity
attr_accessor :name, :credit_rating
attr_accessible :name, as: [:admin, :default]
attr_accessible :credit_rating, as: :admin
end
Customer.
# => {
# :admin=> #<ActiveModel::MassAssignmentSecurity::WhiteList: {"name", "credit_rating"}>,
# :default=>#<ActiveModel::MassAssignmentSecurity::WhiteList: {"name"}>
# }
267 268 269 |
# File 'lib/active_model/mass_assignment_security.rb', line 267 def self. ||= protected_attributes_configs end |
#attr_accessible(*args) ⇒ Object
Specifies a white list of model attributes that can be set via mass-assignment.
Like attr_protected
, a role for the attributes is optional, if no role is provided then :default
is used. A role can be defined by using the :as
option with a symbol or an array of symbols as the value.
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
include ActiveModel::MassAssignmentSecurity
attr_accessor :name, :credit_rating
# Both admin and default user can change name of a customer
attr_accessible :name, as: [:admin, :default]
# Only admin can change credit rating of a customer
attr_accessible :credit_rating, as: :admin
def assign_attributes(values, = {})
sanitize_for_mass_assignment(values, [:as]).each do |k, v|
send("#{k}=", v)
end
end
end
When using the :default
role:
customer = Customer.new
customer.assign_attributes({ name: 'David', credit_rating: 'Excellent', last_login: 1.day.ago }, as: :default)
customer.name # => "David"
customer. # => nil
customer. = 'Average'
customer. # => "Average"
And using the :admin
role:
customer = Customer.new
customer.assign_attributes({ name: 'David', credit_rating: 'Excellent', last_login: 1.day.ago }, as: :admin)
customer.name # => "David"
customer. # => "Excellent"
Note that using Hash#except
or Hash#slice
in place of attr_accessible
to sanitize attributes provides basically the same functionality, but it makes a bit tricky to deal with nested attributes.
186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/active_model/mass_assignment_security.rb', line 186 def attr_accessible(*args) = args. role = [:as] || :default self._accessible_attributes = accessible_attributes_configs.dup Array(role).each do |name| self._accessible_attributes[name] = self.accessible_attributes(name) + args end self._uses_mass_assignment_security = true self. = self._accessible_attributes end |
#attr_protected(*args) ⇒ Object
Attributes named in this macro are protected from mass-assignment whenever attributes are sanitized before assignment. A role for the attributes is optional, if no role is provided then :default
is used. A role can be defined by using the :as
option with a symbol or an array of symbols as the value.
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
include ActiveModel::MassAssignmentSecurity
attr_accessor :name, :email, :logins_count
attr_protected :logins_count
# Suppose that admin can not change email for customer
attr_protected :logins_count, :email, as: :admin
def assign_attributes(values, = {})
sanitize_for_mass_assignment(values, [:as]).each do |k, v|
send("#{k}=", v)
end
end
end
When using the :default
role:
customer = Customer.new
customer.assign_attributes({ name: 'David', email: '[email protected]', logins_count: 5 }, as: :default)
customer.name # => "David"
customer.email # => "[email protected]"
customer.logins_count # => nil
And using the :admin
role:
customer = Customer.new
customer.assign_attributes({ name: 'David', email: '[email protected]', logins_count: 5}, as: :admin)
customer.name # => "David"
customer.email # => nil
customer.logins_count # => nil
customer.email = '[email protected]'
customer.email # => "[email protected]"
To start from an all-closed default and enable attributes as needed, have a look at attr_accessible
.
Note that using Hash#except
or Hash#slice
in place of attr_protected
to sanitize attributes provides basically the same functionality, but it makes a bit tricky to deal with nested attributes.
119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/active_model/mass_assignment_security.rb', line 119 def attr_protected(*args) = args. role = [:as] || :default self._protected_attributes = protected_attributes_configs.dup Array(role).each do |name| self._protected_attributes[name] = self.protected_attributes(name) + args end self._uses_mass_assignment_security = true self. = self._protected_attributes end |
#attributes_protected_by_default ⇒ Object
Returns an empty array by default. You can still override this to define the default attributes protected by #attr_protected method.
class Customer
include ActiveModel::MassAssignmentSecurity
def self.attributes_protected_by_default
[:name]
end
end
Customer.protected_attributes
# => #<ActiveModel::MassAssignmentSecurity::BlackList: {:name}>
285 286 287 |
# File 'lib/active_model/mass_assignment_security.rb', line 285 def attributes_protected_by_default [] end |
#mass_assignment_sanitizer=(value) ⇒ Object
Defines sanitize method.
class Customer
include ActiveModel::MassAssignmentSecurity
attr_accessor :name
attr_protected :name
def assign_attributes(values)
sanitize_for_mass_assignment(values).each do |k, v|
send("#{k}=", v)
end
end
end
# See ActiveModel::MassAssignmentSecurity::StrictSanitizer for more information.
Customer.mass_assignment_sanitizer = :strict
customer = Customer.new
customer.assign_attributes(name: 'David')
# => ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes for Customer: name
Also, you can specify your own sanitizer object.
class CustomSanitizer < ActiveModel::MassAssignmentSecurity::Sanitizer
def process_removed_attributes(klass, attrs)
raise StandardError
end
end
Customer.mass_assignment_sanitizer = CustomSanitizer.new
customer = Customer.new
customer.assign_attributes(name: 'David')
# => StandardError: StandardError
325 326 327 |
# File 'lib/active_model/mass_assignment_security.rb', line 325 def mass_assignment_sanitizer=(value) self._mass_assignment_sanitizer = value.is_a?(Symbol) ? const_get(:"#{value.to_s.camelize}Sanitizer").new(self) : value end |
#protected_attributes(role = :default) ⇒ Object
Returns an instance of ActiveModel::MassAssignmentSecurity::BlackList
with the attributes protected by #attr_protected method. If no role
is provided, then :default
is used.
class Customer
include ActiveModel::MassAssignmentSecurity
attr_accessor :name, :email, :logins_count
attr_protected :logins_count
attr_protected :logins_count, :email, as: :admin
end
Customer.protected_attributes
# => #<ActiveModel::MassAssignmentSecurity::BlackList: {"logins_count"}>
Customer.protected_attributes(:default)
# => #<ActiveModel::MassAssignmentSecurity::BlackList: {"logins_count"}>
Customer.protected_attributes(:admin)
# => #<ActiveModel::MassAssignmentSecurity::BlackList: {"logins_count", "email"}>
221 222 223 |
# File 'lib/active_model/mass_assignment_security.rb', line 221 def protected_attributes(role = :default) protected_attributes_configs[role] end |