shields_up 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +108 -0
- data/LICENSE +19 -0
- data/README.md +107 -0
- data/Rakefile +23 -0
- data/lib/shields_up/exceptions.rb +4 -0
- data/lib/shields_up/parameters.rb +158 -0
- data/lib/shields_up/shields_up.rb +10 -0
- data/lib/shields_up/version.rb +3 -0
- data/lib/shields_up.rb +3 -0
- data/shields_up.gemspec +21 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 391eded2ca4d95f1777b8a227f13905e7f01b975
|
4
|
+
data.tar.gz: 05c2a17280fb9c761b3743e688abcc3c9cbe97ce
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a13deb71b95918e3c1b7d297ec5f72a9d8b29a71d9a58c8f3259d09d9d8373aa2c6f7881b9f7c0c2c0b0df01adcd0f6f052383454ec527c2ac061faf045830a1
|
7
|
+
data.tar.gz: 4d99e218185e1db2828543e5c9ce39f469c593a9cc0a16c98516e1625ffe7d903acb7bf895c2b81ac830c85b49137aaf19d5562bf0bb785de84549da3a8732fd
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
shields_up (0.16.0)
|
5
|
+
activesupport (~> 3.2)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
actionmailer (3.2.19)
|
11
|
+
actionpack (= 3.2.19)
|
12
|
+
mail (~> 2.5.4)
|
13
|
+
actionpack (3.2.19)
|
14
|
+
activemodel (= 3.2.19)
|
15
|
+
activesupport (= 3.2.19)
|
16
|
+
builder (~> 3.0.0)
|
17
|
+
erubis (~> 2.7.0)
|
18
|
+
journey (~> 1.0.4)
|
19
|
+
rack (~> 1.4.5)
|
20
|
+
rack-cache (~> 1.2)
|
21
|
+
rack-test (~> 0.6.1)
|
22
|
+
sprockets (~> 2.2.1)
|
23
|
+
activemodel (3.2.19)
|
24
|
+
activesupport (= 3.2.19)
|
25
|
+
builder (~> 3.0.0)
|
26
|
+
activerecord (3.2.19)
|
27
|
+
activemodel (= 3.2.19)
|
28
|
+
activesupport (= 3.2.19)
|
29
|
+
arel (~> 3.0.2)
|
30
|
+
tzinfo (~> 0.3.29)
|
31
|
+
activeresource (3.2.19)
|
32
|
+
activemodel (= 3.2.19)
|
33
|
+
activesupport (= 3.2.19)
|
34
|
+
activesupport (3.2.19)
|
35
|
+
i18n (~> 0.6, >= 0.6.4)
|
36
|
+
multi_json (~> 1.0)
|
37
|
+
arel (3.0.3)
|
38
|
+
builder (3.0.4)
|
39
|
+
codeclimate-test-reporter (0.4.1)
|
40
|
+
simplecov (>= 0.7.1, < 1.0.0)
|
41
|
+
docile (1.1.5)
|
42
|
+
erubis (2.7.0)
|
43
|
+
hike (1.2.3)
|
44
|
+
i18n (0.6.9)
|
45
|
+
journey (1.0.4)
|
46
|
+
json (1.8.1)
|
47
|
+
mail (2.5.4)
|
48
|
+
mime-types (~> 1.16)
|
49
|
+
treetop (~> 1.4.8)
|
50
|
+
metaclass (0.0.4)
|
51
|
+
mime-types (1.25.1)
|
52
|
+
minitest (4.7.5)
|
53
|
+
mocha (1.1.0)
|
54
|
+
metaclass (~> 0.0.1)
|
55
|
+
multi_json (1.10.1)
|
56
|
+
polyglot (0.3.5)
|
57
|
+
rack (1.4.5)
|
58
|
+
rack-cache (1.2)
|
59
|
+
rack (>= 0.4)
|
60
|
+
rack-ssl (1.3.4)
|
61
|
+
rack
|
62
|
+
rack-test (0.6.2)
|
63
|
+
rack (>= 1.0)
|
64
|
+
rails (3.2.19)
|
65
|
+
actionmailer (= 3.2.19)
|
66
|
+
actionpack (= 3.2.19)
|
67
|
+
activerecord (= 3.2.19)
|
68
|
+
activeresource (= 3.2.19)
|
69
|
+
activesupport (= 3.2.19)
|
70
|
+
bundler (~> 1.0)
|
71
|
+
railties (= 3.2.19)
|
72
|
+
railties (3.2.19)
|
73
|
+
actionpack (= 3.2.19)
|
74
|
+
activesupport (= 3.2.19)
|
75
|
+
rack-ssl (~> 1.3.2)
|
76
|
+
rake (>= 0.8.7)
|
77
|
+
rdoc (~> 3.4)
|
78
|
+
thor (>= 0.14.6, < 2.0)
|
79
|
+
rake (10.3.2)
|
80
|
+
rdoc (3.12.2)
|
81
|
+
json (~> 1.4)
|
82
|
+
simplecov (0.9.1)
|
83
|
+
docile (~> 1.1.0)
|
84
|
+
multi_json (~> 1.0)
|
85
|
+
simplecov-html (~> 0.8.0)
|
86
|
+
simplecov-html (0.8.0)
|
87
|
+
sprockets (2.2.2)
|
88
|
+
hike (~> 1.2)
|
89
|
+
multi_json (~> 1.0)
|
90
|
+
rack (~> 1.0)
|
91
|
+
tilt (~> 1.1, != 1.3.0)
|
92
|
+
thor (0.19.1)
|
93
|
+
tilt (1.4.1)
|
94
|
+
treetop (1.4.15)
|
95
|
+
polyglot
|
96
|
+
polyglot (>= 0.3.1)
|
97
|
+
tzinfo (0.3.41)
|
98
|
+
|
99
|
+
PLATFORMS
|
100
|
+
ruby
|
101
|
+
|
102
|
+
DEPENDENCIES
|
103
|
+
activemodel
|
104
|
+
codeclimate-test-reporter
|
105
|
+
minitest (~> 4.0)
|
106
|
+
mocha
|
107
|
+
rails
|
108
|
+
shields_up!
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2014 Appfolio Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
[](https://travis-ci.org/appfolio/shields_up)
|
2
|
+
[](https://codeclimate.com/github/appfolio/shields_up)
|
3
|
+
[](https://codeclimate.com/github/appfolio/shields_up)
|
4
|
+
|
5
|
+
#Shields Up
|
6
|
+
This gem provides an alternative implementation of strong_parameters.
|
7
|
+
##usage (the grammar for permit statements is the same as strong_parameters)
|
8
|
+
- **Read this first**: [Strong Parameter Usage](http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters)
|
9
|
+
|
10
|
+
|
11
|
+
##Differences to strong parameter
|
12
|
+
params.symbolize_keys (or similar functions) will disable strong_parameters
|
13
|
+
protection silently. With ShieldsUp this can not happen.
|
14
|
+
|
15
|
+
## Enable ShieldsUp<br>
|
16
|
+
|
17
|
+
in Gemfile<br>
|
18
|
+
```
|
19
|
+
gem 'shields_up'
|
20
|
+
```
|
21
|
+
in controllers<br>
|
22
|
+
```
|
23
|
+
include ShieldsUp
|
24
|
+
```
|
25
|
+
|
26
|
+
- ShieldsUp::Parameter type only allows three operations: [], permit and require.
|
27
|
+
- You can use symbols or strings to access variables.<br>
|
28
|
+
|
29
|
+
##Example:<br>
|
30
|
+
```
|
31
|
+
params[:company]
|
32
|
+
```
|
33
|
+
not:
|
34
|
+
```
|
35
|
+
params["company"]
|
36
|
+
```
|
37
|
+
or
|
38
|
+
```
|
39
|
+
params.fetch(:company)
|
40
|
+
params.fetch("company")
|
41
|
+
```
|
42
|
+
|
43
|
+
##A more complicated example:<br>
|
44
|
+
```
|
45
|
+
params.permit(:company => [:address, :enabled])
|
46
|
+
```
|
47
|
+
not:
|
48
|
+
```
|
49
|
+
params.permit("company" => [:address, "enabled"])
|
50
|
+
```
|
51
|
+
|
52
|
+
## How to disable shields up.<br>
|
53
|
+
If you have a bunch of legacy code in a controller or you call into gems whose
|
54
|
+
parameter handling
|
55
|
+
you do not control (e.g. devise) you can disable shields_up at your own risk.
|
56
|
+
Similar to holding a lock around critical sections these blocks should generally be kept as short as possible.
|
57
|
+
<pre>
|
58
|
+
params.with_shields_down do
|
59
|
+
call_some_legacy_stuff_or_gem()
|
60
|
+
end
|
61
|
+
</pre>
|
62
|
+
<br>
|
63
|
+
- with_shields_down can not be nested. This means inside with_shields_down there should be no with_shields_down
|
64
|
+
- the places in an application disabling parameter protection are such explicit and can be accounted for during an audit
|
65
|
+
</b>
|
66
|
+
|
67
|
+
##Common Pitfalls:
|
68
|
+
- *to update and destroy associated records, permit <i>:id,</i> and <i> :_destroy </i> when you use accepts_nested_attributes_for in combination with a has_many association. <br>
|
69
|
+
|
70
|
+
Example:
|
71
|
+
```
|
72
|
+
# To whitelist the following data:
|
73
|
+
# {"applicant" => {"email_address" => "some@email.com",
|
74
|
+
# "contact_info_attributes" => { "1" => {"salutation" => "First Salutation"},
|
75
|
+
# "2" => {"salutation" => "Second Salutation"}}}}
|
76
|
+
params.permit(
|
77
|
+
{:applicant => [
|
78
|
+
:email_address,
|
79
|
+
{:contact_info_attributes => [:salutation, :id, :_destroy]},
|
80
|
+
]}
|
81
|
+
)
|
82
|
+
```
|
83
|
+
- *use hash inside permit statment** for non scaler type.<br>
|
84
|
+
|
85
|
+
Example:
|
86
|
+
```
|
87
|
+
# To whitelist the following data:
|
88
|
+
# {"applicant" => {"email_address" => "some@email.com",
|
89
|
+
# "info" => { "first_name" => 'First', "last_name" => 'Last'}}}
|
90
|
+
```
|
91
|
+
<pre>
|
92
|
+
params.permit(
|
93
|
+
{:applicant => [
|
94
|
+
:email_address,
|
95
|
+
<b>{</b>:info => [:first_name, :last_name]<b>}</b>
|
96
|
+
]}
|
97
|
+
)
|
98
|
+
</pre>
|
99
|
+
|
100
|
+
##Limitations
|
101
|
+
Similar to strong_parameters, this gem was designed with the most common use cases in mind. It is not meant as a silver bullet to handle all your whitelisting problems. However you can easily disable shields_up, and sanitize the parameter with your own code to adapt to your situation.<br>
|
102
|
+
|
103
|
+
In order to keep our grammar compatible to strong_parameters it is not possible
|
104
|
+
to express permission for array of arrays:
|
105
|
+
```
|
106
|
+
{'company' => [['a','b'],['a','b']]}
|
107
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts 'Run `bundle install` to install missing gems'
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'rake'
|
13
|
+
require 'rake/testtask'
|
14
|
+
|
15
|
+
namespace :test do
|
16
|
+
Rake::TestTask.new(:all) do |test|
|
17
|
+
test.libs << 'lib' << 'test'
|
18
|
+
test.pattern = 'test/shields_up/**/*_test.rb'
|
19
|
+
test.verbose = true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
task :default => 'test:all'
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
+
module ShieldsUp
|
3
|
+
class Parameters
|
4
|
+
if defined?(ActionController) && defined?(ActionController::Parameters)
|
5
|
+
PARAM_TYPE = ActionController::Parameters
|
6
|
+
else
|
7
|
+
PARAM_TYPE = ActiveSupport::HashWithIndifferentAccess
|
8
|
+
end
|
9
|
+
|
10
|
+
PERMITTED_SCALAR_TYPES = [
|
11
|
+
String,
|
12
|
+
Symbol,
|
13
|
+
NilClass,
|
14
|
+
Numeric,
|
15
|
+
TrueClass,
|
16
|
+
FalseClass,
|
17
|
+
Date,
|
18
|
+
Time,
|
19
|
+
# DateTimes are Dates, we document the type but avoid the redundant check.
|
20
|
+
StringIO,
|
21
|
+
IO,
|
22
|
+
]
|
23
|
+
if defined?(ActionDispatch) && defined?(ActionDispatch::Http) && defined?(ActionDispatch::Http::UploadedFile)
|
24
|
+
PERMITTED_SCALAR_TYPES << ActionDispatch::Http::UploadedFile
|
25
|
+
end
|
26
|
+
if defined?(Rack) && defined?(Rack::Test) && defined?(Rack::Test::UploadedFile)
|
27
|
+
PERMITTED_SCALAR_TYPES << Rack::Test::UploadedFile
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_shields_down
|
31
|
+
saved = @controller.params
|
32
|
+
@controller.params = @original_params
|
33
|
+
yield
|
34
|
+
ensure
|
35
|
+
@controller.params = saved
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(params, controller)
|
39
|
+
raise UnsupportedParameterType.new unless params.is_a? ActiveSupport::HashWithIndifferentAccess
|
40
|
+
@original_params = params
|
41
|
+
@controller = controller
|
42
|
+
@params = deep_dup_to_hash(params)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
@params.inspect
|
47
|
+
end
|
48
|
+
|
49
|
+
def permit(*permissions)
|
50
|
+
{}.tap do |permitted|
|
51
|
+
permissions.each do |permission|
|
52
|
+
permission, key = (permission.is_a?(Symbol) || permission.is_a?(String)) ? [permission, permission.to_s] : [permission.values.first, permission.keys.first.to_s]
|
53
|
+
if @params.has_key?(key)
|
54
|
+
if permission.is_a?(Symbol) || permission.is_a?(String)
|
55
|
+
result = permit_scalar(key)
|
56
|
+
permitted[key] = result if @params[key] == result
|
57
|
+
else
|
58
|
+
result = permit_nested(key, permission)
|
59
|
+
permitted[key] = result if result
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end.symbolize_keys
|
64
|
+
end
|
65
|
+
|
66
|
+
def require(key)
|
67
|
+
self[key] or raise ParameterMissing.new("Required parameter #{key} does not exist in #{to_s}")
|
68
|
+
end
|
69
|
+
|
70
|
+
# def permit!
|
71
|
+
# deep_dup_to_hash(@params).symbolize_keys
|
72
|
+
# end
|
73
|
+
|
74
|
+
def [](key)
|
75
|
+
key = key.to_s
|
76
|
+
value = @params[key]
|
77
|
+
if value.is_a?(Hash)
|
78
|
+
self.class.new(@original_params[key], @controller)
|
79
|
+
elsif value.is_a?(Array)
|
80
|
+
[].tap do |array|
|
81
|
+
value.each_with_index do |element, i|
|
82
|
+
if permitted_scalar?(element)
|
83
|
+
array << element
|
84
|
+
elsif element.is_a? Hash
|
85
|
+
array << self.class.new(@original_params[key][i], @controller)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
else
|
90
|
+
permit_scalar(key)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def permit_scalar(key)
|
97
|
+
permitted_scalar?(@params[key]) ? @params[key] : nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def permit_simple_hash(name, permissions)
|
101
|
+
if @params[name].is_a? Hash
|
102
|
+
self.class.new(@original_params[name], @controller).permit(*permissions)
|
103
|
+
else
|
104
|
+
permit_scalar(name)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def permit_nested_attributes_for(name, permissions)
|
109
|
+
{}.tap do |result|
|
110
|
+
@params[name].each do |key, value|
|
111
|
+
result[key] = self.class.new(@original_params[name][key], @controller).permit(*permissions) if value.is_a? Hash
|
112
|
+
result[key] = value if permitted_scalar?(value)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def permit_array_of_hashes(name, permissions)
|
118
|
+
@params[name].zip(@original_params[name]).select{|el| el[0].is_a? Hash}.collect{|el| self.class.new(el[1], @controller).permit(*permissions)}
|
119
|
+
end
|
120
|
+
|
121
|
+
def permit_scalars(name)
|
122
|
+
@params[name].select { |element| permitted_scalar? element }
|
123
|
+
end
|
124
|
+
|
125
|
+
def integer_key?(k)
|
126
|
+
k =~ /\A-?\d+\z/
|
127
|
+
end
|
128
|
+
|
129
|
+
def permit_nested(nested_name, permissions_for_nested)
|
130
|
+
if permissions_for_nested == [] # Declaration {:comment_ids => []}.
|
131
|
+
@params[nested_name].is_a?(Array) ? permit_scalars(nested_name) : nil
|
132
|
+
elsif @params[nested_name].is_a? Array # Declaration {:user => :name} or {:user => [:name, :age, {:adress => ...}]}.
|
133
|
+
permit_array_of_hashes(nested_name, permissions_for_nested)
|
134
|
+
elsif @params[nested_name].is_a?(Hash) && @params[nested_name].keys.all? { |k| integer_key?(k) } #{ '1' => {'title' => 'First Chapter'}, '2' => {'title' => 'Second Chapter'}}
|
135
|
+
permit_nested_attributes_for(nested_name, permissions_for_nested)
|
136
|
+
else
|
137
|
+
permit_simple_hash(nested_name, permissions_for_nested)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def permitted_scalar?(value)
|
142
|
+
PERMITTED_SCALAR_TYPES.any? {|type| value.is_a?(type)}
|
143
|
+
end
|
144
|
+
|
145
|
+
def deep_dup_to_hash(params)
|
146
|
+
return dup_if_possible(params) unless params.is_a?(PARAM_TYPE)
|
147
|
+
{}.tap do |dup|
|
148
|
+
params.each do |key, value|
|
149
|
+
dup[key] = deep_dup_to_hash(value)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def dup_if_possible(v)
|
155
|
+
v.duplicable? ? v.dup : v
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module ShieldsUp
|
2
|
+
def self.included(klass)
|
3
|
+
klass.before_filter do
|
4
|
+
self.params = ShieldsUp::Parameters.new(params, self) unless params.is_a?(ShieldsUp::Parameters)
|
5
|
+
end
|
6
|
+
klass.rescue_from(ShieldsUp::ParameterMissing) do |parameter_missing_exception|
|
7
|
+
render :text => "Required parameter missing: #{parameter_missing_exception}", :status => :bad_request
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/shields_up.rb
ADDED
data/shields_up.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'shields_up/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'shields_up'
|
8
|
+
s.version = ShieldsUp::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ['AppFolio']
|
11
|
+
s.email = 'dev@appfolio.com'
|
12
|
+
s.description = 'Mass assignment Protection made by AppFolio Inc., inspired by strong_parameters.'
|
13
|
+
s.summary = s.description
|
14
|
+
s.homepage = 'http://github.com/appfolio/shields_up'
|
15
|
+
s.licenses = ['MIT']
|
16
|
+
|
17
|
+
s.files = Dir['**/*'].reject{ |f| f[%r{^pkg/}] || f[%r{^test/}] }
|
18
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
s.require_paths = ['lib']
|
20
|
+
s.add_dependency('activesupport', '~> 3.2')
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shields_up
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.17.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- AppFolio
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.2'
|
27
|
+
description: Mass assignment Protection made by AppFolio Inc., inspired by strong_parameters.
|
28
|
+
email: dev@appfolio.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- Gemfile
|
34
|
+
- Gemfile.lock
|
35
|
+
- LICENSE
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- lib/shields_up.rb
|
39
|
+
- lib/shields_up/exceptions.rb
|
40
|
+
- lib/shields_up/parameters.rb
|
41
|
+
- lib/shields_up/shields_up.rb
|
42
|
+
- lib/shields_up/version.rb
|
43
|
+
- shields_up.gemspec
|
44
|
+
homepage: http://github.com/appfolio/shields_up
|
45
|
+
licenses:
|
46
|
+
- MIT
|
47
|
+
metadata: {}
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
requirements: []
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 2.2.2
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: Mass assignment Protection made by AppFolio Inc., inspired by strong_parameters.
|
68
|
+
test_files: []
|