action_controller-stashed_redirects 0.1.0 → 0.2.2
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/CHANGELOG.md +16 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +82 -52
- data/README.md +107 -3
- data/Rakefile +0 -9
- data/action_controller-stashed_redirects.gemspec +1 -1
- data/lib/action_controller/stashed_redirects/version.rb +1 -1
- data/lib/action_controller/stashed_redirects.rb +79 -48
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf64ad8ee2fb60526d8517bb26be521de7952bcfd87ed860bfe5ce2fe8a0deb0
|
4
|
+
data.tar.gz: ce4550656d8f30fc4629f72329229542c457403e95803177260fbe575e9ab51a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4188865c205f58bf080d879f50ad818716bac84145b568db85324ea5cbb1aa0f2afe1df87a8e9f2cb29be276ed66dfdceb9ca359e58292e7f11cfff5163c76e
|
7
|
+
data.tar.gz: 2ab7965676ca7d50f881f26ae8fb5bdac89624a02642303feeab5db5191065d73aa7af578533d98fa7b61eb72f8d34c33e8c2f6ad686aaf2a44d07ba32659f75
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.2.0] - 2022-04-21
|
4
|
+
|
5
|
+
- `stash_redirect_for` raises `ArgumentError` on invalid redirect URL
|
6
|
+
|
7
|
+
Protects against storing a URL that `redirect_to` can't redirect to later.
|
8
|
+
|
9
|
+
- `redirect_from_stashed` raises `ActionController::StashedRedirects::MissingRedirectError`
|
10
|
+
|
11
|
+
Useful to add a specific general fallback:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
class ApplicationController < ActionController::Base
|
15
|
+
rescue_from(ActionController::StashedRedirects::MissingRedirectError) { redirect_to root_url }
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
3
19
|
## [0.1.0] - 2022-04-21
|
4
20
|
|
5
21
|
- Initial release
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,89 +1,119 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
action_controller-stashed_redirects (0.
|
4
|
+
action_controller-stashed_redirects (0.2.2)
|
5
5
|
actionpack (>= 7.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
actionpack (7.
|
11
|
-
actionview (= 7.
|
12
|
-
activesupport (= 7.
|
13
|
-
|
10
|
+
actionpack (7.1.3.4)
|
11
|
+
actionview (= 7.1.3.4)
|
12
|
+
activesupport (= 7.1.3.4)
|
13
|
+
nokogiri (>= 1.8.5)
|
14
|
+
racc
|
15
|
+
rack (>= 2.2.4)
|
16
|
+
rack-session (>= 1.0.1)
|
14
17
|
rack-test (>= 0.6.3)
|
15
|
-
rails-dom-testing (~> 2.
|
16
|
-
rails-html-sanitizer (~> 1.
|
17
|
-
actionview (7.
|
18
|
-
activesupport (= 7.
|
18
|
+
rails-dom-testing (~> 2.2)
|
19
|
+
rails-html-sanitizer (~> 1.6)
|
20
|
+
actionview (7.1.3.4)
|
21
|
+
activesupport (= 7.1.3.4)
|
19
22
|
builder (~> 3.1)
|
20
|
-
erubi (~> 1.
|
21
|
-
rails-dom-testing (~> 2.
|
22
|
-
rails-html-sanitizer (~> 1.
|
23
|
-
activesupport (7.
|
23
|
+
erubi (~> 1.11)
|
24
|
+
rails-dom-testing (~> 2.2)
|
25
|
+
rails-html-sanitizer (~> 1.6)
|
26
|
+
activesupport (7.1.3.4)
|
27
|
+
base64
|
28
|
+
bigdecimal
|
24
29
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
30
|
+
connection_pool (>= 2.2.5)
|
31
|
+
drb
|
25
32
|
i18n (>= 1.6, < 2)
|
26
33
|
minitest (>= 5.1)
|
34
|
+
mutex_m
|
27
35
|
tzinfo (~> 2.0)
|
28
|
-
|
29
|
-
|
36
|
+
base64 (0.2.0)
|
37
|
+
bigdecimal (3.1.8)
|
38
|
+
builder (3.3.0)
|
39
|
+
concurrent-ruby (1.3.3)
|
40
|
+
connection_pool (2.4.1)
|
30
41
|
crass (1.0.6)
|
31
|
-
debug (1.
|
32
|
-
irb (
|
33
|
-
reline (>= 0.
|
34
|
-
|
35
|
-
|
42
|
+
debug (1.9.2)
|
43
|
+
irb (~> 1.10)
|
44
|
+
reline (>= 0.3.8)
|
45
|
+
drb (2.2.1)
|
46
|
+
erubi (1.13.0)
|
47
|
+
i18n (1.14.5)
|
36
48
|
concurrent-ruby (~> 1.0)
|
37
|
-
io-console (0.
|
38
|
-
irb (1.
|
39
|
-
|
40
|
-
|
49
|
+
io-console (0.7.2)
|
50
|
+
irb (1.13.2)
|
51
|
+
rdoc (>= 4.0.0)
|
52
|
+
reline (>= 0.4.2)
|
53
|
+
loofah (2.22.0)
|
41
54
|
crass (~> 1.0.2)
|
42
|
-
nokogiri (>= 1.
|
43
|
-
|
44
|
-
|
45
|
-
nokogiri (1.
|
55
|
+
nokogiri (>= 1.12.0)
|
56
|
+
minitest (5.24.1)
|
57
|
+
mutex_m (0.2.0)
|
58
|
+
nokogiri (1.16.6-aarch64-linux)
|
46
59
|
racc (~> 1.4)
|
47
|
-
nokogiri (1.
|
60
|
+
nokogiri (1.16.6-arm-linux)
|
48
61
|
racc (~> 1.4)
|
49
|
-
nokogiri (1.
|
62
|
+
nokogiri (1.16.6-arm64-darwin)
|
50
63
|
racc (~> 1.4)
|
51
|
-
nokogiri (1.
|
64
|
+
nokogiri (1.16.6-x86-linux)
|
52
65
|
racc (~> 1.4)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
66
|
+
nokogiri (1.16.6-x86_64-linux)
|
67
|
+
racc (~> 1.4)
|
68
|
+
psych (5.1.2)
|
69
|
+
stringio
|
70
|
+
racc (1.8.0)
|
71
|
+
rack (3.1.6)
|
72
|
+
rack-session (2.0.0)
|
73
|
+
rack (>= 3.0.0)
|
74
|
+
rack-test (2.1.0)
|
75
|
+
rack (>= 1.3)
|
76
|
+
rackup (2.1.0)
|
77
|
+
rack (>= 3)
|
78
|
+
webrick (~> 1.8)
|
79
|
+
rails-dom-testing (2.2.0)
|
80
|
+
activesupport (>= 5.0.0)
|
81
|
+
minitest
|
59
82
|
nokogiri (>= 1.6)
|
60
|
-
rails-html-sanitizer (1.
|
61
|
-
loofah (~> 2.
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
83
|
+
rails-html-sanitizer (1.6.0)
|
84
|
+
loofah (~> 2.21)
|
85
|
+
nokogiri (~> 1.14)
|
86
|
+
railties (7.1.3.4)
|
87
|
+
actionpack (= 7.1.3.4)
|
88
|
+
activesupport (= 7.1.3.4)
|
89
|
+
irb
|
90
|
+
rackup (>= 1.0.0)
|
66
91
|
rake (>= 12.2)
|
67
|
-
thor (~> 1.0)
|
68
|
-
zeitwerk (~> 2.
|
69
|
-
rake (13.
|
70
|
-
|
92
|
+
thor (~> 1.0, >= 1.2.2)
|
93
|
+
zeitwerk (~> 2.6)
|
94
|
+
rake (13.2.1)
|
95
|
+
rdoc (6.7.0)
|
96
|
+
psych (>= 4.0.0)
|
97
|
+
reline (0.5.9)
|
71
98
|
io-console (~> 0.5)
|
72
|
-
|
73
|
-
|
99
|
+
stringio (3.1.1)
|
100
|
+
thor (1.3.1)
|
101
|
+
tzinfo (2.0.6)
|
74
102
|
concurrent-ruby (~> 1.0)
|
75
|
-
|
103
|
+
webrick (1.8.1)
|
104
|
+
zeitwerk (2.6.16)
|
76
105
|
|
77
106
|
PLATFORMS
|
78
107
|
arm64-darwin-20
|
108
|
+
arm64-darwin-23
|
79
109
|
linux
|
80
110
|
|
81
111
|
DEPENDENCIES
|
82
112
|
action_controller-stashed_redirects!
|
83
113
|
debug
|
84
|
-
minitest
|
114
|
+
minitest
|
85
115
|
railties
|
86
116
|
rake (~> 13.0)
|
87
117
|
|
88
118
|
BUNDLED WITH
|
89
|
-
2.
|
119
|
+
2.5.14
|
data/README.md
CHANGED
@@ -12,13 +12,14 @@ class ApplicationController < ActionController::Base
|
|
12
12
|
|
13
13
|
private
|
14
14
|
def authenticate
|
15
|
-
|
15
|
+
# Pass `redirect_url:` to pass the URL we're currently on.
|
16
|
+
redirect_to new_session_url(redirect_url: request.url) unless Current.user
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
19
20
|
class SessionsController < ApplicationController
|
20
21
|
# Stash a redirect at the start of the session authentication flow,
|
21
|
-
# from
|
22
|
+
# from `params[:redirect_url]` automatically.
|
22
23
|
stash_redirect_for :sign_in, on: :new
|
23
24
|
|
24
25
|
def new
|
@@ -28,6 +29,8 @@ class SessionsController < ApplicationController
|
|
28
29
|
if User.authenticate_by(session_params)
|
29
30
|
# On success, redirect the user back to where they first tried to access before being authenticated.
|
30
31
|
redirect_from_stashed :sign_in
|
32
|
+
else
|
33
|
+
render :new, status: :unprocessable_entity
|
31
34
|
end
|
32
35
|
end
|
33
36
|
end
|
@@ -37,6 +40,107 @@ See the internal documentation for more usage information.
|
|
37
40
|
|
38
41
|
Only internal redirects are allowed, so attackers can't pass an external `redirect_url`.
|
39
42
|
|
43
|
+
### Making a sudo authentication system
|
44
|
+
|
45
|
+
Consider a flow where you want to require super-user, or sudo, privileges for a given action, e.g. type in your password before you can change your credit card.
|
46
|
+
|
47
|
+
We'll make a `require_sudo` API that we can annotate our controller with like this:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
class Billing::CreditCardsController < ApplicationController
|
51
|
+
require_sudo # Require sudo on all actions in this controller.
|
52
|
+
# require_sudo_on :edit, :update # Or just for some actions.
|
53
|
+
|
54
|
+
def edit
|
55
|
+
end
|
56
|
+
|
57
|
+
def update
|
58
|
+
Current.user.billing.credit_cards.find(params[:id]).update!(credit_card_params)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
`require_sudo` or `require_sudo_on` can come from a controller concern like this:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
# app/controllers/concerns/sudo/examination.rb
|
67
|
+
module Sudo::Examination
|
68
|
+
def self.included(klass) = klass.singleton_class.class_eval do
|
69
|
+
def require_sudo_on(*actions, **) = require_sudo(only: *actions, **)
|
70
|
+
def require_sudo(...) = before_action(:require_sudo, ...)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def require_sudo
|
75
|
+
if sudo.exam_needed?
|
76
|
+
raise "Non-get: can't redirect back here, make sure you do …something with an interstitial page?" unless request.get?
|
77
|
+
redirect_to new_sudo_exams_url(redirect_url: request.url)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def sudo = Sudo.new(session)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Which we include in ApplicationController:
|
85
|
+
class ApplicationController < ActionController::Base
|
86
|
+
include Sudo::Examination
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
Notice how in `redirect_to new_sudo_exams_url(redirect_url: request.url)` we're passing the `redirect_url:` along that `ActionController::StashedRedirects` will need.
|
91
|
+
It's pointing back to the page we're on, which required sudo authentication, so we can redirect back to it after the sudo exam has been passed.
|
92
|
+
|
93
|
+
Next up, we can add an in-memory PORO model to give the behavior some better names:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
# app/models/sudo.rb
|
97
|
+
class Sudo < Data.define(:store)
|
98
|
+
def passed!
|
99
|
+
store[:sudo_expires_at] = 15.minutes.from_now
|
100
|
+
end
|
101
|
+
|
102
|
+
def exam_needed?
|
103
|
+
expires_at = store[:sudo_expires_at]
|
104
|
+
expires_at.nil? || Time.parse(expires_at).past?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
109
|
+
Next, we can add the authenticating sudo controller itself, where `stash_redirect_for` will use the `redirect_url:` from earlier:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
# app/controllers/sudo/exams_controller.rb
|
113
|
+
class Sudo::ExamsController < ApplicationController
|
114
|
+
stash_redirect_for :sudo, on: :new
|
115
|
+
|
116
|
+
def new
|
117
|
+
redirect_from_stashed :sudo unless sudo.exam_needed?
|
118
|
+
end
|
119
|
+
|
120
|
+
def create
|
121
|
+
if pass_sudo_exam?
|
122
|
+
sudo.passed!
|
123
|
+
redirect_from_stashed :sudo
|
124
|
+
else
|
125
|
+
render :new, status: :unprocessable_entity
|
126
|
+
end
|
127
|
+
end
|
128
|
+
private def pass_sudo_exam? = Current.user.authenticate_password(params[:password])
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
Finally, we mount the routes for the controller:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
# config/routes.rb
|
136
|
+
namespace :sudo do
|
137
|
+
resources :exams
|
138
|
+
end
|
139
|
+
```
|
140
|
+
|
141
|
+
Users can now fill-in their password, which will hit `sudo/exams#create` and redirect them back to the edit form on the
|
142
|
+
credit cards flow if it's the correct password.
|
143
|
+
|
40
144
|
## Installation
|
41
145
|
|
42
146
|
Install the gem and add to the application's Gemfile by executing:
|
@@ -55,7 +159,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
55
159
|
|
56
160
|
## Contributing
|
57
161
|
|
58
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
162
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/kaspth/action_controller-stashed_redirects.
|
59
163
|
|
60
164
|
## License
|
61
165
|
|
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.summary = "Embed a controller flow within another by stashing the final redirect upfront and performing it after completing."
|
12
12
|
spec.homepage = "https://github.com/kaspth/action_controller-stashed_redirects"
|
13
13
|
spec.license = "MIT"
|
14
|
-
spec.required_ruby_version = ">=
|
14
|
+
spec.required_ruby_version = ">= 3.0.0"
|
15
15
|
|
16
16
|
spec.metadata["homepage_uri"] = spec.homepage
|
17
17
|
spec.metadata["source_code_uri"] = spec.homepage
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support"
|
4
|
-
require_relative "stashed_redirects/version"
|
5
4
|
|
6
5
|
# Pass between different controller flows via stashed redirects
|
7
6
|
#
|
@@ -9,67 +8,99 @@ require_relative "stashed_redirects/version"
|
|
9
8
|
module ActionController::StashedRedirects
|
10
9
|
extend ActiveSupport::Concern
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
autoload :VERSION, "action_controller/stashed_redirects/version"
|
12
|
+
|
13
|
+
# Allow a general `rescue ActionController::StashedRedirects::Error`.
|
14
|
+
Error = Module.new
|
15
|
+
|
16
|
+
class MissingRedirectError < StandardError
|
17
|
+
include Error
|
18
|
+
|
19
|
+
attr_reader :purpose
|
20
|
+
|
21
|
+
def initialize(purpose)
|
22
|
+
super "can't extract a stashed redirect_url to redirect_to"
|
23
|
+
@purpose = purpose
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
# stash_redirect_for :sign_in, from: :referer # Only derive the redirect URL from `request.referer`.
|
32
|
-
def stash_redirect_for(purpose, from: nil)
|
33
|
-
if url = derive_stash_redirect_url_from(from)
|
34
|
-
session[KEY_GENERATOR.(purpose)] = url
|
35
|
-
else
|
36
|
-
raise ArgumentError, "missing a redirect_url to stash, pass one via from: or via a redirect_url URL param"
|
27
|
+
class_methods do
|
28
|
+
# Adds a `before_action` to stash a redirect in a given `on:` action.
|
29
|
+
#
|
30
|
+
# stash_redirect_for :sign_in, on: :new
|
31
|
+
# stash_redirect_for :sign_in, on: %i[ new edit ]
|
32
|
+
# stash_redirect_for :sign_in, on: :new, url: -> { update_post_path(@post) }
|
33
|
+
def stash_redirect_for(purpose, on:, url: DEFAULT_URL)
|
34
|
+
before_action(-> { stash_redirect_for(purpose, url: url) }, only: on)
|
37
35
|
end
|
38
36
|
end
|
39
37
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
38
|
+
private
|
39
|
+
# Stashes a redirect URL in the `session` under the given +purpose+.
|
40
|
+
#
|
41
|
+
# An explicit +redirect_url+ can be passed in `from:`, otherwise the redirect URL is
|
42
|
+
# derived from `params[:redirect_url]` then falling back to `request.referer` on GET requests.
|
43
|
+
#
|
44
|
+
# stash_redirect_for :sign_in
|
45
|
+
# stash_redirect_for :sign_in, from: url_from(params[:redirect_url]) || root_url
|
46
|
+
# stash_redirect_for :sign_in, from: :param # Only derive the redirect URL from `params[:redirect_url]`.
|
47
|
+
# stash_redirect_for :sign_in, from: :referer # Only derive the redirect URL from `request.referer`.
|
48
|
+
def stash_redirect_for(purpose, url: DEFAULT_URL)
|
49
|
+
if url = derive_stash_redirect_url_from(url)
|
50
|
+
session[KEY_GENERATOR.(purpose)] = url
|
51
|
+
else
|
52
|
+
raise ArgumentError, "missing a redirect_url to stash, pass one via from: or via a redirect_url URL param"
|
53
|
+
end
|
54
|
+
end
|
50
55
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
56
|
+
# Finds and deletes the redirect stashed in `session` under the given +purpose+, then redirects.
|
57
|
+
#
|
58
|
+
# redirect_from_stashed :sign_in
|
59
|
+
#
|
60
|
+
# Raises if no stashed redirect is found under the given +purpose+.
|
61
|
+
#
|
62
|
+
# Relies on +redirect_to+'s open redirect protection, see it's documentation for more.
|
63
|
+
def redirect_from_stashed(purpose)
|
64
|
+
redirect_to stashed_redirect_url_for(purpose)
|
65
|
+
end
|
57
66
|
|
58
|
-
|
59
|
-
|
60
|
-
|
67
|
+
# Deletes and returns the redirect stashed in the `session` under the given +purpose+ if any.
|
68
|
+
#
|
69
|
+
# discard_stashed_redirect_for :sign_in # => the sign_in redirect URL or nil.
|
70
|
+
def discard_stashed_redirect_for(purpose)
|
71
|
+
session.delete(KEY_GENERATOR.(purpose))
|
72
|
+
end
|
61
73
|
|
62
74
|
def stashed_redirect_url_for(purpose)
|
63
|
-
|
64
|
-
|
75
|
+
url_from(discard_stashed_redirect_for(purpose)) or raise MissingRedirectError, purpose
|
76
|
+
end
|
65
77
|
|
66
|
-
|
78
|
+
def derive_stash_redirect_url_from(url)
|
79
|
+
case url
|
80
|
+
when DEFAULT_URL then redirect_url
|
81
|
+
when String then url_from url
|
82
|
+
when Symbol, Proc then url_from instance_exec(self, &url)
|
83
|
+
end
|
67
84
|
end
|
68
85
|
|
69
|
-
|
70
|
-
|
71
|
-
|
86
|
+
# Syntactic sugar for redirecting to `redirect_url` with a fallback.
|
87
|
+
#
|
88
|
+
# redirect_forward_or_to root_url # => redirect_to redirect_url || root_url
|
89
|
+
def redirect_forward_or_to(fallback_url)
|
90
|
+
redirect_to redirect_url || fallback_url
|
72
91
|
end
|
92
|
+
|
93
|
+
# Looks up a redirect URL from `params[:redirect_url]` using
|
94
|
+
# Rails' `url_from` as the protection mechanism to ensure it's a valid internal redirect.
|
95
|
+
# See the `url_from` docs: https://api.rubyonrails.org/classes/ActionController/Redirecting.html#method-i-url_from
|
96
|
+
#
|
97
|
+
# You probably want to use `redirect_forward_or_to`.
|
98
|
+
def redirect_url = url_from(params[:redirect_url])
|
99
|
+
|
100
|
+
DEFAULT_URL = Object.new
|
101
|
+
|
102
|
+
KEY_GENERATOR = ->(purpose) { "__url_stash_#{purpose}" }
|
103
|
+
private_constant :KEY_GENERATOR
|
73
104
|
end
|
74
105
|
|
75
106
|
ActiveSupport.on_load(:action_controller) { include ActionController::StashedRedirects }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: action_controller-stashed_redirects
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kasper Timm Hansen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -55,14 +55,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
55
55
|
requirements:
|
56
56
|
- - ">="
|
57
57
|
- !ruby/object:Gem::Version
|
58
|
-
version:
|
58
|
+
version: 3.0.0
|
59
59
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
61
|
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
63
|
version: '0'
|
64
64
|
requirements: []
|
65
|
-
rubygems_version: 3.
|
65
|
+
rubygems_version: 3.5.10
|
66
66
|
signing_key:
|
67
67
|
specification_version: 4
|
68
68
|
summary: Embed a controller flow within another by stashing the final redirect upfront
|