Add some local storage to save settings between

page reloads.
This commit is contained in:
2025-12-12 12:48:44 -05:00
parent aeafdcee1a
commit b465235096
9 changed files with 379 additions and 21 deletions
+70
View File
@@ -0,0 +1,70 @@
using Serilog.Core;
using Serilog.Events;
using Serilog.Parsing;
namespace WebApp.Logging
{
/// <summary>
/// Custom Serilog sink that downgrades antiforgery token deserialization errors to Information level
/// </summary>
public class AntiforgeryLogEventSink : ILogEventSink
{
private readonly ILogEventSink _wrappedSink;
private readonly MessageTemplateParser _parser;
public AntiforgeryLogEventSink(ILogEventSink wrappedSink)
{
_wrappedSink = wrappedSink;
_parser = new MessageTemplateParser();
}
public void Emit(LogEvent logEvent)
{
// Check if this is an antiforgery token deserialization error (Event ID 7)
if (IsTokenDeserializeException(logEvent))
{
// Rewrite the log event at Information level with explanatory message
var messageTemplate = _parser.Parse(
"Antiforgery token validation failed - expected after container restart. " +
"User will receive a fresh token on page refresh. Original message: {OriginalMessage}");
var rewrittenEvent = new LogEvent(
logEvent.Timestamp,
LogEventLevel.Information,
null, // No exception at Info level
messageTemplate,
new[]
{
new LogEventProperty("OriginalMessage",
new ScalarValue(logEvent.MessageTemplate.Render(logEvent.Properties))),
new LogEventProperty("SourceContext",
logEvent.Properties.GetValueOrDefault("SourceContext") ?? new ScalarValue("Unknown")),
new LogEventProperty("RequestPath",
logEvent.Properties.GetValueOrDefault("RequestPath") ?? new ScalarValue("Unknown"))
});
_wrappedSink.Emit(rewrittenEvent);
}
else
{
// Pass through all other log events unchanged
_wrappedSink.Emit(logEvent);
}
}
private bool IsTokenDeserializeException(LogEvent logEvent)
{
if (logEvent.Level != LogEventLevel.Error)
return false;
if (logEvent.Properties.TryGetValue("EventId", out var eventId))
{
var eventIdString = eventId.ToString();
return eventIdString.Contains("\"Id\":7") &&
eventIdString.Contains("\"Name\":\"TokenDeserializeException\"");
}
return false;
}
}
}