Files
jsmr/JSMR.UI.Blazor/Components/Authentication/AuthenticationGate.razor

72 lines
1.8 KiB
Plaintext

@using JSMR.UI.Blazor.Services
@using Microsoft.AspNetCore.Components.Routing
@inject SessionState Session
@inject NavigationManager Navigation
@if (!_ready)
{
<p>Loading...</p>
}
else
{
@ChildContent
}
@code {
[Parameter] public RenderFragment? ChildContent { get; set; }
private bool _ready;
// Add any routes you want public here.
// Use absolute-path form (leading slash).
private static readonly HashSet<string> _allowAnonymous = new(StringComparer.OrdinalIgnoreCase)
{
"/login",
"/login/", // optional
};
protected override async Task OnInitializedAsync()
{
Navigation.LocationChanged += OnLocationChanged;
// One-time refresh at app start
await Session.RefreshAsync();
_ready = true;
await EnforceAsync();
}
private async void OnLocationChanged(object? sender, LocationChangedEventArgs e)
{
// If your Session can change based on navigation/cookies, you *may* refresh here,
// but avoid doing it on every navigation unless necessary.
// await Session.RefreshAsync();
await EnforceAsync();
}
private Task EnforceAsync()
{
if (!_ready) return Task.CompletedTask;
var path = "/" + Navigation.ToBaseRelativePath(Navigation.Uri);
var qIndex = path.IndexOf('?', StringComparison.Ordinal);
if (qIndex >= 0) path = path[..qIndex];
// allow anonymous routes
if (_allowAnonymous.Contains(path))
return Task.CompletedTask;
if (!Session.IsAuthenticated)
{
var returnUrl = Uri.EscapeDataString(Navigation.Uri);
Navigation.NavigateTo($"/login?returnUrl={returnUrl}", forceLoad: false);
}
return Task.CompletedTask;
}
public void Dispose()
=> Navigation.LocationChanged -= OnLocationChanged;
}