Skip to content

Commit 81aa149

Browse files
adrumkapi2289
andauthoredFeb 23, 2025··
[2.x] History Encryption (#25)
* added header constants * refactor resolve props * added always prop * added always prop test * added async task wrapper * added clear history & history encryption * Delete InertiaCore/Utils/Header.cs * fix test sdks? * Minor changes --------- Co-authored-by: Kacper Ziubryniewicz <[email protected]>
1 parent 5a1c858 commit 81aa149

File tree

5 files changed

+110
-5
lines changed

5 files changed

+110
-5
lines changed
 

‎InertiaCore/Models/InertiaOptions.cs

+1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ public class InertiaOptions
66

77
public bool SsrEnabled { get; set; } = false;
88
public string SsrUrl { get; set; } = "http://127.0.0.1:13714/render";
9+
public bool EncryptHistory { get; set; } = false;
910
}

‎InertiaCore/Models/Page.cs

+2
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ internal class Page
66
public string Component { get; set; } = default!;
77
public string? Version { get; set; }
88
public string Url { get; set; } = default!;
9+
public bool EncryptHistory { get; set; } = false;
10+
public bool ClearHistory { get; set; } = false;
911
}

‎InertiaCore/Response.cs

+8-4
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ public class Response : IActionResult
1616
private readonly Dictionary<string, object?> _props;
1717
private readonly string _rootView;
1818
private readonly string? _version;
19+
private readonly bool _encryptHistory;
20+
private readonly bool _clearHistory;
1921

2022
private ActionContext? _context;
2123
private Page? _page;
2224
private IDictionary<string, object>? _viewData;
2325

24-
internal Response(string component, Dictionary<string, object?> props, string rootView, string? version)
25-
=> (_component, _props, _rootView, _version) = (component, props, rootView, version);
26+
internal Response(string component, Dictionary<string, object?> props, string rootView, string? version, bool encryptHistory, bool clearHistory)
27+
=> (_component, _props, _rootView, _version, _encryptHistory, _clearHistory) = (component, props, rootView, version, encryptHistory, clearHistory);
2628

2729
public async Task ExecuteResultAsync(ActionContext context)
2830
{
@@ -40,7 +42,9 @@ protected internal async Task ProcessResponse()
4042
Component = _component,
4143
Version = _version,
4244
Url = _context!.RequestedUri(),
43-
Props = props
45+
Props = props,
46+
EncryptHistory = _encryptHistory,
47+
ClearHistory = _clearHistory,
4448
};
4549

4650
page.Props["errors"] = GetErrors();
@@ -169,7 +173,7 @@ protected internal async Task ProcessResponse()
169173
protected internal JsonResult GetJson()
170174
{
171175
_context!.HttpContext.Response.Headers.Override(InertiaHeader.Inertia, "true");
172-
_context!.HttpContext.Response.Headers.Override("Vary", "Accept");
176+
_context!.HttpContext.Response.Headers.Override("Vary", InertiaHeader.Inertia);
173177
_context!.HttpContext.Response.StatusCode = 200;
174178

175179
return new JsonResult(_page, new JsonSerializerOptions

‎InertiaCore/ResponseFactory.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ internal interface IResponseFactory
2222
public LocationResult Location(string url);
2323
public void Share(string key, object? value);
2424
public void Share(IDictionary<string, object?> data);
25+
public void ClearHistory(bool clear = true);
26+
public void EncryptHistory(bool encrypt = true);
2527
public AlwaysProp Always(object? value);
2628
public AlwaysProp Always(Func<object?> callback);
2729
public AlwaysProp Always(Func<Task<object?>> callback);
@@ -36,6 +38,8 @@ internal class ResponseFactory : IResponseFactory
3638
private readonly IOptions<InertiaOptions> _options;
3739

3840
private object? _version;
41+
private bool _clearHistory;
42+
private bool? _encryptHistory;
3943

4044
public ResponseFactory(IHttpContextAccessor contextAccessor, IGateway gateway, IOptions<InertiaOptions> options) =>
4145
(_contextAccessor, _gateway, _options) = (contextAccessor, gateway, options);
@@ -50,7 +54,7 @@ public Response Render(string component, object? props = null)
5054
.ToDictionary(o => o.Name, o => o.GetValue(props))
5155
};
5256

53-
return new Response(component, dictProps, _options.Value.RootView, GetVersion());
57+
return new Response(component, dictProps, _options.Value.RootView, GetVersion(), _encryptHistory ?? _options.Value.EncryptHistory, _clearHistory);
5458
}
5559

