double_trouble 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +48 -2
- data/lib/double_trouble/protection.rb +15 -20
- data/lib/double_trouble/version.rb +1 -1
- metadata +6 -6
data/README.rdoc
CHANGED
@@ -1,10 +1,56 @@
|
|
1
1
|
= Double Trouble
|
2
2
|
|
3
|
-
Adds nonces to your Rails' forms
|
3
|
+
Adds nonces to your Rails' forms, avoiding duplicates by sending the
|
4
|
+
same form again (when the user has ADHD, as well in the other
|
5
|
+
situations).
|
4
6
|
|
5
7
|
== Installation
|
6
8
|
|
7
|
-
gem install
|
9
|
+
gem install double_trouble
|
10
|
+
|
11
|
+
== Usage
|
12
|
+
|
13
|
+
class CommentsController < ApplicationController
|
14
|
+
protect_from_double_trouble :comment, :only => :create
|
15
|
+
|
16
|
+
def create
|
17
|
+
@comment = Comment.new(params[:comment])
|
18
|
+
if @comment.save
|
19
|
+
# ordinary stuff
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Double trouble works quite similar to CSRF protection
|
25
|
+
(authenticity_token) - it adds form_nonce parameter to your
|
26
|
+
forms. After the protected model is successfully saved (when
|
27
|
+
new_record? returns false), it stores received form_nonce in the
|
28
|
+
Rails.cache by default (you can easily replace the default store by DB
|
29
|
+
backend for instance).
|
30
|
+
|
31
|
+
== Configuration
|
32
|
+
|
33
|
+
You can globally turn the protection off (test environment?):
|
34
|
+
|
35
|
+
ActionController::Base.allow_double_trouble_protection = false
|
36
|
+
|
37
|
+
Default nonce store can be changed:
|
38
|
+
|
39
|
+
ActionController::Base.double_trouble_nonce_store = FormNonce
|
40
|
+
|
41
|
+
FormNonce class must implement two class methods:
|
42
|
+
|
43
|
+
def self.valid?(nonce)
|
44
|
+
# checks if the nonce has not been used before
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.store!(nonce)
|
48
|
+
# stores the given nonce somewhere
|
49
|
+
end
|
50
|
+
|
51
|
+
The name of the form nonce param can be changed as well:
|
52
|
+
|
53
|
+
ActionController::Base.double_trouble_nonce_param = :double_trouble_nonce
|
8
54
|
|
9
55
|
== Copyright
|
10
56
|
|
@@ -3,52 +3,47 @@ module DoubleTrouble
|
|
3
3
|
def self.included(base)
|
4
4
|
base.class_eval do
|
5
5
|
class_inheritable_accessor :allow_double_trouble_protection
|
6
|
-
class_inheritable_accessor :double_trouble_resource_name
|
7
6
|
cattr_accessor :double_trouble_nonce_store
|
8
7
|
cattr_accessor :double_trouble_nonce_param
|
9
8
|
helper_method :protect_against_double_trouble?, :double_trouble_nonce_param, :double_trouble_form_nonce
|
10
9
|
|
11
10
|
self.allow_double_trouble_protection = true
|
11
|
+
|
12
12
|
extend(ClassMethods)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
module ClassMethods
|
17
17
|
def protect_from_double_trouble(resource_name, options = {})
|
18
|
-
self.double_trouble_resource_name = resource_name
|
19
18
|
self.double_trouble_nonce_param ||= :form_nonce
|
20
19
|
self.double_trouble_nonce_store ||= CachedNonce
|
21
20
|
|
22
|
-
around_filter
|
23
|
-
|
24
|
-
|
21
|
+
around_filter(options.slice(:only, :except)) do |controller, action_block|
|
22
|
+
if controller.send(:protect_against_double_trouble?)
|
23
|
+
nonce = controller.params[double_trouble_nonce_param]
|
25
24
|
|
26
|
-
|
25
|
+
double_trouble_nonce_store.valid?(nonce) || raise(InvalidNonce)
|
27
26
|
|
28
|
-
|
29
|
-
if protect_against_double_trouble?
|
30
|
-
nonce = params[double_trouble_nonce_param]
|
31
|
-
store = double_trouble_nonce_store
|
27
|
+
action_block.call
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
29
|
+
controller.instance_variable_get("@#{resource_name}").tap do |resource|
|
30
|
+
resource.present? && !resource.new_record? && double_trouble_nonce_store.store!(nonce)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
action_block.call
|
34
|
+
end
|
37
35
|
end
|
38
|
-
else
|
39
|
-
yield
|
40
36
|
end
|
41
37
|
end
|
42
38
|
|
39
|
+
protected
|
40
|
+
|
43
41
|
def double_trouble_form_nonce
|
44
42
|
ActiveSupport::SecureRandom.base64(32)
|
45
43
|
end
|
46
44
|
|
47
45
|
def protect_against_double_trouble?
|
48
|
-
allow_double_trouble_protection &&
|
49
|
-
double_trouble_resource_name &&
|
50
|
-
double_trouble_nonce_store &&
|
51
|
-
double_trouble_nonce_param
|
46
|
+
allow_double_trouble_protection && double_trouble_nonce_store && double_trouble_nonce_param
|
52
47
|
end
|
53
48
|
end
|
54
49
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: double_trouble
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Jakub Ku\xC5\xBAma"
|
@@ -72,11 +72,11 @@ extensions: []
|
|
72
72
|
extra_rdoc_files: []
|
73
73
|
|
74
74
|
files:
|
75
|
-
- lib/double_trouble/errors.rb
|
76
|
-
- lib/double_trouble/cached_nonce.rb
|
77
75
|
- lib/double_trouble/form_tag_helper_hack.rb
|
78
|
-
- lib/double_trouble/version.rb
|
79
76
|
- lib/double_trouble/protection.rb
|
77
|
+
- lib/double_trouble/cached_nonce.rb
|
78
|
+
- lib/double_trouble/version.rb
|
79
|
+
- lib/double_trouble/errors.rb
|
80
80
|
- lib/double_trouble.rb
|
81
81
|
- LICENSE
|
82
82
|
- README.rdoc
|