param_accessible 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/.gitignore +19 -0
  2. data/.travis.yml +4 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +93 -0
  6. data/Rakefile +7 -0
  7. data/lib/param_accessible/controller_ext.rb +41 -0
  8. data/lib/param_accessible/error.rb +19 -0
  9. data/lib/param_accessible/not_acceptable_helper.rb +23 -0
  10. data/lib/param_accessible/rule.rb +93 -0
  11. data/lib/param_accessible/rules.rb +58 -0
  12. data/lib/param_accessible/version.rb +3 -0
  13. data/lib/param_accessible.rb +8 -0
  14. data/param_accessible.gemspec +23 -0
  15. data/spec/app_root/app/controllers/application_controller.rb +34 -0
  16. data/spec/app_root/app/controllers/except_controller.rb +6 -0
  17. data/spec/app_root/app/controllers/if_false_controller.rb +12 -0
  18. data/spec/app_root/app/controllers/if_true_controller.rb +12 -0
  19. data/spec/app_root/app/controllers/merge_controller.rb +6 -0
  20. data/spec/app_root/app/controllers/not_acceptable_controller.rb +6 -0
  21. data/spec/app_root/app/controllers/only_controller.rb +6 -0
  22. data/spec/app_root/app/controllers/simple_controller.rb +4 -0
  23. data/spec/app_root/app/controllers/unless_false_controller.rb +12 -0
  24. data/spec/app_root/app/controllers/unless_true_controller.rb +12 -0
  25. data/spec/app_root/config/application.rb +12 -0
  26. data/spec/app_root/config/environment.rb +5 -0
  27. data/spec/app_root/config/routes.rb +3 -0
  28. data/spec/lib/except_spec.rb +34 -0
  29. data/spec/lib/if_false_spec.rb +24 -0
  30. data/spec/lib/if_true_spec.rb +34 -0
  31. data/spec/lib/merge_spec.rb +20 -0
  32. data/spec/lib/not_acceptable_helper_spec.rb +30 -0
  33. data/spec/lib/only_spec.rb +34 -0
  34. data/spec/lib/simple_spec.rb +57 -0
  35. data/spec/lib/unless_false_spec.rb +34 -0
  36. data/spec/lib/unless_true_spec.rb +24 -0
  37. data/spec/spec_helper.rb +15 -0
  38. metadata +160 -0
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rspec
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ spec/app_root/log
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in param_accessible.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Dan Cunning
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # ParamAccessible
2
+
3
+ [![Build Status](https://secure.travis-ci.org/topdan/param_accessible.png)](https://secure.travis-ci.org/topdan/param_accessible.png)
4
+
5
+ Provides a method to help protect your Ruby on Rails controllers from malicious or accidentally destructive user parameters. It is independent, but heavily influenced by param_protected.
6
+
7
+ Make all your controllers secure by default as well as provide readable messages to users when a security breach was prevented.
8
+
9
+ For more information on the design considerations please visit: https://www.topdan.com/ruby-on-rails/params-accessible.html
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'param_accessible'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install param_accessible
24
+
25
+ ## Usage
26
+
27
+ class ApplicationController < ActionController::Base
28
+
29
+ # make all your controllers secure by default
30
+ before_filter :ensure_params_are_accessible, :only => [:create, :update]
31
+
32
+ # expose the common rails parameters
33
+ param_accessible :controller, :action, :format, :id
34
+
35
+ # this error is thrown when the user tries to access an inaccessible param
36
+ rescue_from ParamAccessible::Error, :with => :handle_param_not_accessible
37
+
38
+ protected
39
+
40
+ def handle_param_not_accessible e
41
+ flash[:error] = "You gave me some invalid parameters: #{e.inaccessible_params.join(', )}"
42
+ redirect_to :back
43
+ end
44
+
45
+ end
46
+
47
+ class UserController < ApplicationController
48
+
49
+ # these attributes are available for everyone
50
+ param_accessible :user => {:name, :email, :password, :password_confirmation}
51
+
52
+ # these attributes are only available if the controller instance method is_admin? is true
53
+ param_accessible :user => {:is_admin, :is_locked_out}, :if => :is_admin?
54
+
55
+ def update
56
+ @user = User.find(params[:id])
57
+
58
+ # this is now safe!
59
+ if @user.update_attributes(params[:user])
60
+ ...
61
+ else
62
+ ...
63
+ end
64
+ end
65
+ end
66
+
67
+ class DemoController < ApplicationController
68
+
69
+ # rescue_from ParamAccessible::Error and respond with a 406 Not Acceptable status
70
+ # with an HTML, JSON, XML, or JS explanation of which parameters were invalid
71
+ include ParamAccessible::NotAcceptableHelper
72
+
73
+ param_accessible :foo, :if => :is_admin
74
+ param_accessible :bar, :unless => :logged_in?
75
+ param_accessible :baz, :only => :show
76
+ param_accessible :nut, :except => :index
77
+
78
+ end
79
+
80
+ class InsecureController < ApplicationController
81
+
82
+ # skip the filter ApplicationController set up to avoid the accessible parameter checks
83
+ skip_before_filter :ensure_params_are_accessible
84
+
85
+ end
86
+
87
+ ## Contributing
88
+
89
+ 1. Fork it
90
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
91
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
92
+ 4. Push to the branch (`git push origin my-new-feature`)
93
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ task :test => :spec
7
+ task :default => :test
@@ -0,0 +1,41 @@
1
+ module ParamAccessible
2
+
3
+ module ControllerExt
4
+ extend ActiveSupport::Concern
5
+
6
+ protected
7
+
8
+ def ensure_params_are_accessible
9
+ inaccessible_params = param_accessible_rules.detect_inaccessible_params self
10
+
11
+ unless inaccessible_params.nil? || inaccessible_params.blank?
12
+ raise ParamAccessible::Error.new(inaccessible_params)
13
+ end
14
+ end
15
+
16
+ def param_accessible_rules
17
+ self.class.param_accessible_rules
18
+ end
19
+
20
+ module ClassMethods
21
+
22
+ def param_accessible *args
23
+ param_accessible_rules.push *args
24
+ end
25
+
26
+ def param_accessible_rules
27
+ return @param_accessible_rules if defined? @param_accessible_rules
28
+
29
+ # inheritance
30
+ if superclass.respond_to?(:param_accessible_rules)
31
+ @param_accessible_rules = Rules.new superclass.param_accessible_rules
32
+ else
33
+ @param_accessible_rules = Rules.new
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,19 @@
1
+ module ParamAccessible
2
+
3
+ class Error < Exception
4
+
5
+ attr_reader :inaccessible_params
6
+
7
+ def initialize inaccessible_params
8
+ if inaccessible_params.length == 1
9
+ super "#{inaccessible_params.join(', ')} is an invalid parameter"
10
+ else
11
+ super "#{inaccessible_params.join(', ')} are invalid parameters"
12
+ end
13
+
14
+ @inaccessible_params = inaccessible_params
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,23 @@
1
+ module ParamAccessible
2
+
3
+ module NotAcceptableHelper
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ rescue_from ParamAccessible::Error, :with => :handle_param_not_accessible
8
+ end
9
+
10
+ protected
11
+
12
+ def handle_param_not_accessible error
13
+ respond_to do |format|
14
+ format.html { render :status => 406, :text => error.message }
15
+ format.json { render :status => 406, :json => {:error => {:message => "You supplied invalid parameters: #{error.inaccessible_params.join(', ')}"}} }
16
+ format.xml { render :status => 406, :xml => {:message => "You supplied invalid parameters: #{error.inaccessible_params.join(', ')}"}.to_xml('error') }
17
+ format.js { render :status => 406, :text => %(// invalid parameters: #{error.inaccessible_params.join(', ')}\n) }
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,93 @@
1
+ module ParamAccessible
2
+
3
+ class Rule
4
+
5
+ attr_reader :attributes
6
+ attr_reader :if_option, :unless_option
7
+ attr_reader :only_options, :except_options
8
+
9
+ def initialize *args
10
+ if args.length > 1 && args.last.is_a?(Hash)
11
+ options = args.last
12
+ attributes = args[0..-2]
13
+
14
+ options.assert_valid_keys :if, :unless, :only, :except
15
+ # options = normalize_options options
16
+ else
17
+ options = {}
18
+ attributes = args
19
+ end
20
+
21
+ @if_option = options[:if]
22
+ @unless_option = options[:unless]
23
+
24
+ @only_options = clean_action_option options[:only]
25
+ @except_options = clean_action_option options[:except]
26
+
27
+ @attributes = normalize_params attributes
28
+ end
29
+
30
+ def clean_action_option value
31
+ return if value == nil
32
+ value = [value] unless value.is_a?(Array)
33
+ value.collect {|v| v.to_s }
34
+ end
35
+
36
+ def accessible_params_for controller, dest
37
+ return if @if_option != nil && !controller.send(@if_option)
38
+ return if @unless_option != nil && controller.send(@unless_option)
39
+
40
+ return if @only_options != nil && !@only_options.include?(controller.action_name)
41
+ return if @except_options != nil && @except_options.include?(controller.action_name)
42
+
43
+ accessible_hash_for controller, @attributes, dest
44
+ end
45
+
46
+ protected
47
+
48
+ def accessible_hash_for controller, attributes, dest
49
+ attributes.each do |key, value|
50
+ if value.is_a?(Hash)
51
+ attrs = dest[key]
52
+ if attrs.nil?
53
+ attrs = {}
54
+ dest[key] = attrs
55
+ end
56
+
57
+ accessible_hash_for controller, value, attrs
58
+ else
59
+ dest[key] = value
60
+ end
61
+ end
62
+ end
63
+
64
+ # When specifying params to protect, we allow a combination of arrays and hashes much like how
65
+ # ActiveRecord::Base#find's :include options works. This method normalizes that into just nested hashes,
66
+ # stringifying the keys and setting all values to nil. This format is easier/faster to work with when
67
+ # filtering the controller params.
68
+ # Example...
69
+ # [:a, {:b => [:c, :d]}]
70
+ # to
71
+ # {"a"=>nil, "b"=>{"c"=>nil, "d"=>nil}}
72
+ def normalize_params(params, params_out = {})
73
+ if params.instance_of?(Array)
74
+ params.each{ |param| normalize_params(param, params_out) }
75
+ elsif params.instance_of?(Hash)
76
+ params.each do |k, v|
77
+ k = normalize_key(k)
78
+ params_out[k] = {}
79
+ normalize_params(v, params_out[k])
80
+ end
81
+ else
82
+ params_out[normalize_key(params)] = nil
83
+ end
84
+ params_out
85
+ end
86
+
87
+ def normalize_key(k)
88
+ k.to_s
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,58 @@
1
+ module ParamAccessible
2
+
3
+ class Rules < Array
4
+
5
+ def initialize parent = nil
6
+ content = (parent.to_a if parent) || []
7
+ super content
8
+ end
9
+
10
+ def detect_inaccessible_params controller
11
+ accessible_params = {}
12
+
13
+ each do |rule|
14
+ rule.accessible_params_for controller, accessible_params
15
+ end
16
+
17
+ detect_inaccessible_hash controller.params, accessible_params, []
18
+ end
19
+
20
+ def push *args
21
+ super Rule.new(*args)
22
+ end
23
+
24
+ protected
25
+
26
+ def detect_inaccessible_hash hash, accessible, errors, prefix = nil
27
+ hash.each do |key, value|
28
+ if !accessible.has_key?(key)
29
+ errors.push prefix_for(prefix, key)
30
+
31
+ elsif value.is_a?(Hash)
32
+ nested = accessible[key] || {}
33
+ detect_inaccessible_hash value, nested, errors, prefix_for(prefix, key)
34
+
35
+ elsif value.is_a?(Array)
36
+ nested = accessible[key] || {}
37
+ value.each do |v|
38
+ if v.is_a?(Hash)
39
+ detect_inaccessible_hash v, nested, errors, prefix_for(prefix, key)
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ errors
46
+ end
47
+
48
+ def prefix_for prefix, key
49
+ if prefix
50
+ "#{prefix}[#{key}]"
51
+ else
52
+ key
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,3 @@
1
+ module ParamAccessible
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,8 @@
1
+ require "param_accessible/version"
2
+ require "param_accessible/error"
3
+ require "param_accessible/rule"
4
+ require "param_accessible/rules"
5
+ require "param_accessible/not_acceptable_helper"
6
+ require "param_accessible/controller_ext"
7
+
8
+ ActionController::Base.send(:include, ParamAccessible::ControllerExt)
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/param_accessible/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Dan Cunning"]
6
+ gem.email = ["dan@topdan.com"]
7
+ gem.description = %q{Help secure your controllers from malicious parameters}
8
+ gem.summary = %q{Help secure your controllers from malicious parameters}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "param_accessible"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = ParamAccessible::VERSION
17
+
18
+ gem.add_dependency 'activesupport', '>= 3.0.0'
19
+ gem.add_dependency 'actionpack', '>= 3.0.0'
20
+ gem.add_development_dependency 'rails', '>= 3.0.0'
21
+ gem.add_development_dependency 'rspec-rails'
22
+ gem.add_development_dependency "simplecov"
23
+ end
@@ -0,0 +1,34 @@
1
+ class ApplicationController < ActionController::Base
2
+ before_filter :ensure_params_are_accessible, :only => [:create, :update]
3
+ before_filter :render_nothing
4
+
5
+ param_accessible :action, :controller, :format
6
+
7
+ def index
8
+ end
9
+
10
+ def show
11
+ end
12
+
13
+ def new
14
+ end
15
+
16
+ def create
17
+ end
18
+
19
+ def edit
20
+ end
21
+
22
+ def update
23
+ end
24
+
25
+ def destroy
26
+ end
27
+
28
+ private
29
+
30
+ def render_nothing
31
+ render :nothing => true
32
+ end
33
+
34
+ end
@@ -0,0 +1,6 @@
1
+ class ExceptController < ApplicationController
2
+
3
+ param_accessible :foo, :except => :create
4
+ param_accessible({:bar => [:baz]}, :except => :update)
5
+
6
+ end
@@ -0,0 +1,12 @@
1
+ class IfFalseController < ApplicationController
2
+
3
+ param_accessible :foo, :if => :admin?
4
+ param_accessible({:bar => [:baz]}, :if => :admin?)
5
+
6
+ protected
7
+
8
+ def admin?
9
+ false
10
+ end
11
+
12
+ end
@@ -0,0 +1,12 @@
1
+ class IfTrueController < ApplicationController
2
+
3
+ param_accessible :foo, :if => :admin?
4
+ param_accessible({:bar => [:baz]}, :if => :admin?)
5
+
6
+ protected
7
+
8
+ def admin?
9
+ true
10
+ end
11
+
12
+ end
@@ -0,0 +1,6 @@
1
+ class MergeController < ApplicationController
2
+ param_accessible :a, :only => :create
3
+ param_accessible :b
4
+ param_accessible({ :h => :c}, :except => :update)
5
+ param_accessible :h => :b
6
+ end
@@ -0,0 +1,6 @@
1
+ class NotAcceptableController < ApplicationController
2
+ include ParamAccessible::NotAcceptableHelper
3
+
4
+ param_accessible :foo
5
+
6
+ end
@@ -0,0 +1,6 @@
1
+ class OnlyController < ApplicationController
2
+
3
+ param_accessible :foo, :only => :create
4
+ param_accessible({:bar => [:baz]}, :only => :update)
5
+
6
+ end
@@ -0,0 +1,4 @@
1
+ class SimpleController < ApplicationController
2
+ # TODO move action and controller up a level
3
+ param_accessible [:foo, {:bar => [:baz, :nuts]}]
4
+ end
@@ -0,0 +1,12 @@
1
+ class UnlessFalseController < ApplicationController
2
+
3
+ param_accessible :foo, :unless => :admin?
4
+ param_accessible({:bar => [:baz]}, :unless => :admin?)
5
+
6
+ protected
7
+
8
+ def admin?
9
+ false
10
+ end
11
+
12
+ end
@@ -0,0 +1,12 @@
1
+ class UnlessTrueController < ApplicationController
2
+
3
+ param_accessible :foo, :unless => :admin?
4
+ param_accessible({:bar => [:baz]}, :unless => :admin?)
5
+
6
+ protected
7
+
8
+ def admin?
9
+ true
10
+ end
11
+
12
+ end
@@ -0,0 +1,12 @@
1
+ require "action_controller/railtie"
2
+
3
+ module TestApp
4
+ class Application < Rails::Application
5
+ config.root = File.join(File.expand_path('.'), 'spec', 'app_root')
6
+ config.cache_classes = false
7
+ config.whiny_nils = true
8
+ config.secret_token = 'd229e4d22437432705ab3985d4d246'
9
+ config.session_store :cookie_store, :key => 'rails_session'
10
+ config.active_support.deprecation = :stderr
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ TestApp::Application.initialize!
@@ -0,0 +1,3 @@
1
+ TestApp::Application.routes.draw do
2
+ match ':controller(/:action(/:id(.:format)))'
3
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe ExceptController do
4
+ include RSpec::Rails::ControllerExampleGroup
5
+
6
+ it "should limit those attribute to ONLY those actions" do
7
+ post :update, :foo => "hi"
8
+ response.code.should == "200"
9
+ end
10
+
11
+ it "should disallow unknown attributes from those actions" do
12
+ begin
13
+ post :update, :bar => "hi"
14
+ raise "should fail"
15
+ rescue ParamAccessible::Error => e
16
+ e.inaccessible_params.should == %w(bar)
17
+ end
18
+ end
19
+
20
+ it "should obey nested attributes" do
21
+ post :create, :bar => {:baz => 'hi'}
22
+ response.code.should == "200"
23
+ end
24
+
25
+ it "should catch invalid nested attributes for those actions" do
26
+ begin
27
+ post :create, :bar => {:foo => 'hi'}
28
+ raise "should fail"
29
+ rescue ParamAccessible::Error => e
30
+ e.inaccessible_params.should == %w(bar[foo])
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe IfFalseController do
4
+ include RSpec::Rails::ControllerExampleGroup
5
+
6
+ it "should not allow the attribute" do
7
+ begin
8
+ post :create, :foo => "hi"
9
+ raise "should fail"
10
+ rescue ParamAccessible::Error => e
11
+ e.inaccessible_params.should == %w(foo)
12
+ end
13
+ end
14
+
15
+ it "should not allow the nested attribute" do
16
+ begin
17
+ post :create, :bar => {:baz => "hi"}
18
+ raise "should fail"
19
+ rescue ParamAccessible::Error => e
20
+ e.inaccessible_params.should == %w(bar)
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe IfTrueController do
4
+ include RSpec::Rails::ControllerExampleGroup
5
+
6
+ it "should allow valid attributes" do
7
+ post :create, :foo => "hi"
8
+ response.code.should == "200"
9
+ end
10
+
11
+ it "should disallow invalid attributes" do
12
+ begin
13
+ post :create, :nuts => "hi"
14
+ raise "should fail"
15
+ rescue ParamAccessible::Error => e
16
+ e.inaccessible_params.should == %w(nuts)
17
+ end
18
+ end
19
+
20
+ it "should allow valid nested attributes" do
21
+ post :update, :bar => {:baz => 'hi'}
22
+ response.code.should == "200"
23
+ end
24
+
25
+ it "should disallow invalid nested attributes" do
26
+ begin
27
+ post :update, :bar => {:foo => 'hi'}
28
+ raise "should fail"
29
+ rescue ParamAccessible::Error => e
30
+ e.inaccessible_params.should == %w(bar[foo])
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe MergeController do
4
+ include RSpec::Rails::ControllerExampleGroup
5
+
6
+ it "should allow a combination of all rules following the options" do
7
+ post :create, :a => 'hi', :b => 'ho', :h => {:b => 'hey', :c => 'fo'}
8
+ response.code.should == "200"
9
+ end
10
+
11
+ it "should not allow combinations outside of the options" do
12
+ begin
13
+ post :update, :a => 'hi', :b => 'ho', :h => {:b => 'hey', :c => 'fo'}
14
+ raise "should fail"
15
+ rescue ParamAccessible::Error => e
16
+ e.inaccessible_params.should == %w(a h[c])
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe NotAcceptableController do
4
+ include RSpec::Rails::ControllerExampleGroup
5
+
6
+ it "should rescue_from HTML and render 406" do
7
+ post :create, :bar => 'hi'
8
+ response.code.should == "406"
9
+ response.body.should include "bar is an invalid parameter"
10
+ end
11
+
12
+ it "should rescue_from json and render 406" do
13
+ post :create, :bar => 'hi', :format => "json"
14
+ response.code.should == "406"
15
+ response.body.should == {:error => {:message => "You supplied invalid parameters: bar"}}.to_json
16
+ end
17
+
18
+ it "should rescue_from xml and render 406" do
19
+ post :create, :bar => 'hi', :format => "json"
20
+ response.code.should == "406"
21
+ response.body.should == {:error => {:message => "You supplied invalid parameters: bar"}}.to_json
22
+ end
23
+
24
+ it "should rescue_from js and render 406" do
25
+ post :create, :bar => 'hi', :format => "js"
26
+ response.code.should == "406"
27
+ response.body.should == "// invalid parameters: bar\n"
28
+ end
29
+
30
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe OnlyController do
4
+ include RSpec::Rails::ControllerExampleGroup
5
+
6
+ it "should limit those attribute to ONLY those actions" do
7
+ post :create, :foo => "hi"
8
+ response.code.should == "200"
9
+ end
10
+
11
+ it "should disallow unknown attributes from those actions" do
12
+ begin
13
+ post :create, :bar => "hi"
14
+ raise "should fail"
15
+ rescue ParamAccessible::Error => e
16
+ e.inaccessible_params.should == %w(bar)
17
+ end
18
+ end
19
+
20
+ it "should obey nested attributes" do
21
+ post :update, :bar => {:baz => 'hi'}
22
+ response.code.should == "200"
23
+ end
24
+
25
+ it "should catch invalid nested attributes for those actions" do
26
+ begin
27
+ post :update, :bar => {:foo => 'hi'}
28
+ raise "should fail"
29
+ rescue ParamAccessible::Error => e
30
+ e.inaccessible_params.should == %w(bar[foo])
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SimpleController do
4
+ include RSpec::Rails::ControllerExampleGroup
5
+
6
+ it "should not complain if the attributes are missing" do
7
+ post :create
8
+ response.code.should == "200"
9
+ end
10
+
11
+ it "should not complain if a subset of those attributes are given" do
12
+ post :create, :foo => 'hi'
13
+ response.code.should == "200"
14
+ end
15
+
16
+ it "should not complain if exactly those attributes are given" do
17
+ post :create, :foo => 'hi', :bar => {:baz => 'hey', :nuts => 'ho'}
18
+ response.code.should == "200"
19
+ end
20
+
21
+ it "should not complain on actions outside of the before_filter" do
22
+ get :show, :unknown => 'hi'
23
+ response.code.should == '200'
24
+ end
25
+
26
+ it "should complain an unknown attribute is given" do
27
+ begin
28
+ post :create, :unknown => 'hi'
29
+ raise "should fail"
30
+ rescue ParamAccessible::Error => e
31
+ e.inaccessible_params.should == %w(unknown)
32
+ end
33
+ end
34
+
35
+ it "should complain an unknown nested attribute is given" do
36
+ begin
37
+ post :create, :bar => {:unknown => 'hi'}
38
+ raise "should fail"
39
+ rescue ParamAccessible::Error => e
40
+ e.inaccessible_params.should == %w(bar[unknown])
41
+ end
42
+ end
43
+
44
+ it "should handle nested arrays" do
45
+ post :create, :bar => [:baz => 'hi']
46
+ response.code.should == '200'
47
+ end
48
+
49
+ it "should be fine when the ONLY value is a value but not an options hash" do
50
+ SimpleController.param_accessible :bar => []
51
+ end
52
+
53
+ it "should raise an error when the last value is a hash, but not an options hash" do
54
+ lambda { SimpleController.param_accessible :foo, :bar => [] }.should raise_error(ArgumentError)
55
+ end
56
+
57
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe UnlessFalseController do
4
+ include RSpec::Rails::ControllerExampleGroup
5
+
6
+ it "should allow valid attributes" do
7
+ post :create, :foo => "hi"
8
+ response.code.should == "200"
9
+ end
10
+
11
+ it "should disallow invalid attributes" do
12
+ begin
13
+ post :create, :nuts => "hi"
14
+ raise "should fail"
15
+ rescue ParamAccessible::Error => e
16
+ e.inaccessible_params.should == %w(nuts)
17
+ end
18
+ end
19
+
20
+ it "should allow valid nested attributes" do
21
+ post :update, :bar => {:baz => 'hi'}
22
+ response.code.should == "200"
23
+ end
24
+
25
+ it "should disallow invalid nested attributes" do
26
+ begin
27
+ post :update, :bar => {:foo => 'hi'}
28
+ raise "should fail"
29
+ rescue ParamAccessible::Error => e
30
+ e.inaccessible_params.should == %w(bar[foo])
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe UnlessTrueController do
4
+ include RSpec::Rails::ControllerExampleGroup
5
+
6
+ it "should not allow the attribute" do
7
+ begin
8
+ post :create, :foo => "hi"
9
+ raise "should fail"
10
+ rescue ParamAccessible::Error => e
11
+ e.inaccessible_params.should == %w(foo)
12
+ end
13
+ end
14
+
15
+ it "should not allow the nested attribute" do
16
+ begin
17
+ post :create, :bar => {:baz => "hi"}
18
+ raise "should fail"
19
+ rescue ParamAccessible::Error => e
20
+ e.inaccessible_params.should == %w(bar)
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require "#{File.dirname(__FILE__)}/app_root/config/environment"
5
+
6
+ require 'simplecov'
7
+ SimpleCov.start do
8
+ add_filter do |src|
9
+ src.filename =~ /\/spec\//
10
+ end
11
+ end
12
+
13
+ require 'rspec'
14
+ require 'rspec/rails'
15
+ require 'param_accessible'
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: param_accessible
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dan Cunning
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: &177970 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *177970
25
+ - !ruby/object:Gem::Dependency
26
+ name: actionpack
27
+ requirement: &177640 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *177640
36
+ - !ruby/object:Gem::Dependency
37
+ name: rails
38
+ requirement: &177410 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 3.0.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *177410
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec-rails
49
+ requirement: &177110 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *177110
58
+ - !ruby/object:Gem::Dependency
59
+ name: simplecov
60
+ requirement: &176790 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *176790
69
+ description: Help secure your controllers from malicious parameters
70
+ email:
71
+ - dan@topdan.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .travis.yml
78
+ - Gemfile
79
+ - LICENSE
80
+ - README.md
81
+ - Rakefile
82
+ - lib/param_accessible.rb
83
+ - lib/param_accessible/controller_ext.rb
84
+ - lib/param_accessible/error.rb
85
+ - lib/param_accessible/not_acceptable_helper.rb
86
+ - lib/param_accessible/rule.rb
87
+ - lib/param_accessible/rules.rb
88
+ - lib/param_accessible/version.rb
89
+ - param_accessible.gemspec
90
+ - spec/app_root/app/controllers/application_controller.rb
91
+ - spec/app_root/app/controllers/except_controller.rb
92
+ - spec/app_root/app/controllers/if_false_controller.rb
93
+ - spec/app_root/app/controllers/if_true_controller.rb
94
+ - spec/app_root/app/controllers/merge_controller.rb
95
+ - spec/app_root/app/controllers/not_acceptable_controller.rb
96
+ - spec/app_root/app/controllers/only_controller.rb
97
+ - spec/app_root/app/controllers/simple_controller.rb
98
+ - spec/app_root/app/controllers/unless_false_controller.rb
99
+ - spec/app_root/app/controllers/unless_true_controller.rb
100
+ - spec/app_root/config/application.rb
101
+ - spec/app_root/config/environment.rb
102
+ - spec/app_root/config/routes.rb
103
+ - spec/lib/except_spec.rb
104
+ - spec/lib/if_false_spec.rb
105
+ - spec/lib/if_true_spec.rb
106
+ - spec/lib/merge_spec.rb
107
+ - spec/lib/not_acceptable_helper_spec.rb
108
+ - spec/lib/only_spec.rb
109
+ - spec/lib/simple_spec.rb
110
+ - spec/lib/unless_false_spec.rb
111
+ - spec/lib/unless_true_spec.rb
112
+ - spec/spec_helper.rb
113
+ homepage: ''
114
+ licenses: []
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 1.8.10
134
+ signing_key:
135
+ specification_version: 3
136
+ summary: Help secure your controllers from malicious parameters
137
+ test_files:
138
+ - spec/app_root/app/controllers/application_controller.rb
139
+ - spec/app_root/app/controllers/except_controller.rb
140
+ - spec/app_root/app/controllers/if_false_controller.rb
141
+ - spec/app_root/app/controllers/if_true_controller.rb
142
+ - spec/app_root/app/controllers/merge_controller.rb
143
+ - spec/app_root/app/controllers/not_acceptable_controller.rb
144
+ - spec/app_root/app/controllers/only_controller.rb
145
+ - spec/app_root/app/controllers/simple_controller.rb
146
+ - spec/app_root/app/controllers/unless_false_controller.rb
147
+ - spec/app_root/app/controllers/unless_true_controller.rb
148
+ - spec/app_root/config/application.rb
149
+ - spec/app_root/config/environment.rb
150
+ - spec/app_root/config/routes.rb
151
+ - spec/lib/except_spec.rb
152
+ - spec/lib/if_false_spec.rb
153
+ - spec/lib/if_true_spec.rb
154
+ - spec/lib/merge_spec.rb
155
+ - spec/lib/not_acceptable_helper_spec.rb
156
+ - spec/lib/only_spec.rb
157
+ - spec/lib/simple_spec.rb
158
+ - spec/lib/unless_false_spec.rb
159
+ - spec/lib/unless_true_spec.rb
160
+ - spec/spec_helper.rb