signed_form 0.0.1.pre1 → 0.0.1
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 +4 -4
- data/.travis.yml +7 -0
- data/Gemfile +16 -0
- data/README.md +35 -10
- data/Rakefile +12 -0
- data/lib/signed_form/action_controller/permit_signed_params.rb +15 -13
- data/lib/signed_form/action_view/form_helper.rb +1 -1
- data/lib/signed_form/form_builder.rb +47 -29
- data/lib/signed_form/hmac.rb +20 -20
- data/lib/signed_form/version.rb +1 -1
- data/lib/signed_form.rb +3 -0
- data/signed_form.gemspec +1 -0
- data/spec/form_builder_spec.rb +138 -0
- data/spec/{signed_form/hmac_spec.rb → hmac_spec.rb} +0 -0
- data/spec/permit_signed_params_spec.rb +36 -0
- data/spec/spec_helper.rb +52 -1
- metadata +24 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ddf93bef4e43341d61d7f414960eec2b5823eca9
|
4
|
+
data.tar.gz: a6e68f939dc46cb096fd6db9425ceca4559b682c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5665ef2bc0cf38caa6b908f3424c0b4f0a9fe5db124900556e457a7ca9891abec70be1fe75ed74311159ed3b89c85756fd45d0b9f639f16a913a54b815833a49
|
7
|
+
data.tar.gz: ecafd68f4aa85fbc3edb3321e4306c8603677ed30b6862c9b46e7dd4a72a5a193888e444d02dd4de2f10c8b27a303f199f550ba8c9ddf333c54685be163dc513
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -2,3 +2,19 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in signed_form.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
rails_version = ENV['RAILS_VERSION'] || 'master'
|
7
|
+
|
8
|
+
case rails_version
|
9
|
+
when /master/
|
10
|
+
gem "rails", github: "rails/rails"
|
11
|
+
when /3-2-stable/
|
12
|
+
gem "rails", github: "rails/rails", branch: "3-2-stable"
|
13
|
+
when /3-1-stable/
|
14
|
+
gem "rails", github: "rails/rails", branch: "3-1-stable"
|
15
|
+
when /3-0-stable/
|
16
|
+
gem "rails", github: "rails/rails", branch: "3-0-stable"
|
17
|
+
else
|
18
|
+
gem "rails", ENV['RAILS_VERSION']
|
19
|
+
end
|
20
|
+
|
data/README.md
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
# SignedForm
|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/signed_form)
|
4
|
+
[](https://travis-ci.org/erichmenge/signed_form)
|
5
|
+
[](https://codeclimate.com/github/erichmenge/signed_form)
|
6
|
+
|
3
7
|
SignedForm brings new convenience and security to your Rails 4 or Rails 3 application.
|
4
8
|
|
5
9
|
## How It Works
|
6
10
|
|
7
|
-
Traditionally, when you create a form with Rails you enter your fields using something like `f.
|
8
|
-
Once you're done making your form you need to make sure that you've either set those parameters as accessible in
|
9
|
-
model (Rails 3) or use `permit` (Rails 4). This is redundant. Why would you make a form for a user to fill out and
|
10
|
-
then not accept their input?
|
11
|
+
Traditionally, when you create a form with Rails you enter your fields using something like `f.text_field :name` and so
|
12
|
+
on. Once you're done making your form you need to make sure that you've either set those parameters as accessible in
|
13
|
+
the model (Rails 3) or use `permit` (Rails 4). This is redundant. Why would you make a form for a user to fill out and
|
14
|
+
then not accept their input? You need to always maintain this synchronization.
|
11
15
|
|
12
16
|
SignedForm generates a list of attributes that you have in your form and attaches them to be submitted with the form
|
13
17
|
along with a HMAC-SHA1 signature of those attributes to protect them from tampering. That means no more `permit` and
|
@@ -17,6 +21,8 @@ What this looks like:
|
|
17
21
|
|
18
22
|
``` erb
|
19
23
|
<%= signed_form_for(@user) do |f| %>
|
24
|
+
<% f.add_signed_fields :zipcode, :state # Optionally add additional fields to sign %>
|
25
|
+
|
20
26
|
<%= f.text_field :name %>
|
21
27
|
<%= f.text_field :address %>
|
22
28
|
<%= f.submit %>
|
@@ -40,9 +46,7 @@ way you use standard forms.
|
|
40
46
|
|
41
47
|
## Alpha Quality Software
|
42
48
|
|
43
|
-
|
44
|
-
on the code. This software should not be considered production ready. At this time it is only suitable for
|
45
|
-
experimentation.
|
49
|
+
This software should not be considered production ready. At this time it is only suitable for experimentation.
|
46
50
|
|
47
51
|
Now that I've made that disclaimer, you should know that SignedForm is functional.
|
48
52
|
|
@@ -57,7 +61,7 @@ SignedForm requires:
|
|
57
61
|
|
58
62
|
Add this line to your application's Gemfile:
|
59
63
|
|
60
|
-
gem 'signed_form', '0.0.1
|
64
|
+
gem 'signed_form', '~> 0.0.1'
|
61
65
|
|
62
66
|
And then execute:
|
63
67
|
|
@@ -68,12 +72,27 @@ gem. Please set it up as instructed on the linked GitHub repo.
|
|
68
72
|
|
69
73
|
If you're using Rails 4, it works out of the box.
|
70
74
|
|
75
|
+
You'll need to include `SignedForm::ActionController::PermitSignedParams` in the controller(s) you want to use SignedForm with. This can
|
76
|
+
be done application wide by adding the `include` to your ApplicationController.
|
77
|
+
|
78
|
+
``` ruby
|
79
|
+
ApplicationController < ActionController::Base
|
80
|
+
include SignedForm::ActionController::PermitSignedParams
|
81
|
+
|
82
|
+
# ...
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
71
86
|
You'll also need to create an initializer:
|
72
87
|
|
73
88
|
$ echo 'SignedForm::HMAC.secret_key = SecureRandom.hex(64)' > config/initializers/signed_form.rb
|
74
89
|
|
75
90
|
**IMPORTANT** Please read below for information regarding this secret key.
|
76
91
|
|
92
|
+
## Support for other Builders
|
93
|
+
|
94
|
+
* [SimpleForm](https://github.com/erichmenge/signed_form-simple_form)
|
95
|
+
|
77
96
|
## Special Considerations
|
78
97
|
|
79
98
|
If you're running only a single application server the above initializer should work great for you, with a couple of
|
@@ -83,12 +102,18 @@ remove a field someone could still access it using the old signature if some mal
|
|
83
102
|
|
84
103
|
If you're running multiple application servers, the above initializer will not work. You'll need to keep the key in sync
|
85
104
|
between all the servers. The security caveat with that is that if you ever remove a field from a form without updating
|
86
|
-
that secret key, a malicious user could still access the field with the old signature. So you'll probably want to
|
87
|
-
|
105
|
+
that secret key, a malicious user could still access the field with the old signature. So you'll probably want to choose
|
106
|
+
a new secret in the event you remove access to an attribute in a form.
|
88
107
|
|
89
108
|
My above initializer example errs on the side of caution, generating a new secret key every time the app starts up. Only
|
90
109
|
you can decide what is right for you with respect to the secret key.
|
91
110
|
|
111
|
+
### Caching
|
112
|
+
|
113
|
+
Another consideration to be aware of is caching. If you cache a form, and then change the secret key that form will
|
114
|
+
perpetually submit parameters that fail verification. So if you want to cache the form you should tie the cache key to
|
115
|
+
something that will be changed whenever the secret key changes.
|
116
|
+
|
92
117
|
## Contributing
|
93
118
|
|
94
119
|
1. Fork it
|
data/Rakefile
CHANGED
@@ -1 +1,13 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
require "rdoc/task"
|
3
|
+
|
4
|
+
desc 'Generate documentation.'
|
5
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
6
|
+
rdoc.rdoc_dir = 'rdoc'
|
7
|
+
rdoc.title = 'SignedForm'
|
8
|
+
|
9
|
+
rdoc.options << '--line-numbers'
|
10
|
+
rdoc.rdoc_files.include('README.md')
|
11
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
12
|
+
end
|
13
|
+
|
@@ -1,23 +1,25 @@
|
|
1
1
|
module SignedForm
|
2
|
-
module
|
3
|
-
|
4
|
-
|
2
|
+
module ActionController
|
3
|
+
module PermitSignedParams
|
4
|
+
def self.included(base)
|
5
|
+
base.prepend_before_filter :permit_signed_form_data
|
6
|
+
end
|
7
|
+
|
8
|
+
def permit_signed_form_data
|
9
|
+
return if request.method == 'GET' || params['form_signature'].blank?
|
5
10
|
|
6
|
-
|
11
|
+
data, signature = params['form_signature'].split('--', 2)
|
7
12
|
|
8
|
-
|
9
|
-
signature ||= ''
|
13
|
+
signature ||= ''
|
10
14
|
|
11
|
-
|
12
|
-
|
15
|
+
raise Errors::InvalidSignature, "Form signature is not valid" unless SignedForm::HMAC.verify_hmac signature, data
|
16
|
+
allowed_attributes = Marshal.load Base64.strict_decode64(data)
|
13
17
|
|
14
|
-
|
15
|
-
|
18
|
+
allowed_attributes.each do |k, v|
|
19
|
+
params[k] = params.require(k).permit(*v)
|
20
|
+
end
|
16
21
|
end
|
17
22
|
end
|
18
23
|
end
|
19
24
|
end
|
20
25
|
|
21
|
-
ActionController::Base.send :include, SignedForm::PermitSignedParams
|
22
|
-
ActionController::Base.prepend_before_filter :permit_signed_form_data
|
23
|
-
|
@@ -2,7 +2,7 @@ module SignedForm
|
|
2
2
|
module ActionView
|
3
3
|
module FormHelper
|
4
4
|
def signed_form_for(record, options = {}, &block)
|
5
|
-
options[:builder]
|
5
|
+
options[:builder] ||= SignedForm::FormBuilder
|
6
6
|
|
7
7
|
form_for(record, options) do |f|
|
8
8
|
output = capture(f, &block)
|
@@ -1,43 +1,61 @@
|
|
1
1
|
module SignedForm
|
2
2
|
class FormBuilder < ::ActionView::Helpers::FormBuilder
|
3
|
-
attr_accessor :signed_attributes, :signed_attributes_object
|
4
3
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
# Base methods for form signing. Include this module in your own builders to get signatures for the base input
|
5
|
+
# helpers. Add fields to sign with #add_signed_fields
|
6
|
+
module Methods
|
7
|
+
(::ActionView::Helpers::FormBuilder.field_helpers.map(&:to_s) - %w(label fields_for button apply_form_for_options!)).each do |h|
|
8
|
+
define_method(h) do |field, *args|
|
9
|
+
add_signed_fields field
|
10
|
+
super(field, *args)
|
11
|
+
end
|
10
12
|
end
|
11
|
-
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
def initialize(*) #:nodoc:#
|
15
|
+
super
|
16
|
+
if options[:signed_attributes_object]
|
17
|
+
self.signed_attributes_object = options[:signed_attributes_object]
|
18
|
+
else
|
19
|
+
self.signed_attributes = { object_name => [] }
|
20
|
+
self.signed_attributes_object = signed_attributes[object_name]
|
21
|
+
end
|
20
22
|
end
|
21
|
-
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
def form_signature_tag
|
25
|
+
signed_attributes.each { |k,v| v.uniq! if v.is_a?(Array) }
|
26
|
+
encoded_data = Base64.strict_encode64 Marshal.dump(signed_attributes)
|
27
|
+
signature = SignedForm::HMAC::create_hmac(encoded_data)
|
28
|
+
token = "#{encoded_data}--#{signature}"
|
29
|
+
%(<input type="hidden" name="form_signature" value="#{token}" />\n).html_safe
|
30
|
+
end
|
31
|
+
|
32
|
+
def fields_for(record_name, record_object = nil, fields_options = {}, &block)
|
33
|
+
hash = {}
|
34
|
+
array = []
|
35
|
+
|
36
|
+
if nested_attributes_association?(record_name)
|
37
|
+
hash["#{record_name}_attributes"] = fields_options[:signed_attributes_object] = array
|
38
|
+
else
|
39
|
+
hash[record_name] = fields_options[:signed_attributes_object] = array
|
40
|
+
end
|
29
41
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
42
|
+
add_signed_fields hash
|
43
|
+
|
44
|
+
content = super
|
45
|
+
array.uniq!
|
46
|
+
content
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_signed_fields(*fields)
|
50
|
+
signed_attributes_object.push(*fields)
|
36
51
|
end
|
37
52
|
|
38
|
-
|
39
|
-
|
53
|
+
private
|
54
|
+
|
55
|
+
attr_accessor :signed_attributes, :signed_attributes_object
|
40
56
|
end
|
57
|
+
|
58
|
+
include Methods
|
41
59
|
end
|
42
60
|
end
|
43
61
|
|
data/lib/signed_form/hmac.rb
CHANGED
@@ -2,35 +2,35 @@ require 'openssl'
|
|
2
2
|
|
3
3
|
module SignedForm
|
4
4
|
module HMAC
|
5
|
-
|
6
|
-
attr_accessor :secret_key
|
5
|
+
extend self
|
7
6
|
|
8
|
-
|
9
|
-
if secret_key.nil? || secret_key.empty?
|
10
|
-
raise Errors::NoSecretKey, "Please consult the README for instructions on creating a secret key"
|
11
|
-
end
|
7
|
+
attr_accessor :secret_key
|
12
8
|
|
13
|
-
|
9
|
+
def create_hmac(data)
|
10
|
+
if secret_key.nil? || secret_key.empty?
|
11
|
+
raise Errors::NoSecretKey, "Please consult the README for instructions on creating a secret key"
|
14
12
|
end
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
raise Errors::NoSecretKey, "Please consult the README for instructions on creating a secret key"
|
19
|
-
end
|
14
|
+
OpenSSL::HMAC.hexdigest OpenSSL::Digest::SHA1.new, secret_key, data
|
15
|
+
end
|
20
16
|
|
21
|
-
|
17
|
+
def verify_hmac(signature, data)
|
18
|
+
if secret_key.nil? || secret_key.empty?
|
19
|
+
raise Errors::NoSecretKey, "Please consult the README for instructions on creating a secret key"
|
22
20
|
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
secure_compare OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, secret_key, data), signature
|
23
|
+
end
|
24
|
+
|
25
|
+
# After the Rack implementation
|
26
|
+
def secure_compare(a, b)
|
27
|
+
return false unless a.bytesize == b.bytesize
|
27
28
|
|
28
|
-
|
29
|
+
l = a.unpack("C*")
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
31
|
+
r, i = 0, -1
|
32
|
+
b.each_byte { |v| r |= v ^ l[i+=1] }
|
33
|
+
r == 0
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
data/lib/signed_form/version.rb
CHANGED
data/lib/signed_form.rb
CHANGED
data/signed_form.gemspec
CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "rspec", "~> 2.13"
|
24
|
+
spec.add_development_dependency "activemodel", ">= 3.0"
|
24
25
|
|
25
26
|
spec.add_dependency "actionpack", ">= 3.0"
|
26
27
|
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class User
|
4
|
+
extend ActiveModel::Naming
|
5
|
+
|
6
|
+
attr_accessor :name, :widgets_attributes
|
7
|
+
|
8
|
+
def to_key
|
9
|
+
[1]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Widget
|
14
|
+
extend ActiveModel::Naming
|
15
|
+
|
16
|
+
attr_accessor :name
|
17
|
+
|
18
|
+
def persisted?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe SignedForm::FormBuilder do
|
24
|
+
include SignedFormViewHelper
|
25
|
+
|
26
|
+
before { SignedForm::HMAC.secret_key = "abc123" }
|
27
|
+
after { SignedForm::HMAC.secret_key = nil }
|
28
|
+
|
29
|
+
let(:user) { User.new }
|
30
|
+
let(:widget) { Widget.new }
|
31
|
+
|
32
|
+
describe "signed_form_for" do
|
33
|
+
it "should build a form with signature" do
|
34
|
+
content = signed_form_for(User.new) do |f|
|
35
|
+
f.text_field :name
|
36
|
+
end
|
37
|
+
|
38
|
+
regex = '<form.*>.*<input type="hidden" name="form_signature" ' \
|
39
|
+
'value="BAh7BkkiCXVzZXIGOgZFRlsGOgluYW1l--e8f61481cb89382653c1f9de617e9a47e22c7da5".*/>.*' \
|
40
|
+
'<input.*name="user\[name\]".*/>.*' \
|
41
|
+
'</form>'
|
42
|
+
|
43
|
+
content.should =~ Regexp.new(regex, Regexp::MULTILINE)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "form inputs" do
|
48
|
+
(ActionView::Helpers::FormBuilder.field_helpers.map(&:to_s) - %w(label fields_for button radio_button apply_form_for_options!)).each do |field|
|
49
|
+
it "should add to the allowed attributes when #{field} is used" do
|
50
|
+
content = signed_form_for(User.new) do |f|
|
51
|
+
f.send field, :name
|
52
|
+
end
|
53
|
+
|
54
|
+
data = get_data_from_form(content)
|
55
|
+
data['user'].size.should == 1
|
56
|
+
data['user'].should include(:name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should add to the allowed attributes when radio_button is used" do
|
61
|
+
content = signed_form_for(User.new) do |f|
|
62
|
+
f.radio_button :name, ['bar']
|
63
|
+
end
|
64
|
+
|
65
|
+
data = get_data_from_form(content)
|
66
|
+
data['user'].size.should == 1
|
67
|
+
data['user'].should include(:name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "add_signed_fields" do
|
72
|
+
it "should add fields to the marshaled data" do
|
73
|
+
content = signed_form_for(User.new) do |f|
|
74
|
+
f.add_signed_fields :name, :address
|
75
|
+
end
|
76
|
+
|
77
|
+
data = get_data_from_form(content)
|
78
|
+
data['user'].should include(:name, :address)
|
79
|
+
data['user'].size.should == 2
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "fields_for" do
|
84
|
+
it "should nest attributes" do
|
85
|
+
user.stub(widgets: [widget])
|
86
|
+
|
87
|
+
content = signed_form_for(user) do |f|
|
88
|
+
f.fields_for :widgets do |ff|
|
89
|
+
ff.text_field :name
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
data = get_data_from_form(content)
|
94
|
+
data['user'].should include("widgets_attributes" => [:name])
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should deeply nest attributes" do
|
98
|
+
content = signed_form_for(:author, url: '/') do |f|
|
99
|
+
f.fields_for :books do |ff|
|
100
|
+
ff.text_field :name
|
101
|
+
ff.check_box :hardcover
|
102
|
+
ff.fields_for :pages do |fff|
|
103
|
+
fff.text_field :number
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
data = get_data_from_form(content)
|
109
|
+
|
110
|
+
data.should include(:author)
|
111
|
+
data[:author].first.should include(:books)
|
112
|
+
data[:author].first[:books].should include(:name, :hardcover, { pages: [:number] })
|
113
|
+
end
|
114
|
+
|
115
|
+
specify "nested arrays should not have duplicates" do
|
116
|
+
content = signed_form_for(:author, url: '/') do |f|
|
117
|
+
f.fields_for :books do |ff|
|
118
|
+
ff.text_field :name
|
119
|
+
ff.text_field :name
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
data = get_data_from_form(content)
|
124
|
+
data[:author].first[:books].size.should == 1
|
125
|
+
end
|
126
|
+
|
127
|
+
specify "attribute arrays should not have duplicates" do
|
128
|
+
content = signed_form_for(:author, url: '/') do |f|
|
129
|
+
f.text_field :name
|
130
|
+
f.text_field :name
|
131
|
+
end
|
132
|
+
|
133
|
+
data = get_data_from_form(content)
|
134
|
+
data[:author].size.should == 1
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
File without changes
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Controller < ActionController::Base
|
4
|
+
include SignedForm::ActionController::PermitSignedParams
|
5
|
+
end
|
6
|
+
|
7
|
+
describe SignedForm::ActionController::PermitSignedParams do
|
8
|
+
let(:controller) { Controller.new }
|
9
|
+
|
10
|
+
before do
|
11
|
+
SignedForm::HMAC.secret_key = "abc123"
|
12
|
+
|
13
|
+
Controller.any_instance.stub(request: double('request', method: 'POST'))
|
14
|
+
Controller.any_instance.stub(params: { "user" => { name: "Erich Menge", occupation: 'developer' } })
|
15
|
+
end
|
16
|
+
|
17
|
+
after { SignedForm::HMAC.secret_key = nil }
|
18
|
+
|
19
|
+
it "should raise if signature isn't valid" do
|
20
|
+
controller.params['form_signature'] = "bad signature"
|
21
|
+
expect { controller.permit_signed_form_data }.to raise_error(SignedForm::Errors::InvalidSignature)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should permit attributes that are allowed" do
|
25
|
+
params = controller.params
|
26
|
+
|
27
|
+
data = Base64.strict_encode64(Marshal.dump("user" => [:name]))
|
28
|
+
signature = SignedForm::HMAC.create_hmac(data)
|
29
|
+
|
30
|
+
params['form_signature'] = "#{data}--#{signature}"
|
31
|
+
|
32
|
+
params.should_receive(:require).with('user').and_return(params)
|
33
|
+
params.should_receive(:permit).with(:name).and_return(params)
|
34
|
+
controller.permit_signed_form_data
|
35
|
+
end
|
36
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,62 @@
|
|
1
1
|
require 'action_view'
|
2
|
+
require 'action_view/template'
|
3
|
+
require 'action_controller'
|
4
|
+
require 'active_model'
|
2
5
|
require 'action_controller'
|
3
6
|
require 'signed_form'
|
4
7
|
|
8
|
+
require 'active_support/core_ext'
|
9
|
+
|
10
|
+
module SignedFormViewHelper
|
11
|
+
include ActionView::Helpers::FormHelper
|
12
|
+
|
13
|
+
if defined?(ActionView::RecordIdentifier)
|
14
|
+
include ActionView::RecordIdentifier
|
15
|
+
elsif defined?(ActionController::RecordIdentifier)
|
16
|
+
include ActionController::RecordIdentifier
|
17
|
+
end
|
18
|
+
|
19
|
+
include ActionView::Context if defined?(ActionView::Context)
|
20
|
+
include SignedForm::ActionView::FormHelper
|
21
|
+
|
22
|
+
def self.included(base)
|
23
|
+
base.class_eval do
|
24
|
+
attr_accessor :output_buffer
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def protect_against_forgery?
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def user_path(*)
|
33
|
+
'/'
|
34
|
+
end
|
35
|
+
|
36
|
+
def polymorphic_path(*)
|
37
|
+
'/'
|
38
|
+
end
|
39
|
+
|
40
|
+
def _routes(*)
|
41
|
+
double('routes', url_for: '')
|
42
|
+
end
|
43
|
+
|
44
|
+
def controller(*)
|
45
|
+
double('controller')
|
46
|
+
end
|
47
|
+
|
48
|
+
def default_url_options
|
49
|
+
{}
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_data_from_form(content)
|
53
|
+
Marshal.load Base64.strict_decode64(content.match(/name="form_signature" value="(.*)--/)[1])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
5
57
|
RSpec.configure do |config|
|
6
58
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
7
59
|
config.run_all_when_everything_filtered = true
|
8
|
-
config.filter_run :focus
|
9
60
|
|
10
61
|
config.order = 'random'
|
11
62
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: signed_form
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Erich Menge
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-03-
|
11
|
+
date: 2013-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '2.13'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activemodel
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: actionpack
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,7 +102,9 @@ files:
|
|
88
102
|
- lib/signed_form/hmac.rb
|
89
103
|
- lib/signed_form/version.rb
|
90
104
|
- signed_form.gemspec
|
91
|
-
- spec/
|
105
|
+
- spec/form_builder_spec.rb
|
106
|
+
- spec/hmac_spec.rb
|
107
|
+
- spec/permit_signed_params_spec.rb
|
92
108
|
- spec/spec_helper.rb
|
93
109
|
homepage: https://github.com/erichmenge/signed_form
|
94
110
|
licenses:
|
@@ -105,9 +121,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
121
|
version: '1.9'
|
106
122
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
123
|
requirements:
|
108
|
-
- - '
|
124
|
+
- - '>='
|
109
125
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
126
|
+
version: '0'
|
111
127
|
requirements: []
|
112
128
|
rubyforge_project:
|
113
129
|
rubygems_version: 2.0.0
|
@@ -115,5 +131,7 @@ signing_key:
|
|
115
131
|
specification_version: 4
|
116
132
|
summary: Rails signed form security
|
117
133
|
test_files:
|
118
|
-
- spec/
|
134
|
+
- spec/form_builder_spec.rb
|
135
|
+
- spec/hmac_spec.rb
|
136
|
+
- spec/permit_signed_params_spec.rb
|
119
137
|
- spec/spec_helper.rb
|