action_interceptor 0.4.2 → 0.5.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 +4 -4
- data/README.md +1 -8
- data/config/initializers/action_interceptor.rb +20 -1
- data/lib/action_interceptor.rb +11 -7
- data/lib/action_interceptor/action_controller.rb +41 -30
- data/lib/action_interceptor/action_mailer.rb +3 -3
- data/lib/action_interceptor/common.rb +8 -8
- data/lib/action_interceptor/version.rb +1 -1
- data/spec/dummy/config/initializers/action_interceptor.rb +2 -0
- data/spec/lib/action_interceptor/action_controller_spec.rb +7 -4
- data/spec/lib/action_interceptor/action_mailer_spec.rb +4 -4
- data/spec/lib/action_interceptor_spec.rb +7 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9917c52164470d451b2fe730c0b95975a006eb59
|
4
|
+
data.tar.gz: 44dde1824b2307cdff19e5b6aea9bb6eed142c9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 12136e90006094d68efee066d82b60656e053b48fbe97860866e10295333d0520040b82e6c413e3397117083b447b5fd58388becf0edd4e90b4c5d890d5d0de2
|
7
|
+
data.tar.gz: a37aa52a41c91ca9627337a414a080707e25c2fd9107ea739e00a2afe47e9ab065a9507ecc761c09e7dd303bec98a9895ad05880d69236ac38ef88d8a839e283
|
data/README.md
CHANGED
@@ -33,14 +33,7 @@ $ rake action_interceptor:install
|
|
33
33
|
|
34
34
|
In case Action Interceptor is completely unable to determine which page a user
|
35
35
|
came from (should rarely happen if properly configured), it will send the user
|
36
|
-
to your application or gem's
|
37
|
-
|
38
|
-
```rb
|
39
|
-
root :to => 'some_controller#some_action'
|
40
|
-
```
|
41
|
-
|
42
|
-
Alternatively, you can always stub root_url in your
|
43
|
-
ApplicationController and make it a helper method.
|
36
|
+
to your application or gem's root (the '/' path).
|
44
37
|
|
45
38
|
## Usage
|
46
39
|
|
@@ -1,4 +1,7 @@
|
|
1
1
|
ActionInterceptor.configure do
|
2
|
+
# The following options can be set in this initializer
|
3
|
+
# or passed directly to acts_as_interceptor:
|
4
|
+
|
2
5
|
# intercepted_url_key(key)
|
3
6
|
# Type: Method
|
4
7
|
# Arguments: key (Symbol)
|
@@ -12,12 +15,28 @@ ActionInterceptor.configure do
|
|
12
15
|
# If true, the url_options method will be overriden for any controller that
|
13
16
|
# `acts_as_interceptor`. This option causes all links and redirects from any
|
14
17
|
# such controller to include a parameter containing the intercepted_url_key
|
15
|
-
# and the intercepted url.
|
18
|
+
# and the intercepted url.
|
16
19
|
# If set to false, you must use the interceptor_url_options method to obtain
|
17
20
|
# the hash and pass it to any links or redirects that need to use it.
|
18
21
|
# Default: true
|
19
22
|
override_url_options true
|
20
23
|
|
24
|
+
# skip_session(bool)
|
25
|
+
# Type: Method
|
26
|
+
# Arguments: bool (Boolean)
|
27
|
+
# If set to false, ActionInterceptor will store and use the intercepted url
|
28
|
+
# in the session object, under the :interceptor key. ActionInterceptor will
|
29
|
+
# attempt to retrieve the intercepted url from the url params, session and
|
30
|
+
# referer, in this order.
|
31
|
+
# If true, ActionInterceptor will ignore the session, so only the url params
|
32
|
+
# and the referer will be checked, in this order.
|
33
|
+
# Useful if you expect to get redirects that do not or cannot properly set
|
34
|
+
# the url params and must rely on the referer instead.
|
35
|
+
# Default: false
|
36
|
+
skip_session false
|
37
|
+
|
38
|
+
# The following options can only be set in this initializer:
|
39
|
+
|
21
40
|
# interceptor(interceptor_name, &block)
|
22
41
|
# Type: Method
|
23
42
|
# Arguments: interceptor name (Symbol or String),
|
data/lib/action_interceptor.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
require 'action_interceptor/engine'
|
2
2
|
|
3
3
|
module ActionInterceptor
|
4
|
-
def self.intercepted_url_key(key = nil)
|
5
|
-
@intercepted_url_key = key.to_s unless key.blank?
|
6
|
-
@intercepted_url_key || 'r'
|
7
|
-
end
|
8
4
|
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
DEFAULT_CONFIG = {}
|
6
|
+
|
7
|
+
INTERCEPTOR_ATTRIBUTES = [:intercepted_url_key,
|
8
|
+
:override_url_options,
|
9
|
+
:skip_session]
|
10
|
+
|
11
|
+
INTERCEPTOR_ATTRIBUTES.each do |attribute|
|
12
|
+
define_singleton_method(attribute) do |value|
|
13
|
+
DEFAULT_CONFIG[attribute] = value
|
14
|
+
end
|
12
15
|
end
|
13
16
|
|
14
17
|
def self.interceptors
|
@@ -22,4 +25,5 @@ module ActionInterceptor
|
|
22
25
|
def self.configure(&block)
|
23
26
|
instance_exec &block
|
24
27
|
end
|
28
|
+
|
25
29
|
end
|
@@ -6,25 +6,30 @@ module ActionInterceptor
|
|
6
6
|
module ActionController
|
7
7
|
|
8
8
|
def self.included(base)
|
9
|
-
base.class_attribute :
|
10
|
-
:interceptor_filters
|
11
|
-
base.is_interceptor = false
|
12
|
-
base.use_interceptor = false
|
9
|
+
base.class_attribute :interceptor_config, :interceptor_filters
|
13
10
|
base.interceptor_filters = {}
|
14
11
|
|
15
|
-
base.
|
12
|
+
base.send :attr_accessor, :interceptor_enabled
|
16
13
|
|
17
|
-
base.
|
18
|
-
|
14
|
+
base.before_filter :interceptor_setup
|
15
|
+
|
16
|
+
base.helper_method :_compute_redirect_to_location,
|
17
|
+
:interceptor_enabled, :interceptor_enabled=,
|
18
|
+
:is_interceptor?, :current_page?,
|
19
|
+
:current_url, :current_url_hash,
|
19
20
|
|
20
21
|
base.extend(ClassMethods)
|
21
22
|
end
|
22
23
|
|
24
|
+
protected
|
25
|
+
|
23
26
|
def _compute_redirect_to_location(*args, &block)
|
24
27
|
url_for(super(*args, &block))
|
25
28
|
end
|
26
29
|
|
27
|
-
|
30
|
+
def is_interceptor?
|
31
|
+
!interceptor_config.nil?
|
32
|
+
end
|
28
33
|
|
29
34
|
def current_page?(url)
|
30
35
|
# Blank is the current page
|
@@ -38,7 +43,7 @@ module ActionInterceptor
|
|
38
43
|
def current_url_hash
|
39
44
|
return @current_url_hash if @current_url_hash
|
40
45
|
|
41
|
-
key =
|
46
|
+
key = interceptor_config[:intercepted_url_key]
|
42
47
|
|
43
48
|
# Can't redirect back to non-get
|
44
49
|
# Also, can't call root_url here, so use '/' instead
|
@@ -47,8 +52,15 @@ module ActionInterceptor
|
|
47
52
|
@current_url_hash = {key => url}
|
48
53
|
end
|
49
54
|
|
50
|
-
def
|
51
|
-
|
55
|
+
def interceptor_setup
|
56
|
+
config = interceptor_config
|
57
|
+
if is_interceptor?
|
58
|
+
self.interceptor_enabled = interceptor_config[:override_url_options]
|
59
|
+
session.delete(:interceptor) if interceptor_config[:skip_session]
|
60
|
+
else
|
61
|
+
self.interceptor_enabled = false
|
62
|
+
session.delete(:interceptor)
|
63
|
+
end
|
52
64
|
end
|
53
65
|
|
54
66
|
module ClassMethods
|
@@ -83,18 +95,13 @@ module ActionInterceptor
|
|
83
95
|
skip_before_filter *fnames, options
|
84
96
|
end
|
85
97
|
|
86
|
-
def acts_as_interceptor(
|
87
|
-
self.
|
88
|
-
self.use_interceptor = options[:override_url_options].nil? ? \
|
89
|
-
ActionInterceptor.override_url_options : \
|
90
|
-
options[:override_url_options]
|
98
|
+
def acts_as_interceptor(opts = {})
|
99
|
+
self.interceptor_config = ActionInterceptor::DEFAULT_CONFIG.merge(opts)
|
91
100
|
|
92
101
|
class_exec do
|
93
102
|
|
94
103
|
attr_writer :intercepted_url
|
95
104
|
|
96
|
-
skip_before_filter :delete_intercepted_url
|
97
|
-
|
98
105
|
# Ensure that we always store the intercepted url
|
99
106
|
before_filter :intercepted_url
|
100
107
|
|
@@ -105,8 +112,11 @@ module ActionInterceptor
|
|
105
112
|
def intercepted_url
|
106
113
|
return @intercepted_url if @intercepted_url
|
107
114
|
|
108
|
-
key =
|
115
|
+
key = interceptor_config[:intercepted_url_key]
|
109
116
|
encrypted_url = params[key]
|
117
|
+
session_hash = session[:interceptor] \
|
118
|
+
unless interceptor_config[:skip_session]
|
119
|
+
session_hash ||= {}
|
110
120
|
|
111
121
|
begin
|
112
122
|
# URL params are the most reliable, as they preserve
|
@@ -114,17 +124,24 @@ module ActionInterceptor
|
|
114
124
|
# We need to sign them to prevent the Open Redirect vulnerability
|
115
125
|
@intercepted_url = Encryptor.decrypt_and_verify(encrypted_url)
|
116
126
|
|
117
|
-
# If we got this far, the encrypted url is valid
|
127
|
+
# If we got this far, the encrypted url is valid
|
128
|
+
# (i.e. we signed it), so reuse it
|
118
129
|
@intercepted_url_hash = {key => encrypted_url}
|
119
130
|
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
120
131
|
# If the param is not available, use our best guess
|
121
132
|
# Session and referer are safe for redirects (for that user)
|
122
133
|
# Also, can't call root_url here, so use '/' instead
|
123
|
-
@intercepted_url =
|
134
|
+
@intercepted_url = session_hash[key] || request.referer || '/'
|
124
135
|
end
|
136
|
+
|
137
|
+
# Prevent self-redirect
|
138
|
+
@intercepted_url = '/' if current_page?(@intercepted_url)
|
139
|
+
|
125
140
|
# Session is a signed plaintext in Rails 3
|
126
141
|
# In Rails 4, it is encrypted by default
|
127
|
-
session[
|
142
|
+
session[:interceptor] = session_hash.merge(
|
143
|
+
key => @intercepted_url) unless interceptor_config[:skip_session]
|
144
|
+
|
128
145
|
@intercepted_url
|
129
146
|
end
|
130
147
|
|
@@ -135,21 +152,15 @@ module ActionInterceptor
|
|
135
152
|
return @intercepted_url_hash if @intercepted_url_hash
|
136
153
|
|
137
154
|
url = Encryptor.encrypt_and_sign(unencrypted_url)
|
138
|
-
key =
|
155
|
+
key = interceptor_config[:intercepted_url_key]
|
139
156
|
|
140
157
|
@intercepted_url_hash = {key => url}
|
141
158
|
end
|
142
159
|
|
143
160
|
def redirect_back(options = {})
|
144
|
-
url = intercepted_url
|
145
|
-
|
146
161
|
# Disable the return_to param
|
147
162
|
without_interceptor do
|
148
|
-
|
149
|
-
# Also, prevent self redirects
|
150
|
-
url = root_url if url == '/' || current_page?(url)
|
151
|
-
|
152
|
-
redirect_to url, options
|
163
|
+
redirect_to intercepted_url, options
|
153
164
|
end
|
154
165
|
end
|
155
166
|
|
@@ -2,16 +2,16 @@ module ActionInterceptor
|
|
2
2
|
module ActionMailer
|
3
3
|
|
4
4
|
def self.included(base)
|
5
|
-
base.helper_method :
|
5
|
+
base.helper_method :interceptor_enabled, :interceptor_enabled=
|
6
6
|
end
|
7
7
|
|
8
8
|
protected
|
9
9
|
|
10
|
-
def
|
10
|
+
def interceptor_enabled
|
11
11
|
false
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def interceptor_enabled=(arg)
|
15
15
|
false
|
16
16
|
end
|
17
17
|
|
@@ -9,9 +9,9 @@ module ActionInterceptor
|
|
9
9
|
|
10
10
|
def url_for_with_interceptor(options = {})
|
11
11
|
url = url_for_without_interceptor(options)
|
12
|
-
return url unless
|
12
|
+
return url unless interceptor_enabled
|
13
13
|
|
14
|
-
@interceptor_url_for_hash ||= is_interceptor ? \
|
14
|
+
@interceptor_url_for_hash ||= is_interceptor? ? \
|
15
15
|
intercepted_url_hash : \
|
16
16
|
current_url_hash
|
17
17
|
|
@@ -26,12 +26,12 @@ module ActionInterceptor
|
|
26
26
|
|
27
27
|
# Executes the given block as if it was inside an interceptor
|
28
28
|
def with_interceptor(&block)
|
29
|
-
|
29
|
+
previous_interceptor_enabled = interceptor_enabled
|
30
30
|
|
31
31
|
begin
|
32
32
|
# Send the referer with intercepted requests
|
33
33
|
# So we don't rely on the user's browser to do it for us
|
34
|
-
self.
|
34
|
+
self.interceptor_enabled = true
|
35
35
|
|
36
36
|
# Execute the block as if it was defined in this controller
|
37
37
|
instance_exec &block
|
@@ -40,18 +40,18 @@ module ActionInterceptor
|
|
40
40
|
# and return the given value
|
41
41
|
e.exit_value
|
42
42
|
ensure
|
43
|
-
self.
|
43
|
+
self.interceptor_enabled = previous_interceptor_enabled
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
47
|
# Executes the given block as if it was not inside an interceptor
|
48
48
|
def without_interceptor(&block)
|
49
|
-
|
49
|
+
previous_interceptor_enabled = interceptor_enabled
|
50
50
|
|
51
51
|
begin
|
52
52
|
# Send the referer with intercepted requests
|
53
53
|
# So we don't rely on the user's browser to do it for us
|
54
|
-
self.
|
54
|
+
self.interceptor_enabled = false
|
55
55
|
|
56
56
|
# Execute the block as if it was defined in this controller
|
57
57
|
instance_exec &block
|
@@ -60,7 +60,7 @@ module ActionInterceptor
|
|
60
60
|
# and return the given value
|
61
61
|
e.exit_value
|
62
62
|
ensure
|
63
|
-
self.
|
63
|
+
self.interceptor_enabled = previous_interceptor_enabled
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -4,16 +4,19 @@ module ActionInterceptor
|
|
4
4
|
describe ActionController do
|
5
5
|
|
6
6
|
it 'modifies ActionController::Base' do
|
7
|
-
expect(::ActionController::Base).to respond_to(:is_interceptor)
|
8
|
-
expect(::ActionController::Base).to respond_to(:use_interceptor)
|
9
7
|
expect(::ActionController::Base).to respond_to(:interceptor_filters)
|
10
|
-
expect(::ActionController::Base.is_interceptor).to eq(false)
|
11
8
|
expect(::ActionController::Base.interceptor_filters).to be_a(Hash)
|
12
9
|
|
13
10
|
expect(::ActionController::Base).to respond_to(:interceptor)
|
14
11
|
expect(::ActionController::Base).to respond_to(:skip_interceptor)
|
15
12
|
expect(::ActionController::Base).to respond_to(:acts_as_interceptor)
|
16
13
|
|
14
|
+
expect(::ActionController::Base.new.respond_to?(
|
15
|
+
:is_interceptor?, true)).to eq(true)
|
16
|
+
expect(::ActionController::Base.new.send :is_interceptor?).to eq(false)
|
17
|
+
|
18
|
+
expect(::ActionController::Base.new.respond_to?(
|
19
|
+
:interceptor_enabled, true)).to eq(true)
|
17
20
|
expect(::ActionController::Base.new.respond_to?(
|
18
21
|
:current_page?, true)).to eq(true)
|
19
22
|
expect(::ActionController::Base.new.respond_to?(
|
@@ -23,7 +26,7 @@ module ActionInterceptor
|
|
23
26
|
end
|
24
27
|
|
25
28
|
it 'modifies classes that act_as_interceptor' do
|
26
|
-
expect(RegistrationsController.is_interceptor).to eq(true)
|
29
|
+
expect(RegistrationsController.new.send :is_interceptor?).to eq(true)
|
27
30
|
|
28
31
|
expect(RegistrationsController.new.respond_to?(
|
29
32
|
:intercepted_url, true)).to eq(true)
|
@@ -5,11 +5,11 @@ module ActionInterceptor
|
|
5
5
|
|
6
6
|
it 'modifies ActionMailer::Base' do
|
7
7
|
mailer = ::ActionMailer::Base.send(:new)
|
8
|
-
expect(mailer.respond_to?(:
|
9
|
-
expect(mailer.respond_to?(:
|
8
|
+
expect(mailer.respond_to?(:interceptor_enabled, true)).to eq(true)
|
9
|
+
expect(mailer.respond_to?(:interceptor_enabled=, true)).to eq(true)
|
10
10
|
|
11
|
-
expect(mailer.send(:
|
12
|
-
expect(mailer.send(:
|
11
|
+
expect(mailer.send(:interceptor_enabled)).to eq(false)
|
12
|
+
expect(mailer.send(:interceptor_enabled=, true)).to eq(false)
|
13
13
|
end
|
14
14
|
|
15
15
|
end
|
@@ -2,8 +2,9 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe ActionInterceptor do
|
4
4
|
it 'must be configurable' do
|
5
|
-
expect(ActionInterceptor
|
6
|
-
expect(ActionInterceptor
|
5
|
+
expect(ActionInterceptor::DEFAULT_CONFIG[:intercepted_url_key]).to eq(:dummy_key)
|
6
|
+
expect(ActionInterceptor::DEFAULT_CONFIG[:override_url_options]).to eq(true)
|
7
|
+
expect(ActionInterceptor::DEFAULT_CONFIG[:skip_session]).to eq(false)
|
7
8
|
expect(ActionInterceptor.interceptors.keys).to include(:registration)
|
8
9
|
|
9
10
|
my_block = lambda { 'my_block' }
|
@@ -11,11 +12,13 @@ describe ActionInterceptor do
|
|
11
12
|
ActionInterceptor.configure do
|
12
13
|
intercepted_url_key :my_key
|
13
14
|
override_url_options false
|
15
|
+
skip_session true
|
14
16
|
interceptor :my_name, &my_block
|
15
17
|
end
|
16
18
|
|
17
|
-
expect(ActionInterceptor
|
18
|
-
expect(ActionInterceptor
|
19
|
+
expect(ActionInterceptor::DEFAULT_CONFIG[:intercepted_url_key]).to eq(:my_key)
|
20
|
+
expect(ActionInterceptor::DEFAULT_CONFIG[:override_url_options]).to eq(false)
|
21
|
+
expect(ActionInterceptor::DEFAULT_CONFIG[:skip_session]).to eq(true)
|
19
22
|
expect(ActionInterceptor.interceptors).to include({:my_name => my_block})
|
20
23
|
end
|
21
24
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: action_interceptor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dante Soares
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|