Skip to content

Commit 3bd6339

Browse files
skryukovbknoles
authored andcommitted
Add History encryption
1 parent 3af4b7a commit 3bd6339

File tree

11 files changed

+119
-7
lines changed

11 files changed

+119
-7
lines changed

lib/inertia_rails.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
props: options[:props],
1717
view_data: options[:view_data],
1818
deep_merge: options[:deep_merge],
19+
encrypt_history: options[:encrypt_history],
20+
clear_history: options[:clear_history],
1921
).render
2022
end
2123

lib/inertia_rails/configuration.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ class Configuration
1616
# controller configuration.
1717
layout: true,
1818

19+
# Whether to encrypt the history state in the client.
20+
encrypt_history: false,
21+
1922
# SSR options.
2023
ssr_enabled: false,
2124
ssr_url: 'http://localhost:13714',

lib/inertia_rails/controller.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def default_render
123123
end
124124

125125
def redirect_to(options = {}, response_options = {})
126-
capture_inertia_errors(response_options)
126+
capture_inertia_session_options(response_options)
127127
super
128128
end
129129

@@ -155,8 +155,10 @@ def inertia_location(url)
155155
head :conflict
156156
end
157157

158-
def capture_inertia_errors(options)
159-
if (inertia_errors = options.dig(:inertia, :errors))
158+
def capture_inertia_session_options(options)
159+
return unless (inertia = options[:inertia])
160+
161+
if (inertia_errors = inertia[:errors])
160162
if inertia_errors.respond_to?(:to_hash)
161163
session[:inertia_errors] = inertia_errors.to_hash
162164
else
@@ -165,7 +167,10 @@ def capture_inertia_errors(options)
165167
)
166168
session[:inertia_errors] = inertia_errors
167169
end
170+
168171
end
172+
173+
session[:inertia_clear_history] = inertia[:clear_history] if inertia[:clear_history]
169174
end
170175
end
171176
end

lib/inertia_rails/middleware.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# frozen_string_literal: true
2+
13
module InertiaRails
24
class Middleware
35
def initialize(app)
@@ -20,7 +22,10 @@ def response
2022
request = ActionDispatch::Request.new(@env)
2123

2224
# Inertia errors are added to the session via redirect_to
23-
request.session.delete(:inertia_errors) unless keep_inertia_errors?(status)
25+
unless keep_inertia_session_options?(status)
26+
request.session.delete(:inertia_errors)
27+
request.session.delete(:inertia_clear_history)
28+
end
2429

2530
status = 303 if inertia_non_post_redirect?(status)
2631

@@ -29,7 +34,7 @@ def response
2934

3035
private
3136

32-
def keep_inertia_errors?(status)
37+
def keep_inertia_session_options?(status)
3338
redirect_status?(status) || stale_inertia_request?
3439
end
3540

lib/inertia_rails/renderer.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ class Renderer
1515
:controller,
1616
:props,
1717
:view_data,
18+
:encrypt_history,
19+
:clear_history
1820
)
1921

20-
def initialize(component, controller, request, response, render_method, props: nil, view_data: nil, deep_merge: nil)
22+
def initialize(component, controller, request, response, render_method, props: nil, view_data: nil, deep_merge: nil, encrypt_history: nil, clear_history: nil)
2123
@controller = controller
2224
@configuration = controller.__send__(:inertia_configuration)
2325
@component = resolve_component(component)
@@ -27,6 +29,8 @@ def initialize(component, controller, request, response, render_method, props: n
2729
@props = props || controller.__send__(:inertia_view_assigns)
2830
@view_data = view_data || {}
2931
@deep_merge = !deep_merge.nil? ? deep_merge : configuration.deep_merge_shared_data
32+
@encrypt_history = !encrypt_history.nil? ? encrypt_history : configuration.encrypt_history
33+
@clear_history = clear_history || controller.session[:inertia_clear_history] || false
3034
end
3135

3236
def render
@@ -101,6 +105,8 @@ def page
101105
props: computed_props,
102106
url: @request.original_fullpath,
103107
version: configuration.version,
108+
encryptHistory: encrypt_history,
109+
clearHistory: clear_history,
104110
}
105111

