pax_global_header 0000666 0000000 0000000 00000000064 12551267773 0014531 g ustar 00root root 0000000 0000000 52 comment=0421e825911b05a77c6521171b43070c9e6c4b35
protected_attributes-1.1.3/ 0000775 0000000 0000000 00000000000 12551267773 0015772 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/.gitignore 0000664 0000000 0000000 00000000072 12551267773 0017761 0 ustar 00root root 0000000 0000000 *.gem
*.rbc
.bundle
*.lock
pkg
.ruby-version
.ruby-gemset
protected_attributes-1.1.3/.travis.yml 0000664 0000000 0000000 00000001275 12551267773 0020110 0 ustar 00root root 0000000 0000000 language: ruby
sudo: false
cache: bundler
rvm:
- 1.9.3
- 2.0.0
- 2.1
- 2.2
gemfile:
- gemfiles/Gemfile-rails-4.0-stable
- gemfiles/Gemfile-rails-4.1-stable
- gemfiles/Gemfile-rails-4.2-stable
- gemfiles/Gemfile-rails-4.0
- gemfiles/Gemfile-rails-4.1
- gemfiles/Gemfile-rails-4.2
notifications:
email: false
irc:
on_success: change
on_failure: always
channels:
- "irc.freenode.org#rails-contrib"
campfire:
on_success: change
on_failure: always
rooms:
- secure: "RuC26E0TkxKzIQfqLuSHphe5FlgC1ULzhGpkZXqht3oDQjAuR+EmslxdWS9c\nVWwEr7PA+jnEp/8+sYM8TqHgLxFDHTTC6DgQoNNUY/Ti+mEyZunOPmXWP4UG\n6NLwr/rIuP1DEmDa6/q8V7qGn++SJrm1m4emGU4PbYNu6e6Nihc="
protected_attributes-1.1.3/CHANGELOG.md 0000664 0000000 0000000 00000004115 12551267773 0017604 0 ustar 00root root 0000000 0000000 ## 1.1.3
* Fix deprecation code.
## 1.1.2
* Deprecate `config.active_record.whitelist_attributes`.
* Fix integration with associations.
## 1.1.1
* Fix strong parameters integration.
* Remove warnings
* Fix `find_or_*` and `first_or_*` methods integration.
## 1.1.0
* Integrate with strong parameters. This allows to migrate a codebase partially
from `protected_attributes` to `strong_parameters`. Every model that does not
use a protection macro (`attr_accessible` or `attr_protected`), will be
protected by strong parameters. The behavior stays the same for models, which
use a protection macro.
To fully restore the old behavior set:
config.action_controller.permit_all_parameters = true
Or add a callback to your controllers like this:
before_action { params.permit! }
Fixes #41.
## 1.0.9
* Fixes ThroughAssociation#build_record method on rails 4.1.10+
Fixes #60, #63
* Fixes build_association method on rails 4.2.0+
Fixes https://github.com/rails/rails/issues/18121
## 1.0.8 (June 16, 2014)
* Support Rails 4.0.6+ and 4.1.2+.
Fixes #35
## 1.0.7 (March 12, 2014)
* Fix STI support on Active Record <= 4.0.3.
## 1.0.6 (March 10, 2014)
* Support to Rails 4.1
* Fix `CollectionProxy#new` method.
Fixes #21
## 1.0.5 (November 1, 2013)
* Fix install error with Rails 4.0.1.
Related with https://github.com/bundler/bundler/issues/2583
## 1.0.4 (October 18, 2013)
* Avoid override the entire Active Record initialization.
Fixes rails/rails#12243
## 1.0.3 (June 29, 2013)
* Fix "uninitialized constant ActiveRecord::MassAssignmentSecurity::NestedAttributes::ClassMethods::REJECT_ALL_BLANK_PROC"
error when using `:all_blank` option.
Fixes #8
* Fix `NoMethodError` exception when calling `raise_nested_attributes_record_not_found`.
## 1.0.2 (June 25, 2013)
* Sync #initialize override to latest rails implementation
Fixes #14
## 1.0.1 (April 6, 2013)
* Fix "uninitialized constant `ActiveRecord::SchemaMigration`" error
when checking pending migrations.
Fixes rails/rails#10109
## 1.0.0 (January 22, 2013)
* First public version
protected_attributes-1.1.3/Gemfile 0000664 0000000 0000000 00000000076 12551267773 0017270 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gem 'rails', '~> 4.0'
gemspec
protected_attributes-1.1.3/LICENSE.txt 0000664 0000000 0000000 00000002061 12551267773 0017614 0 ustar 00root root 0000000 0000000 Copyright (c) 2012 Guillermo Iguaran
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. protected_attributes-1.1.3/README.md 0000664 0000000 0000000 00000007610 12551267773 0017255 0 ustar 00root root 0000000 0000000 # Protected Attributes
[](https://travis-ci.org/rails/protected_attributes)
Protect attributes from mass-assignment in Active Record models.
This plugin adds the class methods `attr_accessible` and `attr_protected` to your models to be able to declare white or black lists of attributes.
Note: This plugin will be officially supported until the release of Rails 5.0.
## Installation
Add this line to your application's `Gemfile`:
gem 'protected_attributes'
And then execute:
bundle install
## Usage
Mass assignment security provides an interface for protecting attributes from end-user injection. This plugin provides two class methods in Active Record classes to control access to their attributes. The `attr_protected` method takes a list of attributes that will be ignored in mass-assignment.
For example:
```ruby
attr_protected :admin
```
`attr_protected` also optionally takes a role option using `:as` which allows you to define multiple mass-assignment groupings. If no role is defined then attributes will be added to the `:default` role.
```ruby
attr_protected :last_login, :as => :admin
```
A much better way, because it follows the whitelist-principle, is the `attr_accessible` method. It is the exact opposite of `attr_protected`, because it takes a list of attributes that will be mass-assigned if present. Any other attributes will be ignored. This way you won’t forget to protect attributes when adding new ones in the course of development. Here is an example:
```ruby
attr_accessible :name
attr_accessible :name, :is_admin, :as => :admin
```
If you want to set a protected attribute, you will to have to assign it individually:
```ruby
params[:user] # => {:name => "owned", :is_admin => true}
@user = User.new(params[:user])
@user.is_admin # => false, not mass-assigned
@user.is_admin = true
@user.is_admin # => true
```
When assigning attributes in Active Record using `attributes=` the `:default` role will be used. To assign attributes using different roles you should use `assign_attributes` which accepts an optional `:as` options parameter. If no `:as` option is provided then the `:default` role will be used.
You can also bypass mass-assignment security by using the `:without_protection` option. Here is an example:
```ruby
@user = User.new
@user.assign_attributes(:name => 'Josh', :is_admin => true)
@user.name # => Josh
@user.is_admin # => false
@user.assign_attributes({ :name => 'Josh', :is_admin => true }, :as => :admin)
@user.name # => Josh
@user.is_admin # => true
@user.assign_attributes({ :name => 'Josh', :is_admin => true }, :without_protection => true)
@user.name # => Josh
@user.is_admin # => true
```
In a similar way, `new`, `create`, `create!`, `update_attributes` and `update_attributes!` methods all respect mass-assignment security and accept either `:as` or `:without_protection` options. For example:
```ruby
@user = User.new({ :name => 'Sebastian', :is_admin => true }, :as => :admin)
@user.name # => Sebastian
@user.is_admin # => true
@user = User.create({ :name => 'Sebastian', :is_admin => true }, :without_protection => true)
@user.name # => Sebastian
@user.is_admin # => true
```
By default the gem will use the strong parameters protection when assigning attribute, unless your model has `attr_accessible` or `attr_protected` calls.
### Errors
By default, attributes in the params hash which are not allowed to be updated are just ignored. If you prefer an exception to be raised configure:
```ruby
config.active_record.mass_assignment_sanitizer = :strict
```
Any protected attributes violation raises `ActiveModel::MassAssignmentSecurity::Error` then.
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
protected_attributes-1.1.3/Rakefile 0000664 0000000 0000000 00000000314 12551267773 0017435 0 ustar 00root root 0000000 0000000 #!/usr/bin/env rake
require "bundler/gem_tasks"
require 'rake/testtask'
Rake::TestTask.new do |t|
t.libs = ["test"]
t.pattern = "test/**/*_test.rb"
t.ruby_opts = ['-w']
end
task :default => :test
protected_attributes-1.1.3/gemfiles/ 0000775 0000000 0000000 00000000000 12551267773 0017565 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/gemfiles/Gemfile-rails-4.0 0000664 0000000 0000000 00000000114 12551267773 0022463 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gem 'rails', '~> 4.0.13'
gemspec path: '..'
protected_attributes-1.1.3/gemfiles/Gemfile-rails-4.0-stable 0000664 0000000 0000000 00000000154 12551267773 0023737 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gem 'rails', github: 'rails/rails', branch: '4-0-stable'
gemspec path: '..'
protected_attributes-1.1.3/gemfiles/Gemfile-rails-4.1 0000664 0000000 0000000 00000000113 12551267773 0022463 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gem 'rails', '~> 4.1.9'
gemspec path: '..'
protected_attributes-1.1.3/gemfiles/Gemfile-rails-4.1-stable 0000664 0000000 0000000 00000000154 12551267773 0023740 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gem 'rails', github: 'rails/rails', branch: '4-1-stable'
gemspec path: '..'
protected_attributes-1.1.3/gemfiles/Gemfile-rails-4.2 0000664 0000000 0000000 00000000113 12551267773 0022464 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gem 'rails', '~> 4.2.0'
gemspec path: '..'
protected_attributes-1.1.3/gemfiles/Gemfile-rails-4.2-stable 0000664 0000000 0000000 00000000154 12551267773 0023741 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gem 'rails', github: 'rails/rails', branch: '4-2-stable'
gemspec path: '..'
protected_attributes-1.1.3/lib/ 0000775 0000000 0000000 00000000000 12551267773 0016540 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/lib/action_controller/ 0000775 0000000 0000000 00000000000 12551267773 0022260 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/lib/action_controller/accessible_params_wrapper.rb 0000664 0000000 0000000 00000001403 12551267773 0030003 0 ustar 00root root 0000000 0000000 require 'active_support/concern'
require 'action_controller'
require 'action_controller/metal/params_wrapper'
module ActionController
module ParamsWrapper
class Options # :nodoc:
undef :include
def include
return super if @include_set
m = model
synchronize do
return super if @include_set
@include_set = true
unless super || exclude
if m.respond_to?(:accessible_attributes) && m.accessible_attributes(:default).present?
self.include = m.accessible_attributes(:default).to_a
elsif m.respond_to?(:attribute_names) && m.attribute_names.any?
self.include = m.attribute_names
end
end
end
end
end
end
end
protected_attributes-1.1.3/lib/active_model/ 0000775 0000000 0000000 00000000000 12551267773 0021173 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/lib/active_model/mass_assignment_security.rb 0000664 0000000 0000000 00000032571 12551267773 0026652 0 ustar 00root root 0000000 0000000 require 'active_support/concern'
require 'active_support/core_ext/class/attribute'
require 'active_support/core_ext/string/inflections'
require 'active_model'
require 'active_model/mass_assignment_security/permission_set'
require 'active_model/mass_assignment_security/sanitizer'
module ActiveModel
# == Active Model Mass-Assignment Security
#
# 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 ActiveModel::MassAssignmentSecurity
#
# attr_accessible :first_name, :last_name
# attr_accessible :first_name, :last_name, :plan_id, as: :admin
#
# def update
# ...
# @account.update_attributes(account_params)
# ...
# end
#
# protected
#
# def account_params
# role = admin ? :admin : :default
# sanitize_for_mass_assignment(params[:account], role)
# end
#
# end
#
# === Configuration options
#
# * mass_assignment_sanitizer - Defines sanitize method. Possible
# values are:
# * :logger (default) - writes filtered attributes to logger
# * :strict - raise ActiveModel::MassAssignmentSecurity::Error
# on any protected attribute update.
#
# You can specify your own sanitizer object eg. MySanitizer.new.
# See ActiveModel::MassAssignmentSecurity::LoggerSanitizer for
# example implementation.
module MassAssignmentSecurity
extend ActiveSupport::Concern
include ActiveModel::ForbiddenAttributesProtection
included do
class_attribute :_accessible_attributes, instance_writer: false
class_attribute :_protected_attributes, instance_writer: false
class_attribute :_active_authorizer, instance_writer: false
class_attribute :_uses_mass_assignment_security, instance_writer: false
self._uses_mass_assignment_security = false
class_attribute :_mass_assignment_sanitizer, instance_writer: false
self.mass_assignment_sanitizer = :logger
end
module ClassMethods
# 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, options = {})
# sanitize_for_mass_assignment(values, options[: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: 'a@b.com', logins_count: 5 }, as: :default)
# customer.name # => "David"
# customer.email # => "a@b.com"
# customer.logins_count # => nil
#
# And using the :admin role:
#
# customer = Customer.new
# customer.assign_attributes({ name: 'David', email: 'a@b.com', logins_count: 5}, as: :admin)
# customer.name # => "David"
# customer.email # => nil
# customer.logins_count # => nil
#
# customer.email = 'c@d.com'
# customer.email # => "c@d.com"
#
# 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.
def attr_protected(*args)
options = args.extract_options!
role = options[: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._active_authorizer = self._protected_attributes
end
# 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, options = {})
# sanitize_for_mass_assignment(values, options[: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.credit_rating # => nil
#
# customer.credit_rating = 'Average'
# customer.credit_rating # => "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.credit_rating # => "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.
def attr_accessible(*args)
options = args.extract_options!
role = options[: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._active_authorizer = self._accessible_attributes
end
# 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
# # => #
#
# Customer.protected_attributes(:default)
# # => #
#
# Customer.protected_attributes(:admin)
# # => #
def protected_attributes(role = :default)
protected_attributes_configs[role]
end
# 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
# # => #
#
# Customer.accessible_attributes(:default)
# # => #
#
# Customer.accessible_attributes(:admin)
# # => #
def accessible_attributes(role = :default)
accessible_attributes_configs[role]
end
# 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.active_authorizers
# # => {
# # :admin=> #,
# # :default=>#
# # }
def active_authorizers
self._active_authorizer ||= protected_attributes_configs
end
alias active_authorizer active_authorizers
# 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
# # => #
def attributes_protected_by_default
[]
end
# 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
def mass_assignment_sanitizer=(value)
self._mass_assignment_sanitizer = if value.is_a?(Symbol)
const_get(:"#{value.to_s.camelize}Sanitizer").new(self)
else
value
end
end
private
def protected_attributes_configs
self._protected_attributes ||= begin
Hash.new { |h,k| h[k] = BlackList.new(attributes_protected_by_default) }
end
end
def accessible_attributes_configs
self._accessible_attributes ||= begin
Hash.new { |h,k| h[k] = WhiteList.new }
end
end
end
protected
def sanitize_for_mass_assignment(attributes, role = nil) #:nodoc:
if _uses_mass_assignment_security
_mass_assignment_sanitizer.sanitize(self.class, attributes, mass_assignment_authorizer(role))
else
sanitize_forbidden_attributes(attributes)
end
end
def mass_assignment_authorizer(role) #:nodoc:
self.class.active_authorizer[role || :default]
end
end
end
protected_attributes-1.1.3/lib/active_model/mass_assignment_security/ 0000775 0000000 0000000 00000000000 12551267773 0026315 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/lib/active_model/mass_assignment_security/permission_set.rb 0000664 0000000 0000000 00000001275 12551267773 0031712 0 ustar 00root root 0000000 0000000 require 'set'
module ActiveModel
module MassAssignmentSecurity
class PermissionSet < Set #:nodoc:
def +(values)
super(values.compact.map(&:to_s))
end
def include?(key)
super(remove_multiparameter_id(key))
end
def deny?(key)
raise NotImplementedError, "#deny?(key) supposed to be overwritten"
end
protected
def remove_multiparameter_id(key)
key.to_s.gsub(/\(.+/, '')
end
end
class WhiteList < PermissionSet #:nodoc:
def deny?(key)
!include?(key)
end
end
class BlackList < PermissionSet #:nodoc:
def deny?(key)
include?(key)
end
end
end
end
protected_attributes-1.1.3/lib/active_model/mass_assignment_security/sanitizer.rb 0000664 0000000 0000000 00000003700 12551267773 0030652 0 ustar 00root root 0000000 0000000 module ActiveModel
module MassAssignmentSecurity
class Sanitizer #:nodoc:
# Returns all attributes not denied by the authorizer.
def sanitize(klass, attributes, authorizer)
rejected = []
sanitized_attributes = attributes.reject do |key, value|
rejected << key if authorizer.deny?(key)
end
process_removed_attributes(klass, rejected) unless rejected.empty?
sanitized_attributes
end
protected
def process_removed_attributes(klass, attrs)
raise NotImplementedError, "#process_removed_attributes(klass, attrs) is intended to be overwritten by a subclass"
end
end
class LoggerSanitizer < Sanitizer #:nodoc:
def initialize(target)
@target = target
super()
end
def logger
@target.logger
end
def logger?
@target.respond_to?(:logger) && @target.logger
end
def backtrace
if defined? Rails.backtrace_cleaner
Rails.backtrace_cleaner.clean(caller)
else
caller
end
end
def process_removed_attributes(klass, attrs)
if logger?
logger.warn do
"WARNING: Can't mass-assign protected attributes for #{klass.name}: #{attrs.join(', ')}\n" +
backtrace.map { |trace| "\t#{trace}" }.join("\n")
end
end
end
end
class StrictSanitizer < Sanitizer #:nodoc:
def initialize(target = nil)
super()
end
def process_removed_attributes(klass, attrs)
unless (attrs - insensitive_attributes).empty?
raise ActiveModel::MassAssignmentSecurity::Error.new(klass, attrs)
end
end
def insensitive_attributes
['id']
end
end
class Error < StandardError #:nodoc:
def initialize(klass, attrs)
super("Can't mass-assign protected attributes for #{klass.name}: #{attrs.join(', ')}")
end
end
end
end
protected_attributes-1.1.3/lib/active_record/ 0000775 0000000 0000000 00000000000 12551267773 0021351 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/lib/active_record/mass_assignment_security.rb 0000664 0000000 0000000 00000002312 12551267773 0027016 0 ustar 00root root 0000000 0000000 require "active_record"
def active_record_40?
ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 0
end
require "active_record/mass_assignment_security/associations"
require "active_record/mass_assignment_security/attribute_assignment"
require "active_record/mass_assignment_security/core"
require "active_record/mass_assignment_security/nested_attributes"
require "active_record/mass_assignment_security/persistence"
require "active_record/mass_assignment_security/reflection"
require "active_record/mass_assignment_security/relation"
require "active_record/mass_assignment_security/validations"
require "active_record/mass_assignment_security/associations"
require "active_record/mass_assignment_security/inheritance"
class ActiveRecord::Base
include ActiveRecord::MassAssignmentSecurity::Core
include ActiveRecord::MassAssignmentSecurity::AttributeAssignment
include ActiveRecord::MassAssignmentSecurity::Persistence
include ActiveRecord::MassAssignmentSecurity::Validations
include ActiveRecord::MassAssignmentSecurity::NestedAttributes
include ActiveRecord::MassAssignmentSecurity::Inheritance
end
class ActiveRecord::SchemaMigration < ActiveRecord::Base
attr_accessible :version
end
protected_attributes-1.1.3/lib/active_record/mass_assignment_security/ 0000775 0000000 0000000 00000000000 12551267773 0026473 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/lib/active_record/mass_assignment_security/associations.rb 0000664 0000000 0000000 00000010337 12551267773 0031523 0 ustar 00root root 0000000 0000000 module ActiveRecord
module Associations
class Association
undef :build_record
def build_record(attributes, options)
reflection.build_association(attributes, options) do |record|
attributes = create_scope.except(*(record.changed - [reflection.foreign_key]))
record.assign_attributes(attributes, without_protection: true)
end
end
private :build_record
end
class CollectionAssociation
undef :build
undef :create
undef :create!
def build(attributes = {}, options = {}, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| build(attr, options, &block) }
else
add_to_target(build_record(attributes, options)) do |record|
yield(record) if block_given?
end
end
end
def create(attributes = {}, options = {}, &block)
create_record(attributes, options, &block)
end
def create!(attributes = {}, options = {}, &block)
create_record(attributes, options, true, &block)
end
def create_record(attributes, options, raise = false, &block)
unless owner.persisted?
raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
end
if attributes.is_a?(Array)
attributes.collect { |attr| create_record(attr, options, raise, &block) }
else
transaction do
add_to_target(build_record(attributes, options)) do |record|
yield(record) if block_given?
insert_record(record, true, raise)
end
end
end
end
private :create_record
end
class CollectionProxy
undef :create
undef :create!
def build(attributes = {}, options = {}, &block)
@association.build(attributes, options, &block)
end
alias_method :new, :build
def create(attributes = {}, options = {}, &block)
@association.create(attributes, options, &block)
end
def create!(attributes = {}, options = {}, &block)
@association.create!(attributes, options, &block)
end
end
module ThroughAssociation
undef :build_record if respond_to?(:build_record, false)
private
def build_record(attributes, options={})
inverse = source_reflection.inverse_of
target = through_association.target
if inverse && target && !target.is_a?(Array)
attributes[inverse.foreign_key] = target.id
end
super(attributes, options)
end
end
class HasManyThroughAssociation
undef :build_record
undef :options_for_through_record if respond_to?(:options_for_through_record, false)
def build_record(attributes, options = {})
ensure_not_nested
record = super(attributes, options)
inverse = source_reflection.inverse_of
if inverse
if inverse.macro == :has_many
record.send(inverse.name) << build_through_record(record)
elsif inverse.macro == :has_one
record.send("#{inverse.name}=", build_through_record(record))
end
end
record
end
private :build_record
def options_for_through_record
[through_scope_attributes, without_protection: true]
end
private :options_for_through_record
end
class SingularAssociation
undef :create
undef :create!
undef :build
def create(attributes = {}, options = {}, &block)
create_record(attributes, options, &block)
end
def create!(attributes = {}, options = {}, &block)
create_record(attributes, options, true, &block)
end
def build(attributes = {}, options = {})
record = build_record(attributes, options)
yield(record) if block_given?
set_new_record(record)
record
end
def create_record(attributes, options = {}, raise_error = false)
record = build_record(attributes, options)
yield(record) if block_given?
saved = record.save
set_new_record(record)
raise RecordInvalid.new(record) if !saved && raise_error
record
end
private :create_record
end
end
end
protected_attributes-1.1.3/lib/active_record/mass_assignment_security/attribute_assignment.rb 0000664 0000000 0000000 00000005671 12551267773 0033264 0 ustar 00root root 0000000 0000000 require 'active_model/mass_assignment_security'
require 'active_record'
module ActiveRecord
module MassAssignmentSecurity
module AttributeAssignment
extend ActiveSupport::Concern
include ActiveModel::MassAssignmentSecurity
module ClassMethods
private
# The primary key and inheritance column can never be set by mass-assignment for security reasons.
def attributes_protected_by_default
default = [ primary_key, inheritance_column ]
default << 'id' unless primary_key.eql? 'id'
default
end
end
# Allows you to set all the attributes for a particular mass-assignment
# security role by passing in a hash of attributes with keys matching
# the attribute names (which again matches the column names) and the role
# name using the :as option.
#
# To bypass mass-assignment security you can use the :without_protection => true
# option.
#
# class User < ActiveRecord::Base
# attr_accessible :name
# attr_accessible :name, :is_admin, :as => :admin
# end
#
# user = User.new
# user.assign_attributes({ :name => 'Josh', :is_admin => true })
# user.name # => "Josh"
# user.is_admin? # => false
#
# user = User.new
# user.assign_attributes({ :name => 'Josh', :is_admin => true }, :as => :admin)
# user.name # => "Josh"
# user.is_admin? # => true
#
# user = User.new
# user.assign_attributes({ :name => 'Josh', :is_admin => true }, :without_protection => true)
# user.name # => "Josh"
# user.is_admin? # => true
def assign_attributes(new_attributes, options = {})
return if new_attributes.blank?
attributes = new_attributes.stringify_keys
multi_parameter_attributes = []
nested_parameter_attributes = []
previous_options = @mass_assignment_options
@mass_assignment_options = options
unless options[:without_protection]
attributes = sanitize_for_mass_assignment(attributes, mass_assignment_role)
end
attributes.each do |k, v|
if k.include?("(")
multi_parameter_attributes << [ k, v ]
elsif v.is_a?(Hash)
nested_parameter_attributes << [ k, v ]
else
_assign_attribute(k, v)
end
end
assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty?
assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
ensure
@mass_assignment_options = previous_options
end
protected
def mass_assignment_options
@mass_assignment_options ||= {}
end
def mass_assignment_role
mass_assignment_options[:as] || :default
end
end
end
end
protected_attributes-1.1.3/lib/active_record/mass_assignment_security/core.rb 0000664 0000000 0000000 00000000447 12551267773 0027755 0 ustar 00root root 0000000 0000000 module ActiveRecord
module MassAssignmentSecurity
module Core
private
def init_attributes(attributes, options)
assign_attributes(attributes, options)
end
def init_internals
super
@mass_assignment_options = nil
end
end
end
end
protected_attributes-1.1.3/lib/active_record/mass_assignment_security/inheritance.rb 0000664 0000000 0000000 00000001543 12551267773 0031314 0 ustar 00root root 0000000 0000000 module ActiveRecord
module MassAssignmentSecurity
module Inheritance
extend ActiveSupport::Concern
module ClassMethods
private
# Detect the subclass from the inheritance column of attrs. If the inheritance column value
# is not self or a valid subclass, raises ActiveRecord::SubclassNotFound
# If this is a StrongParameters hash, and access to inheritance_column is not permitted,
# this will ignore the inheritance column and return nil
def subclass_from_attributes?(attrs)
active_authorizer[:default].deny?(inheritance_column) ? nil : super
end
# Support Active Record <= 4.0.3, which uses the old method signature.
def subclass_from_attrs(attrs)
active_authorizer[:default].deny?(inheritance_column) ? nil : super
end
end
end
end
end
protected_attributes-1.1.3/lib/active_record/mass_assignment_security/nested_attributes.rb 0000664 0000000 0000000 00000015222 12551267773 0032552 0 ustar 00root root 0000000 0000000 module ActiveRecord
module MassAssignmentSecurity
module NestedAttributes
extend ActiveSupport::Concern
module ClassMethods
REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |key, value| key == '_destroy' || value.blank? } }
def accepts_nested_attributes_for(*attr_names)
options = { :allow_destroy => false, :update_only => false }
options.update(attr_names.extract_options!)
options.assert_valid_keys(:allow_destroy, :reject_if, :limit, :update_only)
options[:reject_if] = REJECT_ALL_BLANK_PROC if options[:reject_if] == :all_blank
attr_names.each do |association_name|
if reflection = reflect_on_association(association_name)
reflection.options[:autosave] = true
add_autosave_association_callbacks(reflection)
nested_attributes_options = self.nested_attributes_options.dup
nested_attributes_options[association_name.to_sym] = options
self.nested_attributes_options = nested_attributes_options
type = (reflection.collection? ? :collection : :one_to_one)
generated_methods_module = active_record_40? ? generated_feature_methods : generated_association_methods
# def pirate_attributes=(attributes)
# assign_nested_attributes_for_one_to_one_association(:pirate, attributes, mass_assignment_options)
# end
generated_methods_module.module_eval <<-eoruby, __FILE__, __LINE__ + 1
if method_defined?(:#{association_name}_attributes=)
remove_method(:#{association_name}_attributes=)
end
def #{association_name}_attributes=(attributes)
assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes, mass_assignment_options)
end
eoruby
else
raise ArgumentError, "No association found for name `#{association_name}'. Has it been defined yet?"
end
end
end
end
private
UNASSIGNABLE_KEYS = %w( id _destroy )
def assign_nested_attributes_for_one_to_one_association(association_name, attributes, assignment_opts = {})
options = self.nested_attributes_options[association_name]
attributes = attributes.with_indifferent_access
if (options[:update_only] || !attributes['id'].blank?) && (record = send(association_name)) &&
(options[:update_only] || record.id.to_s == attributes['id'].to_s)
assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy], assignment_opts) unless call_reject_if(association_name, attributes)
elsif attributes['id'].present? && !assignment_opts[:without_protection]
raise_nested_attributes_record_not_found!(association_name, attributes['id'])
elsif !reject_new_record?(association_name, attributes)
method = "build_#{association_name}"
if respond_to?(method)
send(method, attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
else
raise ArgumentError, "Cannot build association `#{association_name}'. Are you trying to build a polymorphic one-to-one association?"
end
end
end
def assign_nested_attributes_for_collection_association(association_name, attributes_collection, assignment_opts = {})
options = self.nested_attributes_options[association_name]
unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
end
if limit = options[:limit]
limit = case limit
when Symbol
send(limit)
when Proc
limit.call
else
limit
end
if limit && attributes_collection.size > limit
raise TooManyRecords, "Maximum #{limit} records are allowed. Got #{attributes_collection.size} records instead."
end
end
if attributes_collection.is_a? Hash
keys = attributes_collection.keys
attributes_collection = if keys.include?('id') || keys.include?(:id)
[attributes_collection]
else
attributes_collection.values
end
end
association = association(association_name)
existing_records = if association.loaded?
association.target
else
attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact
attribute_ids.empty? ? [] : association.scope.where(association.klass.primary_key => attribute_ids)
end
attributes_collection.each do |attributes|
attributes = attributes.with_indifferent_access
if attributes['id'].blank?
unless reject_new_record?(association_name, attributes)
association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
end
elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s }
unless association.loaded? || call_reject_if(association_name, attributes)
# Make sure we are operating on the actual object which is in the association's
# proxy_target array (either by finding it, or adding it if not found)
target_record = association.target.detect { |record| record == existing_record }
if target_record
existing_record = target_record
else
association.add_to_target(existing_record)
end
end
if !call_reject_if(association_name, attributes)
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy], assignment_opts)
end
elsif assignment_opts[:without_protection]
association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
else
raise_nested_attributes_record_not_found!(association_name, attributes['id'])
end
end
end
def assign_to_or_mark_for_destruction(record, attributes, allow_destroy, assignment_opts)
record.assign_attributes(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
record.mark_for_destruction if has_destroy_flag?(attributes) && allow_destroy
end
def unassignable_keys(assignment_opts)
assignment_opts[:without_protection] ? UNASSIGNABLE_KEYS - %w[id] : UNASSIGNABLE_KEYS
end
end
end
end
protected_attributes-1.1.3/lib/active_record/mass_assignment_security/persistence.rb 0000664 0000000 0000000 00000007055 12551267773 0031353 0 ustar 00root root 0000000 0000000 require 'active_support/concern'
module ActiveRecord
module MassAssignmentSecurity
# = Active Record Persistence
module Persistence
extend ActiveSupport::Concern
module ClassMethods
# Creates an object (or multiple objects) and saves it to the database, if validations pass.
# The resulting object is returned whether the object was saved successfully to the database or not.
#
# The +attributes+ parameter can be either a Hash or an Array of Hashes. These Hashes describe the
# attributes on the objects that are to be created.
#
# +create+ respects mass-assignment security and accepts either +:as+ or +:without_protection+ options
# in the +options+ parameter.
#
# ==== Examples
# # Create a single new object
# User.create(:first_name => 'Jamie')
#
# # Create a single new object using the :admin mass-assignment security role
# User.create({ :first_name => 'Jamie', :is_admin => true }, :as => :admin)
#
# # Create a single new object bypassing mass-assignment security
# User.create({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true)
#
# # Create an Array of new objects
# User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
#
# # Create a single object and pass it into a block to set other attributes.
# User.create(:first_name => 'Jamie') do |u|
# u.is_admin = false
# end
#
# # Creating an Array of new objects using a block, where the block is executed for each object:
# User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
# u.is_admin = false
# end
def create(attributes = nil, options = {}, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| create(attr, options, &block) }
else
object = new(attributes, options, &block)
object.save
object
end
end
end
# Updates the attributes of the model from the passed-in hash and saves the
# record, all wrapped in a transaction. If the object is invalid, the saving
# will fail and false will be returned.
#
# When updating model attributes, mass-assignment security protection is respected.
# If no +:as+ option is supplied then the +:default+ role will be used.
# If you want to bypass the forbidden attributes protection then you can do so using
# the +:without_protection+ option.
def update(attributes, options = {})
# The following transaction covers any possible database side-effects of the
# attributes assignment. For example, setting the IDs of a child collection.
with_transaction_returning_status do
assign_attributes(attributes, options)
save
end
end
alias :update_attributes :update
# Updates its receiver just like +update_attributes+ but calls save! instead
# of +save+, so an exception is raised if the record is invalid.
def update!(attributes, options = {})
# The following transaction covers any possible database side-effects of the
# attributes assignment. For example, setting the IDs of a child collection.
with_transaction_returning_status do
assign_attributes(attributes, options)
save!
end
end
alias :update_attributes! :update!
end
end
end
protected_attributes-1.1.3/lib/active_record/mass_assignment_security/reflection.rb 0000664 0000000 0000000 00000000704 12551267773 0031153 0 ustar 00root root 0000000 0000000 module ActiveRecord
module Reflection
if defined?(AbstractReflection)
class AbstractReflection
undef :build_association
def build_association(*options, &block)
klass.new(*options, &block)
end
end
else
class AssociationReflection
undef :build_association
def build_association(*options, &block)
klass.new(*options, &block)
end
end
end
end
end
protected_attributes-1.1.3/lib/active_record/mass_assignment_security/relation.rb 0000664 0000000 0000000 00000005551 12551267773 0030643 0 ustar 00root root 0000000 0000000 module ActiveRecord
class Relation
undef :first_or_create
undef :first_or_create!
undef :first_or_initialize
undef :find_or_initialize_by
undef :find_or_create_by
undef :find_or_create_by!
# Tries to load the first record; if it fails, then create is called with the same arguments as this method.
#
# Expects arguments in the same format as +Base.create+.
#
# ==== Examples
# # Find the first user named Penélope or create a new one.
# User.where(:first_name => 'Penélope').first_or_create
# # =>
#
# # Find the first user named Penélope or create a new one.
# # We already have one so the existing record will be returned.
# User.where(:first_name => 'Penélope').first_or_create
# # =>
#
# # Find the first user named Scarlett or create a new one with a particular last name.
# User.where(:first_name => 'Scarlett').first_or_create(:last_name => 'Johansson')
# # =>
#
# # Find the first user named Scarlett or create a new one with a different last name.
# # We already have one so the existing record will be returned.
# User.where(:first_name => 'Scarlett').first_or_create do |user|
# user.last_name = "O'Hara"
# end
# # =>
def first_or_create(attributes = nil, options = {}, &block)
first || create(attributes, options, &block)
end
# Like first_or_create but calls create! so an exception is raised if the created record is invalid.
#
# Expects arguments in the same format as Base.create!.
def first_or_create!(attributes = nil, options = {}, &block)
first || create!(attributes, options, &block)
end
# Like first_or_create but calls new instead of create.
#
# Expects arguments in the same format as Base.new.
def first_or_initialize(attributes = nil, options = {}, &block)
first || new(attributes, options, &block)
end
def find_or_initialize_by(attributes, options = {}, &block)
find_by(attributes) || new(attributes, options, &block)
end
def find_or_create_by(attributes, options = {}, &block)
find_by(attributes) || create(attributes, options, &block)
end
def find_or_create_by!(attributes, options = {}, &block)
find_by(attributes) || create!(attributes, options, &block)
end
end
module QueryMethods
protected
def sanitize_forbidden_attributes(attributes) #:nodoc:
if !model._uses_mass_assignment_security
sanitize_for_mass_assignment(attributes)
else
attributes
end
end
end
end
protected_attributes-1.1.3/lib/active_record/mass_assignment_security/validations.rb 0000664 0000000 0000000 00000001272 12551267773 0031337 0 ustar 00root root 0000000 0000000 require 'active_support/concern'
module ActiveRecord
module MassAssignmentSecurity
module Validations
extend ActiveSupport::Concern
module ClassMethods
# Creates an object just like Base.create but calls save! instead of +save+
# so an exception is raised if the record is invalid.
def create!(attributes = nil, options = {}, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| create!(attr, options, &block) }
else
object = new(attributes, options)
yield(object) if block_given?
object.save!
object
end
end
end
end
end
end
protected_attributes-1.1.3/lib/protected_attributes.rb 0000664 0000000 0000000 00000000602 12551267773 0023322 0 ustar 00root root 0000000 0000000 require "active_model/mass_assignment_security"
require "protected_attributes/railtie" if defined? Rails::Railtie
require "protected_attributes/version"
ActiveSupport.on_load :active_record do
require "active_record/mass_assignment_security"
end
ActiveSupport.on_load :action_controller do
require "action_controller/accessible_params_wrapper"
end
module ProtectedAttributes
end
protected_attributes-1.1.3/lib/protected_attributes/ 0000775 0000000 0000000 00000000000 12551267773 0022777 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/lib/protected_attributes/railtie.rb 0000664 0000000 0000000 00000000710 12551267773 0024753 0 ustar 00root root 0000000 0000000 module ProtectedAttributes
class Railtie < ::Rails::Railtie
initializer "protected_attributes.active_record", :before => "active_record.set_configs" do |app|
if app.config.respond_to?(:active_record) && app.config.active_record.delete(:whitelist_attributes)
ActiveSupport::Deprecation.warn "config.active_record.whitelist_attributes is deprecated and have no effect. Remove its call from the configuration."
end
end
end
end
protected_attributes-1.1.3/lib/protected_attributes/version.rb 0000664 0000000 0000000 00000000063 12551267773 0025010 0 ustar 00root root 0000000 0000000 module ProtectedAttributes
VERSION = "1.1.3"
end
protected_attributes-1.1.3/protected_attributes.gemspec 0000664 0000000 0000000 00000002110 12551267773 0023570 0 ustar 00root root 0000000 0000000 # -*- encoding: utf-8 -*-
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'protected_attributes/version'
Gem::Specification.new do |gem|
gem.name = "protected_attributes"
gem.version = ProtectedAttributes::VERSION
gem.authors = ["David Heinemeier Hansson"]
gem.email = ["david@loudthinking.com"]
gem.description = %q{Protect attributes from mass assignment}
gem.summary = %q{Protect attributes from mass assignment in Active Record models}
gem.homepage = "https://github.com/rails/protected_attributes"
gem.license = "MIT"
gem.files = Dir["LICENSE.txt", "README.md", "lib/**/*"]
gem.require_paths = ["lib"]
gem.add_dependency "activemodel", ">= 4.0.1", "< 5.0"
gem.add_development_dependency "activerecord", ">= 4.0.1", "< 5.0"
gem.add_development_dependency "actionpack", ">= 4.0.1", "< 5.0"
gem.add_development_dependency "railties", ">= 4.0.1", "< 5.0"
gem.add_development_dependency "sqlite3"
gem.add_development_dependency "mocha"
end
protected_attributes-1.1.3/test/ 0000775 0000000 0000000 00000000000 12551267773 0016751 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/test/abstract_unit.rb 0000664 0000000 0000000 00000010436 12551267773 0022144 0 ustar 00root root 0000000 0000000 require 'action_dispatch'
require 'action_controller'
require 'active_support/dependencies'
def active_support_4_0?
ActiveSupport::VERSION::MAJOR == 4 && ActiveSupport::VERSION::MINOR == 0
end
if active_support_4_0?
require 'active_support/core_ext/class/attribute_accessors'
else
require 'active_support/core_ext/module/attribute_accessors'
end
module SetupOnce
extend ActiveSupport::Concern
included do
cattr_accessor :setup_once_block
self.setup_once_block = nil
setup :run_setup_once
end
module ClassMethods
def setup_once(&block)
self.setup_once_block = block
end
end
private
def run_setup_once
if self.setup_once_block
self.setup_once_block.call
self.setup_once_block = nil
end
end
end
SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
module ActiveSupport
class TestCase
include SetupOnce
# Hold off drawing routes until all the possible controller classes
# have been loaded.
setup_once do
SharedTestRoutes.draw do
get ':controller(/:action)'
end
ActionDispatch::IntegrationTest.app.routes.draw do
get ':controller(/:action)'
end
end
end
end
class RoutedRackApp
attr_reader :routes
def initialize(routes, &blk)
@routes = routes
@stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes)
end
def call(env)
@stack.call(env)
end
end
class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
setup do
@routes = SharedTestRoutes
end
def self.build_app(routes = nil)
RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware|
middleware.use "ActionDispatch::DebugExceptions"
middleware.use "ActionDispatch::Callbacks"
middleware.use "ActionDispatch::ParamsParser"
middleware.use "ActionDispatch::Cookies"
middleware.use "ActionDispatch::Flash"
middleware.use "Rack::Head"
yield(middleware) if block_given?
end
end
self.app = build_app
# Stub Rails dispatcher so it does not get controller references and
# simply return the controller#action as Rack::Body.
class StubDispatcher < ::ActionDispatch::Routing::RouteSet::Dispatcher
protected
def controller_reference(controller_param)
controller_param
end
def dispatch(controller, action, env)
[200, {'Content-Type' => 'text/html'}, ["#{controller}##{action}"]]
end
end
def self.stub_controllers
old_dispatcher = ActionDispatch::Routing::RouteSet::Dispatcher
ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, StubDispatcher }
yield ActionDispatch::Routing::RouteSet.new
ensure
ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, old_dispatcher }
end
def with_routing(&block)
temporary_routes = ActionDispatch::Routing::RouteSet.new
old_app, self.class.app = self.class.app, self.class.build_app(temporary_routes)
old_routes = SharedTestRoutes
silence_warnings { Object.const_set(:SharedTestRoutes, temporary_routes) }
yield temporary_routes
ensure
self.class.app = old_app
silence_warnings { Object.const_set(:SharedTestRoutes, old_routes) }
end
def with_autoload_path(path)
path = File.join(File.dirname(__FILE__), "fixtures", path)
if ActiveSupport::Dependencies.autoload_paths.include?(path)
yield
else
begin
ActiveSupport::Dependencies.autoload_paths << path
yield
ensure
ActiveSupport::Dependencies.autoload_paths.reject! {|p| p == path}
ActiveSupport::Dependencies.clear
end
end
end
end
module ActionController
class Base
include ActionController::Testing
# This stub emulates the Railtie including the URL helpers from a Rails application
include SharedTestRoutes.url_helpers
include SharedTestRoutes.mounted_helpers
#self.view_paths = FIXTURE_LOAD_PATH
def self.test_routes(&block)
routes = ActionDispatch::Routing::RouteSet.new
routes.draw(&block)
include routes.url_helpers
end
end
class TestCase
include ActionDispatch::TestProcess
setup do
@routes = SharedTestRoutes
end
end
end
protected_attributes-1.1.3/test/accessible_params_wrapper_test.rb 0000664 0000000 0000000 00000004775 12551267773 0025552 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'abstract_unit'
require 'action_controller/accessible_params_wrapper'
module ParamsWrapperTestHelp
def with_default_wrapper_options(&block)
@controller.class._set_wrapper_options({:format => [:json]})
@controller.class.inherited(@controller.class)
yield
end
def assert_parameters(expected)
assert_equal expected, self.class.controller_class.last_parameters
end
end
class AccessibleParamsWrapperTest < ActionController::TestCase
include ParamsWrapperTestHelp
class UsersController < ActionController::Base
class << self
attr_accessor :last_parameters
end
def parse
self.class.last_parameters = request.params.except(:controller, :action)
head :ok
end
end
class User; end
class Person; end
tests UsersController
def teardown
UsersController.last_parameters = nil
end
def test_derived_wrapped_keys_from_matching_model
User.expects(:respond_to?).with(:accessible_attributes).returns(false)
User.expects(:respond_to?).with(:attribute_names).returns(true)
User.expects(:attribute_names).twice.returns(["username"])
with_default_wrapper_options do
@request.env['CONTENT_TYPE'] = 'application/json'
post :parse, { 'username' => 'sikachu', 'title' => 'Developer' }
assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu' }})
end
end
def test_derived_wrapped_keys_from_specified_model
with_default_wrapper_options do
Person.expects(:respond_to?).with(:accessible_attributes).returns(false)
Person.expects(:respond_to?).with(:attribute_names).returns(true)
Person.expects(:attribute_names).twice.returns(["username"])
UsersController.wrap_parameters Person
@request.env['CONTENT_TYPE'] = 'application/json'
post :parse, { 'username' => 'sikachu', 'title' => 'Developer' }
assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }})
end
end
def test_accessible_wrapped_keys_from_matching_model
User.expects(:respond_to?).with(:accessible_attributes).returns(true)
User.expects(:accessible_attributes).with(:default).twice.returns(["username"])
with_default_wrapper_options do
@request.env['CONTENT_TYPE'] = 'application/json'
post :parse, { 'username' => 'sikachu', 'title' => 'Developer' }
assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu' }})
end
end
end
protected_attributes-1.1.3/test/ar_helper.rb 0000664 0000000 0000000 00000004000 12551267773 0021231 0 ustar 00root root 0000000 0000000 require 'active_record'
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Schema.verbose = false
ActiveRecord::Schema.define do
create_table :accounts, :force => true do |t|
t.integer :firm_id
t.string :firm_name
t.integer :credit_limit
end
create_table :companies, :force => true do |t|
t.string :type
t.integer :firm_id
t.string :firm_name
t.string :name
t.integer :client_of
t.integer :rating, :default => 1
t.integer :account_id
t.string :description, :default => ""
end
add_index :companies, [:firm_id, :type, :rating], :name => "company_index"
add_index :companies, [:firm_id, :type], :name => "company_partial_index", :where => "rating > 10"
create_table :keyboards, :force => true, :id => false do |t|
t.primary_key :key_number
t.string :name
end
create_table :people, :force => true do |t|
t.string :first_name, :null => false
t.string :gender, :limit => 1
t.string :comments
t.references :best_friend
t.references :best_friend_of
t.timestamps null: false
end
create_table :subscribers, :force => true, :id => false do |t|
t.string :nick, :null => false
t.string :name
end
add_index :subscribers, :nick, :unique => true
create_table :books, :force => true do |t|
t.string :title
end
create_table :tasks, :force => true do |t|
t.datetime :starting
t.datetime :ending
end
create_table :pirates, :force => true do |t|
t.string :name
end
create_table :groups, :force => true do |t|
end
create_table :memberships, :force => true do |t|
t.integer "group_id"
t.integer "pirate_id"
end
create_table :teams, :force => true
create_table :wolves, :force => true
create_table :vampires, :force => true
create_table :battles, :force => true do |t|
t.integer "team_id"
t.integer "battle_id"
t.string "battle_type"
end
end
QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type')
protected_attributes-1.1.3/test/attribute_sanitization_test.rb 0000664 0000000 0000000 00000122335 12551267773 0025142 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'ar_helper'
require 'active_record/mass_assignment_security'
require 'models/battle'
require 'models/company'
require 'models/group'
require 'models/keyboard'
require 'models/membership'
require 'models/person'
require 'models/pirate'
require 'models/subscriber'
require 'models/task'
require 'models/team'
require 'models/vampire'
require 'models/wolf'
module MassAssignmentTestHelpers
def teardown
ActiveRecord::Base.send(:descendants).each do |klass|
begin
klass.delete_all
rescue
end
end
end
def attributes_hash
{
:id => 5,
:first_name => 'Josh',
:gender => 'm',
:comments => 'rides a sweet bike'
}
end
def assert_default_attributes(person, create = false)
unless create
assert_nil person.id
else
assert !!person.id
end
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_nil person.comments
end
def assert_admin_attributes(person, create = false)
unless create
assert_nil person.id
else
assert !!person.id
end
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_equal 'rides a sweet bike', person.comments
end
def assert_all_attributes(person)
assert_equal 5, person.id
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_equal 'rides a sweet bike', person.comments
end
def with_strict_sanitizer
ActiveRecord::Base.mass_assignment_sanitizer = :strict
yield
ensure
ActiveRecord::Base.mass_assignment_sanitizer = :logger
end
end
module MassAssignmentRelationTestHelpers
def setup
super
@person = LoosePerson.create(attributes_hash)
end
end
class AttributeSanitizationTest < ActiveSupport::TestCase
include MassAssignmentTestHelpers
def test_customized_primary_key_remains_protected
subscriber = Subscriber.new(:nick => 'webster123', :name => 'nice try')
assert_nil subscriber.id
keyboard = Keyboard.new(:key_number => 9, :name => 'nice try')
assert_nil keyboard.id
end
def test_customized_primary_key_remains_protected_when_referred_to_as_id
subscriber = Subscriber.new(:id => 'webster123', :name => 'nice try')
assert_nil subscriber.id
keyboard = Keyboard.new(:id => 9, :name => 'nice try')
assert_nil keyboard.id
end
def test_mass_assigning_invalid_attribute
firm = Firm.new
assert_raise(ActiveRecord::UnknownAttributeError) do
firm.attributes = { "id" => 5, "type" => "Client", "i_dont_even_exist" => 20 }
end
end
def test_mass_assigning_does_not_choke_on_nil
assert_nil Firm.new.assign_attributes(nil)
end
def test_mass_assigning_does_not_choke_on_empty_hash
assert_nil Firm.new.assign_attributes({})
end
def test_assign_attributes_uses_default_role_when_no_role_is_provided
p = LoosePerson.new
p.assign_attributes(attributes_hash)
assert_default_attributes(p)
end
def test_assign_attributes_skips_mass_assignment_security_protection_when_without_protection_is_used
p = LoosePerson.new
p.assign_attributes(attributes_hash, :without_protection => true)
assert_all_attributes(p)
end
def test_assign_attributes_with_default_role_and_attr_protected_attributes
p = LoosePerson.new
p.assign_attributes(attributes_hash, :as => :default)
assert_default_attributes(p)
end
def test_assign_attributes_with_admin_role_and_attr_protected_attributes
p = LoosePerson.new
p.assign_attributes(attributes_hash, :as => :admin)
assert_admin_attributes(p)
end
def test_assign_attributes_with_default_role_and_attr_accessible_attributes
p = TightPerson.new
p.assign_attributes(attributes_hash, :as => :default)
assert_default_attributes(p)
end
def test_assign_attributes_with_admin_role_and_attr_accessible_attributes
p = TightPerson.new
p.assign_attributes(attributes_hash, :as => :admin)
assert_admin_attributes(p)
end
def test_new_with_attr_accessible_attributes
p = TightPerson.new(attributes_hash)
assert_default_attributes(p)
end
def test_new_with_attr_protected_attributes
p = LoosePerson.new(attributes_hash)
assert_default_attributes(p)
end
def test_create_with_attr_accessible_attributes
p = TightPerson.create(attributes_hash)
assert_default_attributes(p, true)
end
def test_create_with_attr_protected_attributes
p = LoosePerson.create(attributes_hash)
assert_default_attributes(p, true)
end
def test_new_with_admin_role_with_attr_accessible_attributes
p = TightPerson.new(attributes_hash, :as => :admin)
assert_admin_attributes(p)
end
def test_new_with_admin_role_with_attr_protected_attributes
p = LoosePerson.new(attributes_hash, :as => :admin)
assert_admin_attributes(p)
end
def test_create_with_admin_role_with_attr_accessible_attributes
p = TightPerson.create(attributes_hash, :as => :admin)
assert_admin_attributes(p, true)
end
def test_create_with_admin_role_with_attr_protected_attributes
p = LoosePerson.create(attributes_hash, :as => :admin)
assert_admin_attributes(p, true)
end
def test_create_with_bang_with_admin_role_with_attr_accessible_attributes
p = TightPerson.create!(attributes_hash, :as => :admin)
assert_admin_attributes(p, true)
end
def test_create_with_bang_with_admin_role_with_attr_protected_attributes
p = LoosePerson.create!(attributes_hash, :as => :admin)
assert_admin_attributes(p, true)
end
def test_new_with_without_protection_with_attr_accessible_attributes
p = TightPerson.new(attributes_hash, :without_protection => true)
assert_all_attributes(p)
end
def test_new_with_without_protection_with_attr_protected_attributes
p = LoosePerson.new(attributes_hash, :without_protection => true)
assert_all_attributes(p)
end
def test_create_with_without_protection_with_attr_accessible_attributes
p = TightPerson.create(attributes_hash, :without_protection => true)
assert_all_attributes(p)
end
def test_create_with_without_protection_with_attr_protected_attributes
p = LoosePerson.create(attributes_hash, :without_protection => true)
assert_all_attributes(p)
end
def test_create_with_bang_with_without_protection_with_attr_accessible_attributes
p = TightPerson.create!(attributes_hash, :without_protection => true)
assert_all_attributes(p)
end
def test_create_with_bang_with_without_protection_with_attr_protected_attributes
p = LoosePerson.create!(attributes_hash, :without_protection => true)
assert_all_attributes(p)
end
def test_protection_against_class_attribute_writers
attribute_writers = [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names,
:default_timezone, :schema_format, :lock_optimistically, :timestamped_migrations, :default_scopes,
:connection_handler, :nested_attributes_options,
:attribute_method_matchers, :time_zone_aware_attributes, :skip_time_zone_conversion_for_attributes]
attribute_writers.push(:_attr_readonly) if active_record_40?
attribute_writers.each do |method|
assert_respond_to Task, method
assert_respond_to Task, "#{method}="
assert_respond_to Task.new, method unless method == :configurations && !active_record_40?
assert !Task.new.respond_to?("#{method}=")
end
end
def test_new_with_protected_inheritance_column
firm = Company.new(type: "Firm")
assert_equal Company, firm.class
end
def test_new_with_accessible_inheritance_column
corporation = Corporation.new(type: "SpecialCorporation")
assert_equal SpecialCorporation, corporation.class
end
def test_new_with_invalid_inheritance_column_class
assert_raise(ActiveRecord::SubclassNotFound) { Corporation.new(type: "InvalidCorporation") }
end
def test_new_with_unrelated_inheritance_column_class
assert_raise(ActiveRecord::SubclassNotFound) { Corporation.new(type: "Person") }
end
def test_update_attributes_as_admin
person = TightPerson.create({ "first_name" => 'Joshua' })
person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
person.reload
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_equal 'from NZ', person.comments
end
def test_update_attributes_without_protection
person = TightPerson.create({ "first_name" => 'Joshua' })
person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
person.reload
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_equal 'from NZ', person.comments
end
def test_update_attributes_with_bang_as_admin
person = TightPerson.create({ "first_name" => 'Joshua' })
person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
person.reload
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_equal 'from NZ', person.comments
end
def test_update_attributes_with_bang_without_protection
person = TightPerson.create({ "first_name" => 'Joshua' })
person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
person.reload
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_equal 'from NZ', person.comments
end
def test_update_as_admin
person = TightPerson.create({ "first_name" => 'Joshua' })
person.update({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
person.reload
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_equal 'from NZ', person.comments
end
def test_update_without_protection
person = TightPerson.create({ "first_name" => 'Joshua' })
person.update({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
person.reload
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_equal 'from NZ', person.comments
end
def test_update_with_bang_as_admin
person = TightPerson.create({ "first_name" => 'Joshua' })
person.update!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
person.reload
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_equal 'from NZ', person.comments
end
def test_update_with_bang_without_protection
person = TightPerson.create({ "first_name" => 'Joshua' })
person.update!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
person.reload
assert_equal 'Josh', person.first_name
assert_equal 'm', person.gender
assert_equal 'from NZ', person.comments
end
end
class MassAssignmentSecurityRelationTest < ActiveSupport::TestCase
include MassAssignmentTestHelpers
def test_find_or_initialize_by_with_attr_accessible_attributes
p = TightPerson.where(first_name: 'Josh').first_or_initialize(attributes_hash)
assert_default_attributes(p)
end
def test_find_or_initialize_by_with_admin_role_with_attr_accessible_attributes
p = TightPerson.where(first_name: 'Josh').first_or_initialize(attributes_hash, as: :admin)
assert_admin_attributes(p)
end
def test_find_or_initialize_by_with_attr_protected_attributes
p = LoosePerson.where(first_name: 'Josh').first_or_initialize(attributes_hash)
assert_default_attributes(p)
end
def test_find_or_initialize_by_with_admin_role_with_attr_protected_attributes
p = LoosePerson.where(first_name: 'Josh').first_or_initialize(attributes_hash, as: :admin)
assert_admin_attributes(p)
end
def test_find_or_create_by_with_attr_accessible_attributes
p = TightPerson.where(first_name: 'Josh').first_or_create(attributes_hash)
assert_default_attributes(p, true)
end
def test_find_or_create_by_with_admin_role_with_attr_accessible_attributes
p = TightPerson.where(first_name: 'Josh').first_or_create(attributes_hash, as: :admin)
assert_admin_attributes(p, true)
end
def test_find_or_create_by_with_attr_protected_attributes
p = LoosePerson.where(first_name: 'Josh').first_or_create(attributes_hash)
assert_default_attributes(p, true)
end
def test_find_or_create_by_with_admin_role_with_attr_protected_attributes
p = LoosePerson.where(first_name: 'Josh').first_or_create(attributes_hash, as: :admin)
assert_admin_attributes(p, true)
end
def test_find_or_create_by_bang_with_attr_accessible_attributes
p = TightPerson.where(first_name: 'Josh').first_or_create!(attributes_hash)
assert_default_attributes(p, true)
end
def test_find_or_create_by_bang_with_admin_role_with_attr_accessible_attributes
p = TightPerson.where(first_name: 'Josh').first_or_create!(attributes_hash, as: :admin)
assert_admin_attributes(p, true)
end
def test_find_or_create_by_bang_with_attr_protected_attributes
p = LoosePerson.where(first_name: 'Josh').first_or_create!(attributes_hash)
assert_default_attributes(p, true)
end
def test_find_or_create_by_bang_with_admin_role_with_attr_protected_attributes
p = LoosePerson.where(first_name: 'Josh').first_or_create!(attributes_hash, as: :admin)
assert_admin_attributes(p, true)
end
end
class MassAssignmentSecurityFindersTest < ActiveSupport::TestCase
include MassAssignmentTestHelpers
def test_find_or_initialize_by_with_attr_accessible_attributes
p = TightPerson.find_or_initialize_by(attributes_hash)
assert_default_attributes(p)
end
def test_find_or_initialize_by_with_admin_role_with_attr_accessible_attributes
p = TightPerson.find_or_initialize_by(attributes_hash, as: :admin)
assert_admin_attributes(p)
end
def test_find_or_initialize_by_with_attr_protected_attributes
p = LoosePerson.find_or_initialize_by(attributes_hash)
assert_default_attributes(p)
end
def test_find_or_initialize_by_with_admin_role_with_attr_protected_attributes
p = LoosePerson.find_or_initialize_by(attributes_hash, as: :admin)
assert_admin_attributes(p)
end
def test_find_or_create_by_with_attr_accessible_attributes
p = TightPerson.find_or_create_by(attributes_hash)
assert_default_attributes(p, true)
end
def test_find_or_create_by_with_admin_role_with_attr_accessible_attributes
p = TightPerson.find_or_create_by(attributes_hash, as: :admin)
assert_admin_attributes(p, true)
end
def test_find_or_create_by_with_attr_protected_attributes
p = LoosePerson.find_or_create_by(attributes_hash)
assert_default_attributes(p, true)
end
def test_find_or_create_by_with_admin_role_with_attr_protected_attributes
p = LoosePerson.find_or_create_by(attributes_hash, as: :admin)
assert_admin_attributes(p, true)
end
def test_find_or_create_by_bang_with_attr_accessible_attributes
p = TightPerson.find_or_create_by!(attributes_hash)
assert_default_attributes(p, true)
end
def test_find_or_create_by_bang_with_admin_role_with_attr_accessible_attributes
p = TightPerson.find_or_create_by!(attributes_hash, as: :admin)
assert_admin_attributes(p, true)
end
def test_find_or_create_by_bang_with_attr_protected_attributes
p = LoosePerson.find_or_create_by!(attributes_hash)
assert_default_attributes(p, true)
end
def test_find_or_create_by_bang_with_admin_role_with_attr_protected_attributes
p = LoosePerson.find_or_create_by!(attributes_hash, as: :admin)
assert_admin_attributes(p, true)
end
end
if active_record_40?
# This class should be deleted when we remove activerecord-deprecated_finders as a
# dependency.
class MassAssignmentSecurityDeprecatedFindersTest < ActiveSupport::TestCase
include MassAssignmentTestHelpers
def setup
super
@deprecation_behavior = ActiveSupport::Deprecation.behavior
ActiveSupport::Deprecation.behavior = :silence
end
def teardown
super
ActiveSupport::Deprecation.behavior = @deprecation_behavior
end
def test_find_or_initialize_by_with_attr_accessible_attributes
p = TightPerson.find_or_initialize_by_first_name('Josh', attributes_hash)
assert_default_attributes(p)
end
def test_find_or_initialize_by_with_admin_role_with_attr_accessible_attributes
p = TightPerson.find_or_initialize_by_first_name('Josh', attributes_hash, :as => :admin)
assert_admin_attributes(p)
end
def test_find_or_initialize_by_with_attr_protected_attributes
p = LoosePerson.find_or_initialize_by_first_name('Josh', attributes_hash)
assert_default_attributes(p)
end
def test_find_or_initialize_by_with_admin_role_with_attr_protected_attributes
p = LoosePerson.find_or_initialize_by_first_name('Josh', attributes_hash, :as => :admin)
assert_admin_attributes(p)
end
def test_find_or_create_by_with_attr_accessible_attributes
p = TightPerson.find_or_create_by_first_name('Josh', attributes_hash)
assert_default_attributes(p, true)
end
def test_find_or_create_by_with_admin_role_with_attr_accessible_attributes
p = TightPerson.find_or_create_by_first_name('Josh', attributes_hash, :as => :admin)
assert_admin_attributes(p, true)
end
def test_find_or_create_by_with_attr_protected_attributes
p = LoosePerson.find_or_create_by_first_name('Josh', attributes_hash)
assert_default_attributes(p, true)
end
def test_find_or_create_by_with_admin_role_with_attr_protected_attributes
p = LoosePerson.find_or_create_by_first_name('Josh', attributes_hash, :as => :admin)
assert_admin_attributes(p, true)
end
end
end
class MassAssignmentSecurityHasOneRelationsTest < ActiveSupport::TestCase
include MassAssignmentTestHelpers
include MassAssignmentRelationTestHelpers
# build
def test_has_one_build_with_attr_protected_attributes
best_friend = @person.build_best_friend(attributes_hash)
assert_default_attributes(best_friend)
end
def test_has_one_build_with_attr_accessible_attributes
best_friend = @person.build_best_friend(attributes_hash)
assert_default_attributes(best_friend)
end
def test_has_one_build_with_admin_role_with_attr_protected_attributes
best_friend = @person.build_best_friend(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend)
end
def test_has_one_build_with_admin_role_with_attr_accessible_attributes
best_friend = @person.build_best_friend(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend)
end
def test_has_one_build_without_protection
best_friend = @person.build_best_friend(attributes_hash, :without_protection => true)
assert_all_attributes(best_friend)
end
def test_has_one_build_with_strict_sanitizer
with_strict_sanitizer do
best_friend = @person.build_best_friend(attributes_hash.except(:id, :comments))
assert_equal @person.id, best_friend.best_friend_id
end
end
# create
def test_has_one_create_with_attr_protected_attributes
best_friend = @person.create_best_friend(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_has_one_create_with_attr_accessible_attributes
best_friend = @person.create_best_friend(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_has_one_create_with_admin_role_with_attr_protected_attributes
best_friend = @person.create_best_friend(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_has_one_create_with_admin_role_with_attr_accessible_attributes
best_friend = @person.create_best_friend(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_has_one_create_without_protection
best_friend = @person.create_best_friend(attributes_hash, :without_protection => true)
assert_all_attributes(best_friend)
end
def test_has_one_create_with_strict_sanitizer
with_strict_sanitizer do
best_friend = @person.create_best_friend(attributes_hash.except(:id, :comments))
assert_equal @person.id, best_friend.best_friend_id
end
end
# create!
def test_has_one_create_with_bang_with_attr_protected_attributes
best_friend = @person.create_best_friend!(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_has_one_create_with_bang_with_attr_accessible_attributes
best_friend = @person.create_best_friend!(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes
best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes
best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_has_one_create_with_bang_without_protection
best_friend = @person.create_best_friend!(attributes_hash, :without_protection => true)
assert_all_attributes(best_friend)
end
def test_has_one_create_with_bang_with_strict_sanitizer
with_strict_sanitizer do
best_friend = @person.create_best_friend!(attributes_hash.except(:id, :comments))
assert_equal @person.id, best_friend.best_friend_id
end
end
end
class MassAssignmentSecurityBelongsToRelationsTest < ActiveSupport::TestCase
include MassAssignmentTestHelpers
include MassAssignmentRelationTestHelpers
# build
def test_belongs_to_build_with_attr_protected_attributes
best_friend = @person.build_best_friend_of(attributes_hash)
assert_default_attributes(best_friend)
end
def test_belongs_to_build_with_attr_accessible_attributes
best_friend = @person.build_best_friend_of(attributes_hash)
assert_default_attributes(best_friend)
end
def test_belongs_to_build_with_admin_role_with_attr_protected_attributes
best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend)
end
def test_belongs_to_build_with_admin_role_with_attr_accessible_attributes
best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend)
end
def test_belongs_to_build_without_protection
best_friend = @person.build_best_friend_of(attributes_hash, :without_protection => true)
assert_all_attributes(best_friend)
end
# create
def test_belongs_to_create_with_attr_protected_attributes
best_friend = @person.create_best_friend_of(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_belongs_to_create_with_attr_accessible_attributes
best_friend = @person.create_best_friend_of(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_belongs_to_create_with_admin_role_with_attr_protected_attributes
best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_belongs_to_create_with_admin_role_with_attr_accessible_attributes
best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_belongs_to_create_without_protection
best_friend = @person.create_best_friend_of(attributes_hash, :without_protection => true)
assert_all_attributes(best_friend)
end
def test_belongs_to_create_with_strict_sanitizer
with_strict_sanitizer do
best_friend = @person.create_best_friend_of(attributes_hash.except(:id, :comments))
assert_equal best_friend.id, @person.best_friend_of_id
end
end
# create!
def test_belongs_to_create_with_bang_with_attr_protected_attributes
best_friend = @person.create_best_friend!(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_belongs_to_create_with_bang_with_attr_accessible_attributes
best_friend = @person.create_best_friend!(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_belongs_to_create_with_bang_with_admin_role_with_attr_protected_attributes
best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_belongs_to_create_with_bang_with_admin_role_with_attr_accessible_attributes
best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_belongs_to_create_with_bang_without_protection
best_friend = @person.create_best_friend!(attributes_hash, :without_protection => true)
assert_all_attributes(best_friend)
end
def test_belongs_to_create_with_bang_with_strict_sanitizer
with_strict_sanitizer do
best_friend = @person.create_best_friend_of!(attributes_hash.except(:id, :comments))
assert_equal best_friend.id, @person.best_friend_of_id
end
end
end
class MassAssignmentSecurityHasManyRelationsTest < ActiveSupport::TestCase
include MassAssignmentTestHelpers
include MassAssignmentRelationTestHelpers
# build
def test_has_many_build_with_attr_protected_attributes
best_friend = @person.best_friends.build(attributes_hash)
assert_default_attributes(best_friend)
end
def test_has_many_build_with_attr_accessible_attributes
best_friend = @person.best_friends.build(attributes_hash)
assert_default_attributes(best_friend)
end
def test_has_many_build_with_admin_role_with_attr_protected_attributes
best_friend = @person.best_friends.build(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend)
end
def test_has_many_build_with_admin_role_with_attr_accessible_attributes
best_friend = @person.best_friends.build(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend)
end
def test_has_many_build_without_protection
best_friend = @person.best_friends.build(attributes_hash, :without_protection => true)
assert_all_attributes(best_friend)
end
def test_has_many_build_with_strict_sanitizer
with_strict_sanitizer do
best_friend = @person.best_friends.build(attributes_hash.except(:id, :comments))
assert_equal @person.id, best_friend.best_friend_id
end
end
def test_has_many_through_build_with_attr_accessible_attributes
group = Group.create!
pirate = group.members.build(name: "Murphy")
assert_equal "Murphy", pirate.name
end
# new
def test_has_many_new_with_attr_protected_attributes
best_friend = @person.best_friends.new(attributes_hash)
assert_default_attributes(best_friend)
end
def test_has_many_new_with_attr_accessible_attributes
best_friend = @person.best_friends.new(attributes_hash)
assert_default_attributes(best_friend)
end
def test_has_many_new_with_admin_role_with_attr_protected_attributes
best_friend = @person.best_friends.new(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend)
end
def test_has_many_new_with_admin_role_with_attr_accessible_attributes
best_friend = @person.best_friends.new(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend)
end
def test_has_many_new_without_protection
best_friend = @person.best_friends.new(attributes_hash, :without_protection => true)
assert_all_attributes(best_friend)
end
def test_has_many_new_with_strict_sanitizer
with_strict_sanitizer do
best_friend = @person.best_friends.new(attributes_hash.except(:id, :comments))
assert_equal @person.id, best_friend.best_friend_id
end
end
# create
def test_has_many_create_with_attr_protected_attributes
best_friend = @person.best_friends.create(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_has_many_create_with_attr_accessible_attributes
best_friend = @person.best_friends.create(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_has_many_create_with_admin_role_with_attr_protected_attributes
best_friend = @person.best_friends.create(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_has_many_create_with_admin_role_with_attr_accessible_attributes
best_friend = @person.best_friends.create(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_has_many_create_without_protection
best_friend = @person.best_friends.create(attributes_hash, :without_protection => true)
assert_all_attributes(best_friend)
end
def test_has_many_create_with_strict_sanitizer
with_strict_sanitizer do
best_friend = @person.best_friends.create(attributes_hash.except(:id, :comments))
assert_equal @person.id, best_friend.best_friend_id
end
end
# create!
def test_has_many_create_with_bang_with_attr_protected_attributes
best_friend = @person.best_friends.create!(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_has_many_create_with_bang_with_attr_accessible_attributes
best_friend = @person.best_friends.create!(attributes_hash)
assert_default_attributes(best_friend, true)
end
def test_has_many_create_with_bang_with_admin_role_with_attr_protected_attributes
best_friend = @person.best_friends.create!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_has_many_create_with_bang_with_admin_role_with_attr_accessible_attributes
best_friend = @person.best_friends.create!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true)
end
def test_has_many_create_with_bang_without_protection
best_friend = @person.best_friends.create!(attributes_hash, :without_protection => true)
assert_all_attributes(best_friend)
end
def test_has_many_create_with_bang_with_strict_sanitizer
with_strict_sanitizer do
best_friend = @person.best_friends.create!(attributes_hash.except(:id, :comments))
assert_equal @person.id, best_friend.best_friend_id
end
end
# concat
def test_concat_has_many_through_association_member
group = Group.create!
pirate = Pirate.create!
group.members << pirate
assert_equal pirate.memberships.first, group.memberships.first
end
def test_concat_has_many_through_polymorphic_association
team = Team.create!
vampire = Vampire.create!
wolf = Wolf.create!
team.vampire_battles << vampire
wolf.teams << team
assert_equal team.wolf_battles.first, wolf
end
end
class MassAssignmentSecurityNestedAttributesTest < ActiveSupport::TestCase
include MassAssignmentTestHelpers
def nested_attributes_hash(association, collection = false, except = [:id])
if collection
{ :first_name => 'David' }.merge(:"#{association}_attributes" => [attributes_hash.except(*except)])
else
{ :first_name => 'David' }.merge(:"#{association}_attributes" => attributes_hash.except(*except))
end
end
# build
def test_has_one_new_with_attr_protected_attributes
person = LoosePerson.new(nested_attributes_hash(:best_friend))
assert_default_attributes(person.best_friend)
end
def test_has_one_new_with_attr_accessible_attributes
person = TightPerson.new(nested_attributes_hash(:best_friend))
assert_default_attributes(person.best_friend)
end
def test_has_one_new_with_admin_role_with_attr_protected_attributes
person = LoosePerson.new(nested_attributes_hash(:best_friend), :as => :admin)
assert_admin_attributes(person.best_friend)
end
def test_has_one_new_with_admin_role_with_attr_accessible_attributes
person = TightPerson.new(nested_attributes_hash(:best_friend), :as => :admin)
assert_admin_attributes(person.best_friend)
end
def test_has_one_new_without_protection
person = LoosePerson.new(nested_attributes_hash(:best_friend, false, nil), :without_protection => true)
assert_all_attributes(person.best_friend)
end
def test_belongs_to_new_with_attr_protected_attributes
person = LoosePerson.new(nested_attributes_hash(:best_friend_of))
assert_default_attributes(person.best_friend_of)
end
def test_belongs_to_new_with_attr_accessible_attributes
person = TightPerson.new(nested_attributes_hash(:best_friend_of))
assert_default_attributes(person.best_friend_of)
end
def test_belongs_to_new_with_admin_role_with_attr_protected_attributes
person = LoosePerson.new(nested_attributes_hash(:best_friend_of), :as => :admin)
assert_admin_attributes(person.best_friend_of)
end
def test_belongs_to_new_with_admin_role_with_attr_accessible_attributes
person = TightPerson.new(nested_attributes_hash(:best_friend_of), :as => :admin)
assert_admin_attributes(person.best_friend_of)
end
def test_belongs_to_new_without_protection
person = LoosePerson.new(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true)
assert_all_attributes(person.best_friend_of)
end
def test_has_many_new_with_attr_protected_attributes
person = LoosePerson.new(nested_attributes_hash(:best_friends, true))
assert_default_attributes(person.best_friends.first)
end
def test_has_many_new_with_attr_accessible_attributes
person = TightPerson.new(nested_attributes_hash(:best_friends, true))
assert_default_attributes(person.best_friends.first)
end
def test_has_many_new_with_admin_role_with_attr_protected_attributes
person = LoosePerson.new(nested_attributes_hash(:best_friends, true), :as => :admin)
assert_admin_attributes(person.best_friends.first)
end
def test_has_many_new_with_admin_role_with_attr_accessible_attributes
person = TightPerson.new(nested_attributes_hash(:best_friends, true), :as => :admin)
assert_admin_attributes(person.best_friends.first)
end
def test_has_many_new_without_protection
person = LoosePerson.new(nested_attributes_hash(:best_friends, true, nil), :without_protection => true)
assert_all_attributes(person.best_friends.first)
end
# create
def test_has_one_create_with_attr_protected_attributes
person = LoosePerson.create(nested_attributes_hash(:best_friend))
assert_default_attributes(person.best_friend, true)
end
def test_has_one_create_with_attr_accessible_attributes
person = TightPerson.create(nested_attributes_hash(:best_friend))
assert_default_attributes(person.best_friend, true)
end
def test_has_one_create_with_admin_role_with_attr_protected_attributes
person = LoosePerson.create(nested_attributes_hash(:best_friend), :as => :admin)
assert_admin_attributes(person.best_friend, true)
end
def test_has_one_create_with_admin_role_with_attr_accessible_attributes
person = TightPerson.create(nested_attributes_hash(:best_friend), :as => :admin)
assert_admin_attributes(person.best_friend, true)
end
def test_has_one_create_without_protection
person = LoosePerson.create(nested_attributes_hash(:best_friend, false, nil), :without_protection => true)
assert_all_attributes(person.best_friend)
end
def test_belongs_to_create_with_attr_protected_attributes
person = LoosePerson.create(nested_attributes_hash(:best_friend_of))
assert_default_attributes(person.best_friend_of, true)
end
def test_belongs_to_create_with_attr_accessible_attributes
person = TightPerson.create(nested_attributes_hash(:best_friend_of))
assert_default_attributes(person.best_friend_of, true)
end
def test_belongs_to_create_with_admin_role_with_attr_protected_attributes
person = LoosePerson.create(nested_attributes_hash(:best_friend_of), :as => :admin)
assert_admin_attributes(person.best_friend_of, true)
end
def test_belongs_to_create_with_admin_role_with_attr_accessible_attributes
person = TightPerson.create(nested_attributes_hash(:best_friend_of), :as => :admin)
assert_admin_attributes(person.best_friend_of, true)
end
def test_belongs_to_create_without_protection
person = LoosePerson.create(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true)
assert_all_attributes(person.best_friend_of)
end
def test_has_many_create_with_attr_protected_attributes
person = LoosePerson.create(nested_attributes_hash(:best_friends, true))
assert_default_attributes(person.best_friends.first, true)
end
def test_has_many_create_with_attr_accessible_attributes
person = TightPerson.create(nested_attributes_hash(:best_friends, true))
assert_default_attributes(person.best_friends.first, true)
end
def test_has_many_create_with_admin_role_with_attr_protected_attributes
person = LoosePerson.create(nested_attributes_hash(:best_friends, true), :as => :admin)
assert_admin_attributes(person.best_friends.first, true)
end
def test_has_many_create_with_admin_role_with_attr_accessible_attributes
person = TightPerson.create(nested_attributes_hash(:best_friends, true), :as => :admin)
assert_admin_attributes(person.best_friends.first, true)
end
def test_has_many_create_without_protection
person = LoosePerson.create(nested_attributes_hash(:best_friends, true, nil), :without_protection => true)
assert_all_attributes(person.best_friends.first)
end
# create!
def test_has_one_create_with_bang_with_attr_protected_attributes
person = LoosePerson.create!(nested_attributes_hash(:best_friend))
assert_default_attributes(person.best_friend, true)
end
def test_has_one_create_with_bang_with_attr_accessible_attributes
person = TightPerson.create!(nested_attributes_hash(:best_friend))
assert_default_attributes(person.best_friend, true)
end
def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes
person = LoosePerson.create!(nested_attributes_hash(:best_friend), :as => :admin)
assert_admin_attributes(person.best_friend, true)
end
def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes
person = TightPerson.create!(nested_attributes_hash(:best_friend), :as => :admin)
assert_admin_attributes(person.best_friend, true)
end
def test_has_one_create_with_bang_without_protection
person = LoosePerson.create!(nested_attributes_hash(:best_friend, false, nil), :without_protection => true)
assert_all_attributes(person.best_friend)
end
def test_belongs_to_create_with_bang_with_attr_protected_attributes
person = LoosePerson.create!(nested_attributes_hash(:best_friend_of))
assert_default_attributes(person.best_friend_of, true)
end
def test_belongs_to_create_with_bang_with_attr_accessible_attributes
person = TightPerson.create!(nested_attributes_hash(:best_friend_of))
assert_default_attributes(person.best_friend_of, true)
end
def test_belongs_to_create_with_bang_with_admin_role_with_attr_protected_attributes
person = LoosePerson.create!(nested_attributes_hash(:best_friend_of), :as => :admin)
assert_admin_attributes(person.best_friend_of, true)
end
def test_belongs_to_create_with_bang_with_admin_role_with_attr_accessible_attributes
person = TightPerson.create!(nested_attributes_hash(:best_friend_of), :as => :admin)
assert_admin_attributes(person.best_friend_of, true)
end
def test_belongs_to_create_with_bang_without_protection
person = LoosePerson.create!(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true)
assert_all_attributes(person.best_friend_of)
end
def test_has_many_create_with_bang_with_attr_protected_attributes
person = LoosePerson.create!(nested_attributes_hash(:best_friends, true))
assert_default_attributes(person.best_friends.first, true)
end
def test_has_many_create_with_bang_with_attr_accessible_attributes
person = TightPerson.create!(nested_attributes_hash(:best_friends, true))
assert_default_attributes(person.best_friends.first, true)
end
def test_has_many_create_with_bang_with_admin_role_with_attr_protected_attributes
person = LoosePerson.create!(nested_attributes_hash(:best_friends, true), :as => :admin)
assert_admin_attributes(person.best_friends.first, true)
end
def test_has_many_create_with_bang_with_admin_role_with_attr_accessible_attributes
person = TightPerson.create!(nested_attributes_hash(:best_friends, true), :as => :admin)
assert_admin_attributes(person.best_friends.first, true)
end
def test_has_many_create_with_bang_without_protection
person = LoosePerson.create!(nested_attributes_hash(:best_friends, true, nil), :without_protection => true)
assert_all_attributes(person.best_friends.first)
end
def test_mass_assignment_options_are_reset_after_exception
person = NestedPerson.create!({ :first_name => 'David', :gender => 'm' }, :as => :admin)
person.create_best_friend!({ :first_name => 'Jeremy', :gender => 'm' }, :as => :admin)
attributes = { :best_friend_attributes => { :comments => 'rides a sweet bike' } }
assert_raises(RuntimeError) { person.assign_attributes(attributes, :as => :admin) }
assert_equal 'm', person.best_friend.gender
person.best_friend_attributes = { :gender => 'f' }
assert_equal 'm', person.best_friend.gender
end
def test_mass_assignment_options_are_nested_correctly
person = NestedPerson.create!({ :first_name => 'David', :gender => 'm' }, :as => :admin)
person.create_best_friend!({ :first_name => 'Jeremy', :gender => 'm' }, :as => :admin)
attributes = { :best_friend_first_name => 'Josh', :best_friend_attributes => { :gender => 'f' } }
person.assign_attributes(attributes, :as => :admin)
assert_equal 'Josh', person.best_friend.first_name
assert_equal 'f', person.best_friend.gender
end
end
protected_attributes-1.1.3/test/mass_assignment_security/ 0000775 0000000 0000000 00000000000 12551267773 0024073 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/test/mass_assignment_security/black_list_test.rb 0000664 0000000 0000000 00000000762 12551267773 0027573 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'active_model/mass_assignment_security'
class BlackListTest < ActiveModel::TestCase
def setup
@black_list = ActiveModel::MassAssignmentSecurity::BlackList.new
@included_key = 'admin'
@black_list += [ @included_key ]
end
test "deny? is true for included items" do
assert_equal true, @black_list.deny?(@included_key)
end
test "deny? is false for non-included items" do
assert_equal false, @black_list.deny?('first_name')
end
end
protected_attributes-1.1.3/test/mass_assignment_security/permission_set_test.rb 0000664 0000000 0000000 00000002217 12551267773 0030524 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'active_model/mass_assignment_security'
class PermissionSetTest < ActiveModel::TestCase
def setup
@permission_list = ActiveModel::MassAssignmentSecurity::PermissionSet.new
end
test "+ stringifies added collection values" do
symbol_collection = [ :admin ]
new_list = @permission_list += symbol_collection
assert new_list.include?('admin'), "did not add collection to #{@permission_list.inspect}}"
end
test "+ compacts added collection values" do
added_collection = [ nil ]
new_list = @permission_list + added_collection
assert_equal new_list, @permission_list, "did not add collection to #{@permission_list.inspect}}"
end
test "include? normalizes multi-parameter keys" do
multi_param_key = 'admin(1)'
new_list = @permission_list += [ 'admin' ]
assert new_list.include?(multi_param_key), "#{multi_param_key} not found in #{@permission_list.inspect}"
end
test "include? normal keys" do
normal_key = 'admin'
new_list = @permission_list += [ normal_key ]
assert new_list.include?(normal_key), "#{normal_key} not found in #{@permission_list.inspect}"
end
end
protected_attributes-1.1.3/test/mass_assignment_security/sanitizer_test.rb 0000664 0000000 0000000 00000003436 12551267773 0027475 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'active_model/mass_assignment_security'
require 'active_support/logger'
class SanitizerTest < ActiveModel::TestCase
attr_accessor :logger
class Authorizer < ActiveModel::MassAssignmentSecurity::PermissionSet
def deny?(key)
['admin', 'id'].include?(key)
end
end
def setup
@logger_sanitizer = ActiveModel::MassAssignmentSecurity::LoggerSanitizer.new(self)
@strict_sanitizer = ActiveModel::MassAssignmentSecurity::StrictSanitizer.new(self)
@authorizer = Authorizer.new
end
test "sanitize attributes" do
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
attributes = @logger_sanitizer.sanitize(self.class, original_attributes, @authorizer)
assert attributes.key?('first_name'), "Allowed key shouldn't be rejected"
assert !attributes.key?('admin'), "Denied key should be rejected"
end
test "debug mass assignment removal with LoggerSanitizer" do
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
log = StringIO.new
self.logger = ActiveSupport::Logger.new(log)
@logger_sanitizer.sanitize(self.class, original_attributes, @authorizer)
assert_match(/admin/, log.string, "Should log removed attributes: #{log.string}")
end
test "debug mass assignment removal with StrictSanitizer" do
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
assert_raise ActiveModel::MassAssignmentSecurity::Error do
@strict_sanitizer.sanitize(self.class, original_attributes, @authorizer)
end
end
test "mass assignment insensitive attributes" do
original_attributes = {'id' => 1, 'first_name' => 'allowed'}
assert_nothing_raised do
@strict_sanitizer.sanitize(self.class, original_attributes, @authorizer)
end
end
end
protected_attributes-1.1.3/test/mass_assignment_security/strong_parameters_fallback_test.rb 0000664 0000000 0000000 00000006033 12551267773 0033037 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'ar_helper'
require 'rack/test'
require 'action_controller/metal/strong_parameters'
require 'active_record/mass_assignment_security'
require 'active_model/mass_assignment_security'
require 'models/book'
require 'models/person'
class StrongParametersFallbackTest < ActiveModel::TestCase
test "AR, use strong parameters when no protection macro (attr_accessible, attr_protected) was used." do
untrusted_params = ActionController::Parameters.new(title: 'Agile Development with Ruby on Rails')
assert_raises(ActiveModel::ForbiddenAttributesError) { Book.new untrusted_params }
assert_raises(ActiveModel::ForbiddenAttributesError) { Book.new.attributes = untrusted_params }
assert_raises(ActiveModel::ForbiddenAttributesError) { Book.where(title: 'Agile Development with Ruby on Rails').first_or_initialize(untrusted_params) }
assert_raises(ActiveModel::ForbiddenAttributesError) { Book.where(title: 'Agile Development with Ruby on Rails').first_or_create(untrusted_params) }
assert_raises(ActiveModel::ForbiddenAttributesError) { Book.where(title: 'Agile Development with Ruby on Rails').first_or_create!(untrusted_params) }
assert_raises(ActiveModel::ForbiddenAttributesError) { Book.find_or_initialize_by(untrusted_params) }
assert_raises(ActiveModel::ForbiddenAttributesError) { Book.find_or_create_by(untrusted_params) }
assert_raises(ActiveModel::ForbiddenAttributesError) { Book.find_or_create_by!(untrusted_params) }
end
test "AR, ignore strong parameters when protection macro was used" do
untrusted_params = ActionController::Parameters.new(first_name: "John")
assert_nothing_raised { TightPerson.new untrusted_params }
assert_nothing_raised { TightPerson.new.attributes = untrusted_params }
assert_nothing_raised { TightPerson.where(first_name: "John").first_or_initialize(untrusted_params) }
assert_nothing_raised { TightPerson.where(first_name: "John").first_or_create(untrusted_params) }
assert_nothing_raised { TightPerson.where(first_name: "John").first_or_create!(untrusted_params) }
assert_nothing_raised { TightPerson.find_or_initialize_by(untrusted_params) }
assert_nothing_raised { TightPerson.find_or_create_by(untrusted_params) }
assert_nothing_raised { TightPerson.find_or_create_by!(untrusted_params) }
end
test "with PORO including MassAssignmentSecurity that uses a protection marco" do
klass = Class.new do
include ActiveModel::MassAssignmentSecurity
attr_protected :admin
end
untrusted_params = ActionController::Parameters.new(admin: true)
assert_equal({}, klass.new.send(:sanitize_for_mass_assignment, untrusted_params))
end
test "with PORO including MassAssignmentSecurity that does not use a protection marco" do
klass = Class.new do
include ActiveModel::MassAssignmentSecurity
end
untrusted_params = ActionController::Parameters.new(name: "37 signals")
assert_raises ActiveModel::ForbiddenAttributesError do
klass.new.send :sanitize_for_mass_assignment, untrusted_params
end
end
end
protected_attributes-1.1.3/test/mass_assignment_security/white_list_test.rb 0000664 0000000 0000000 00000000761 12551267773 0027636 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'active_model/mass_assignment_security'
class WhiteListTest < ActiveModel::TestCase
def setup
@white_list = ActiveModel::MassAssignmentSecurity::WhiteList.new
@included_key = 'first_name'
@white_list += [ @included_key ]
end
test "deny? is false for included items" do
assert_equal false, @white_list.deny?(@included_key)
end
test "deny? is true for non-included items" do
assert_equal true, @white_list.deny?('admin')
end
end
protected_attributes-1.1.3/test/mass_assignment_security_test.rb 0000664 0000000 0000000 00000011513 12551267773 0025460 0 ustar 00root root 0000000 0000000 require 'test_helper'
require 'active_model/mass_assignment_security'
require 'models/mass_assignment_specific'
class CustomSanitizer < ActiveModel::MassAssignmentSecurity::Sanitizer
def process_removed_attributes(klass, attrs)
raise StandardError
end
end
class MassAssignmentSecurityTest < ActiveModel::TestCase
def test_attribute_protection
user = User.new
expected = { "name" => "John Smith", "email" => "john@smith.com" }
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true))
assert_equal expected, sanitized
end
def test_attribute_protection_when_role_is_nil
user = User.new
expected = { "name" => "John Smith", "email" => "john@smith.com" }
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true), nil)
assert_equal expected, sanitized
end
def test_only_moderator_role_attribute_accessible
user = SpecialUser.new
expected = { "name" => "John Smith", "email" => "john@smith.com" }
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true), :moderator)
assert_equal expected, sanitized
sanitized = user.sanitize_for_mass_assignment({ "name" => "John Smith", "email" => "john@smith.com", "admin" => true })
assert_equal({}, sanitized)
end
def test_attributes_accessible
user = Person.new
expected = { "name" => "John Smith", "email" => "john@smith.com" }
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true))
assert_equal expected, sanitized
end
def test_attributes_accessible_with_admin_role
user = Person.new
expected = { "name" => "John Smith", "email" => "john@smith.com", "admin" => true }
sanitized = user.sanitize_for_mass_assignment(expected.merge("super_powers" => true), :admin)
assert_equal expected, sanitized
end
def test_attributes_accessible_with_roles_given_as_array
user = Account.new
expected = { "name" => "John Smith", "email" => "john@smith.com" }
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true))
assert_equal expected, sanitized
end
def test_attributes_accessible_with_admin_role_when_roles_given_as_array
user = Account.new
expected = { "name" => "John Smith", "email" => "john@smith.com", "admin" => true }
sanitized = user.sanitize_for_mass_assignment(expected.merge("super_powers" => true), :admin)
assert_equal expected, sanitized
end
def test_attributes_protected_by_default
firm = Firm.new
expected = { }
sanitized = firm.sanitize_for_mass_assignment({ "type" => "Client" })
assert_equal expected, sanitized
end
def test_mass_assignment_protection_inheritance
assert SpecialLoosePerson.accessible_attributes.blank?
assert_equal Set.new(['credit_rating', 'administrator']), SpecialLoosePerson.protected_attributes
assert SpecialLoosePerson.accessible_attributes.blank?
assert_equal Set.new(['credit_rating']), SpecialLoosePerson.protected_attributes(:admin)
assert LooseDescendant.accessible_attributes.blank?
assert_equal Set.new(['credit_rating', 'administrator', 'phone_number']), LooseDescendant.protected_attributes
assert LooseDescendantSecond.accessible_attributes.blank?
assert_equal Set.new(['credit_rating', 'administrator', 'phone_number', 'name']), LooseDescendantSecond.protected_attributes,
'Running attr_protected twice in one class should merge the protections'
assert((SpecialTightPerson.protected_attributes - SpecialTightPerson.attributes_protected_by_default).blank?)
assert_equal Set.new(['name', 'address']), SpecialTightPerson.accessible_attributes
assert((SpecialTightPerson.protected_attributes(:admin) - SpecialTightPerson.attributes_protected_by_default).blank?)
assert_equal Set.new(['name', 'address', 'admin']), SpecialTightPerson.accessible_attributes(:admin)
assert((TightDescendant.protected_attributes - TightDescendant.attributes_protected_by_default).blank?)
assert_equal Set.new(['name', 'address', 'phone_number']), TightDescendant.accessible_attributes
assert((TightDescendant.protected_attributes(:admin) - TightDescendant.attributes_protected_by_default).blank?)
assert_equal Set.new(['name', 'address', 'admin', 'super_powers']), TightDescendant.accessible_attributes(:admin)
end
def test_mass_assignment_multiparameter_protector
task = Task.new
attributes = { "starting(1i)" => "2004", "starting(2i)" => "6", "starting(3i)" => "24" }
sanitized = task.sanitize_for_mass_assignment(attributes)
assert_equal sanitized, { }
end
def test_custom_sanitizer
old_sanitizer = User._mass_assignment_sanitizer
user = User.new
User.mass_assignment_sanitizer = CustomSanitizer.new
assert_raise StandardError do
user.sanitize_for_mass_assignment("admin" => true)
end
ensure
User.mass_assignment_sanitizer = old_sanitizer
end
end
protected_attributes-1.1.3/test/models/ 0000775 0000000 0000000 00000000000 12551267773 0020234 5 ustar 00root root 0000000 0000000 protected_attributes-1.1.3/test/models/battle.rb 0000664 0000000 0000000 00000000171 12551267773 0022033 0 ustar 00root root 0000000 0000000 class Battle < ActiveRecord::Base
attr_accessible []
belongs_to :team
belongs_to :battle, :polymorphic => true
end
protected_attributes-1.1.3/test/models/book.rb 0000664 0000000 0000000 00000000044 12551267773 0021511 0 ustar 00root root 0000000 0000000 class Book < ActiveRecord::Base
end
protected_attributes-1.1.3/test/models/company.rb 0000664 0000000 0000000 00000000436 12551267773 0022232 0 ustar 00root root 0000000 0000000 class AbstractCompany < ActiveRecord::Base
self.abstract_class = true
end
class Company < AbstractCompany
attr_protected :rating
end
class Firm < Company
end
class Corporation < Company
attr_accessible :type, :name, :description
end
class SpecialCorporation < Corporation
end
protected_attributes-1.1.3/test/models/group.rb 0000664 0000000 0000000 00000000303 12551267773 0021711 0 ustar 00root root 0000000 0000000 class Group < ActiveRecord::Base
self.mass_assignment_sanitizer = :strict
has_many :memberships, :dependent => :destroy
has_many :members, :through => :memberships, :source => :pirate
end
protected_attributes-1.1.3/test/models/keyboard.rb 0000664 0000000 0000000 00000000142 12551267773 0022356 0 ustar 00root root 0000000 0000000 class Keyboard < ActiveRecord::Base
attr_accessible(nil)
self.primary_key = 'key_number'
end
protected_attributes-1.1.3/test/models/mass_assignment_specific.rb 0000664 0000000 0000000 00000003241 12551267773 0025621 0 ustar 00root root 0000000 0000000 class User
include ActiveModel::MassAssignmentSecurity
attr_protected :admin
public :sanitize_for_mass_assignment
end
class SpecialUser
include ActiveModel::MassAssignmentSecurity
attr_accessible :name, :email, :as => :moderator
public :sanitize_for_mass_assignment
end
class Person
include ActiveModel::MassAssignmentSecurity
attr_accessible :name, :email
attr_accessible :name, :email, :admin, :as => :admin
public :sanitize_for_mass_assignment
end
class Account
include ActiveModel::MassAssignmentSecurity
attr_accessible :name, :email, :as => [:default, :admin]
attr_accessible :admin, :as => :admin
public :sanitize_for_mass_assignment
end
class Firm
include ActiveModel::MassAssignmentSecurity
public :sanitize_for_mass_assignment
def self.attributes_protected_by_default
["type"]
end
end
class Task
include ActiveModel::MassAssignmentSecurity
attr_protected :starting
public :sanitize_for_mass_assignment
end
class SpecialLoosePerson
include ActiveModel::MassAssignmentSecurity
attr_protected :credit_rating, :administrator
attr_protected :credit_rating, :as => :admin
end
class LooseDescendant < SpecialLoosePerson
attr_protected :phone_number
end
class LooseDescendantSecond< SpecialLoosePerson
attr_protected :phone_number
attr_protected :name
end
class SpecialTightPerson
include ActiveModel::MassAssignmentSecurity
attr_accessible :name, :address
attr_accessible :name, :address, :admin, :as => :admin
def self.attributes_protected_by_default
["mobile_number"]
end
end
class TightDescendant < SpecialTightPerson
attr_accessible :phone_number
attr_accessible :super_powers, :as => :admin
end
protected_attributes-1.1.3/test/models/membership.rb 0000664 0000000 0000000 00000000225 12551267773 0022713 0 ustar 00root root 0000000 0000000 class Membership < ActiveRecord::Base
self.mass_assignment_sanitizer = :strict
belongs_to :group
belongs_to :pirate
attr_accessible []
end
protected_attributes-1.1.3/test/models/person.rb 0000664 0000000 0000000 00000003625 12551267773 0022075 0 ustar 00root root 0000000 0000000 class LoosePerson < ActiveRecord::Base
self.table_name = 'people'
attr_protected :comments, :best_friend_id, :best_friend_of_id
attr_protected :as => :admin
has_one :best_friend, :class_name => 'LoosePerson', :foreign_key => :best_friend_id
belongs_to :best_friend_of, :class_name => 'LoosePerson', :foreign_key => :best_friend_of_id
has_many :best_friends, :class_name => 'LoosePerson', :foreign_key => :best_friend_id
accepts_nested_attributes_for :best_friend, :best_friend_of, :best_friends
end
class TightPerson < ActiveRecord::Base
self.table_name = 'people'
attr_accessible :first_name, :gender
attr_accessible :first_name, :gender, :comments, :as => :admin
attr_accessible :best_friend_attributes, :best_friend_of_attributes, :best_friends_attributes
attr_accessible :best_friend_attributes, :best_friend_of_attributes, :best_friends_attributes, :as => :admin
has_one :best_friend, :class_name => 'TightPerson', :foreign_key => :best_friend_id
belongs_to :best_friend_of, :class_name => 'TightPerson', :foreign_key => :best_friend_of_id
has_many :best_friends, :class_name => 'TightPerson', :foreign_key => :best_friend_id
accepts_nested_attributes_for :best_friend, :best_friend_of, :best_friends
end
class NestedPerson < ActiveRecord::Base
self.table_name = 'people'
attr_accessible :first_name, :best_friend_first_name, :best_friend_attributes
attr_accessible :first_name, :gender, :comments, :as => :admin
attr_accessible :best_friend_attributes, :best_friend_first_name, :as => :admin
has_one :best_friend, :class_name => 'NestedPerson', :foreign_key => :best_friend_id
accepts_nested_attributes_for :best_friend, :update_only => true, :reject_if => :all_blank
def comments=(new_comments)
raise RuntimeError
end
def best_friend_first_name=(new_name)
assign_attributes({ :best_friend_attributes => { :first_name => new_name } })
end
end
protected_attributes-1.1.3/test/models/pirate.rb 0000664 0000000 0000000 00000000201 12551267773 0022036 0 ustar 00root root 0000000 0000000 class Pirate < ActiveRecord::Base
self.mass_assignment_sanitizer = :strict
attr_accessible :name
has_many :memberships
end
protected_attributes-1.1.3/test/models/subscriber.rb 0000664 0000000 0000000 00000000246 12551267773 0022726 0 ustar 00root root 0000000 0000000 class Subscriber < ActiveRecord::Base
attr_accessible(nil)
self.primary_key = 'nick'
has_many :subscriptions
has_many :books, :through => :subscriptions
end
protected_attributes-1.1.3/test/models/task.rb 0000664 0000000 0000000 00000000106 12551267773 0021520 0 ustar 00root root 0000000 0000000 class Task < ActiveRecord::Base
def updated_at
ending
end
end
protected_attributes-1.1.3/test/models/team.rb 0000664 0000000 0000000 00000000445 12551267773 0021512 0 ustar 00root root 0000000 0000000 class Team < ActiveRecord::Base
has_many :battles
has_many :wolf_battles, :through => :battles, :class_name => 'Wolf', :source => :battle, :source_type => 'Wolf'
has_many :vampire_battles, :through => :battles, :class_name => 'Vampire', :source => :battle, :source_type => 'Vampire'
end
protected_attributes-1.1.3/test/models/vampire.rb 0000664 0000000 0000000 00000000163 12551267773 0022224 0 ustar 00root root 0000000 0000000 class Vampire < ActiveRecord::Base
has_many :battles, :as => :battle
has_many :teams, :through => :battles
end
protected_attributes-1.1.3/test/models/wolf.rb 0000664 0000000 0000000 00000000160 12551267773 0021525 0 ustar 00root root 0000000 0000000 class Wolf < ActiveRecord::Base
has_many :battles, :as => :battle
has_many :teams, :through => :battles
end
protected_attributes-1.1.3/test/test_helper.rb 0000664 0000000 0000000 00000000245 12551267773 0021615 0 ustar 00root root 0000000 0000000 require 'bundler/setup'
require 'minitest/autorun'
require 'mocha/api'
require 'rails'
ActiveSupport.test_order = :random if ActiveSupport.respond_to?(:test_order)