5660
public async Task<IHtmlContent> Head(dynamic model)
@@ -131,6 +135,10 @@ public void Share(IDictionary<string, object?> data)
131135
context.Features.Set(sharedData);
132136
}
133137

138+
public void ClearHistory(bool clear = true) => _clearHistory = clear;
139+
140+
public void EncryptHistory(bool encrypt = true) => _encryptHistory = encrypt;
141+
134142
public LazyProp Lazy(Func<object?> callback) => new(callback);
135143
public LazyProp Lazy(Func<Task<object?>> callback) => new(callback);
136144
public AlwaysProp Always(object? value) => new(value);

‎InertiaCoreTests/UnitTestHistory.cs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using InertiaCore.Models;
2+
using Microsoft.AspNetCore.Http;
3+
using Microsoft.AspNetCore.Mvc;
4+
5+
namespace InertiaCoreTests;
6+
7+
public partial class Tests
8+
{
9+
[Test]
10+
[Description("Test if history encryption is sent correctly.")]
11+
public async Task TestHistoryEncryptionResult()
12+
{
13+
_factory.EncryptHistory();
14+
15+
var response = _factory.Render("Test/Page", new
16+
{
17+
Test = "Test"
18+
});
19+
20+
var headers = new HeaderDictionary
21+
{
22+
{ "X-Inertia", "true" }
23+
};
24+
25+
var context = PrepareContext(headers);
26+
27+
response.SetContext(context);
28+
await response.ProcessResponse();
29+
30+
var result = response.GetResult();
31+
32+
Assert.Multiple(() =>
33+
{
34+
Assert.That(result, Is.InstanceOf<JsonResult>());
35+
36+
var json = (result as JsonResult)?.Value;
37+
Assert.That(json, Is.InstanceOf<Page>());
38+
39+
Assert.That((json as Page)?.ClearHistory, Is.EqualTo(false));
40+
Assert.That((json as Page)?.EncryptHistory, Is.EqualTo(true));
41+
Assert.That((json as Page)?.Component, Is.EqualTo("Test/Page"));
42+
Assert.That((json as Page)?.Props, Is.EqualTo(new Dictionary<string, object?>
43+
{
44+
{ "test", "Test" },
45+
{ "errors", new Dictionary<string, string>(0) }
46+
}));
47+
});
48+
}
49+
50+
[Test]
51+
[Description("Test if clear history is sent correctly.")]
52+
public async Task TestClearHistoryResult()
53+
{
54+
_factory.ClearHistory();
55+
56+
var response = _factory.Render("Test/Page", new
57+
{
58+
Test = "Test"
59+
});
60+
61+
var headers = new HeaderDictionary
62+
{
63+
{ "X-Inertia", "true" }
64+
};
65+
66+
var context = PrepareContext(headers);
67+
68+
response.SetContext(context);
69+
await response.ProcessResponse();
70+
71+
var result = response.GetResult();
72+
73+
Assert.Multiple(() =>
74+
{
75+
Assert.That(result, Is.InstanceOf<JsonResult>());
76+
77+
var json = (result as JsonResult)?.Value;
78+
Assert.That(json, Is.InstanceOf<Page>());
79+
80+
Assert.That((json as Page)?.ClearHistory, Is.EqualTo(true));
81+
Assert.That((json as Page)?.EncryptHistory, Is.EqualTo(false));
82+
Assert.That((json as Page)?.Component, Is.EqualTo("Test/Page"));
83+
Assert.That((json as Page)?.Props, Is.EqualTo(new Dictionary<string, object?>
84+
{
85+
{ "test", "Test" },
86+
{ "errors", new Dictionary<string, string>(0) }
87+
}));
88+
});
89+
}
90+
}

0 commit comments

Comments
 (0)
Please sign in to comment.