106112
deferred_props = deferred_props_keys

spec/dummy/app/controllers/inertia_config_test_controller.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ class InertiaConfigTestController < ApplicationController
55
ssr_url: "http://localhost:7777",
66
layout: "test",
77
version: "1.0",
8+
encrypt_history: false,
89
)
910

1011
# Test that modules included in the same class can also call it.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class InertiaEncryptHistoryController < ApplicationController
2+
inertia_config(
3+
encrypt_history: -> { action_name != "default_config" }
4+
)
5+
6+
def default_config
7+
render inertia: 'TestComponent'
8+
end
9+
10+
def encrypt_history
11+
render inertia: 'TestComponent'
12+
end
13+
14+
def override_config
15+
render inertia: 'TestComponent', encrypt_history: false
16+
end
17+
18+
def clear_history
19+
render inertia: 'TestComponent', clear_history: true
20+
end
21+
22+
def clear_history_after_redirect
23+
redirect_to :empty_test, inertia: {clear_history: true}
24+
end
25+
end

spec/dummy/config/routes.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,10 @@
6161
get 'conditional_share_show' => 'inertia_conditional_sharing#show'
6262
get 'conditional_share_edit' => 'inertia_conditional_sharing#edit'
6363
get 'conditional_share_show_with_a_problem' => 'inertia_conditional_sharing#show_with_a_problem'
64+
65+
get 'encrypt_history_default_config' => 'inertia_encrypt_history#default_config'
66+
get 'encrypt_history_encrypt_history' => 'inertia_encrypt_history#encrypt_history'
67+
get 'encrypt_history_override_config' => 'inertia_encrypt_history#override_config'
68+
get 'encrypt_history_clear_history' => 'inertia_encrypt_history#clear_history'
69+
post 'encrypt_history_clear_history_after_redirect' => 'inertia_encrypt_history#clear_history_after_redirect'
6470
end

spec/inertia/configuration_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
ssr_enabled: true,
3030
ssr_url: "http://localhost:7777",
3131
version: "2.0",
32+
encrypt_history: false,
3233
)
3334
end
3435
end

spec/inertia/encrypt_history_spec.rb

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
RSpec.describe 'Inertia encrypt history', type: :request do
2+
let(:headers) { {'X-Inertia' => true} }
3+
4+
context 'with default config' do
5+
it 'returns encryptHistory false' do
6+
get encrypt_history_default_config_path, headers: headers
7+
8+
expect(response.parsed_body['encryptHistory']).to eq(false)
9+
expect(response.parsed_body['clearHistory']).to eq(false)
10+
end
11+
end
12+
13+
context 'with encrypt history config' do
14+
it 'returns encryptHistory true' do
15+
get encrypt_history_encrypt_history_path, headers: headers
16+
17+
expect(response.parsed_body['encryptHistory']).to eq(true)
18+
expect(response.parsed_body['clearHistory']).to eq(false)
19+
end
20+
end
21+
22+
context 'with override config' do
23+
24+
it 'returns encryptHistory false' do
25+
get encrypt_history_override_config_path, headers: headers
26+
27+
expect(response.parsed_body['encryptHistory']).to eq(false)
28+
expect(response.parsed_body['clearHistory']).to eq(false)
29+
end
30+
end
31+
32+
context 'with clear history' do
33+
it 'returns clearHistory true' do
34+
get encrypt_history_clear_history_path, headers: headers
35+
36+
expect(response.parsed_body['clearHistory']).to eq(true)
37+
end
38+
end
39+
40+
context 'with clear history on redirect' do
41+
it 'returns clearHistory true after the redirect' do
42+
post encrypt_history_clear_history_after_redirect_path, headers: headers
43+
44+
expect(response.headers['Location']).to eq(empty_test_url)
45+
expect(session[:inertia_clear_history]).to eq(true)
46+
47+
follow_redirect!
48+
expect(response.body).to include('&quot;clearHistory&quot;:true')
49+
50+
get empty_test_path, headers: headers
51+
expect(response.parsed_body['clearHistory']).to eq(false)
52+
end
53+
end
54+
end

0 commit comments

Comments
 (0)