Skip to content

Commit 123876a

Browse files
committed
Home Page Design and ReauthRequired Raiese Event Test Fix
1 parent 5f2de3a commit 123876a

File tree

8 files changed

+306
-221
lines changed

8 files changed

+306
-221
lines changed

samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Dialogs/SessionDialog.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<DialogContent>
1515
@if (_chainDetail is not null)
1616
{
17-
<MudPaper Class="pa-4 mud-width-full" Elevation="0">
17+
<MudPaper Class="pa-4 mud-width-full" Elevation="0" >
1818
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2" Class="mb-3">
1919
<MudIconButton Icon="@Icons.Material.Filled.ArrowBack" Color="Color.Primary" Variant="Variant.Filled" OnClick="ClearDetail" />
2020
<MudText Typo="Typo.h6">Device Details</MudText>
@@ -29,7 +29,7 @@
2929
}
3030
</MudStack>
3131

32-
<MudPaper Class="pa-4 mb-4" Style="background: var(--mud-palette-background-gray)" Elevation="0">
32+
<MudPaper Class="pa-4 mb-4" Elevation="0" Outlined="true">
3333
<MudGrid Spacing="3">
3434

3535
<MudItem xs="12" md="6">

samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Layout/MainLayout.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
<MudAppBar Style="backdrop-filter: blur(10px)" Color="Color.Transparent" Dense="true" Elevation="0">
88
<UAuthLogo />
99
<MudText Class="ml-2 cursor-pointer" Style="user-select: none" @onclick="@(() => Nav.NavigateTo("/home", true))"><b>UltimateAuth</b></MudText>
10-
<MudDivider Class="ml-4 mr-2" Vertical="true" />
11-
<MudText Class="ml-2" Typo="Typo.subtitle2">Blazor Server Sample</MudText>
10+
<MudDivider Class="ml-3 mr-1" Vertical="true" />
11+
<MudText Class="ml-2" Style="line-height: 14px" Typo="Typo.subtitle2">Blazor Server Sample</MudText>
1212

1313
<MudSpacer />
1414

samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/Home.razor

Lines changed: 188 additions & 188 deletions
Large diffs are not rendered by default.

samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Components/Pages/Login.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
@inject IDialogService DialogService
1111

1212
<MudPage FullScreen="FullScreen.FullWithoutAppbar" Column="1" Row="1">
13-
<MudContainer Class="d-flex align-center justify-center" MaxWidth="MaxWidth.Medium">
13+
<MudContainer Class="d-flex align-center justify-center" MaxWidth="MaxWidth.Medium" Gutters="false">
1414
<MudGrid Spacing="0">
1515
<MudItem Class="order-1 order-sm-0" xs="12" sm="6">
1616
<MudPaper Class="mud-theme-primary uauth-login-paper pa-8 d-flex flex-column align-center justify-center" Elevation="3">

samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Program.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@
4040
builder.Services.AddUltimateAuthServer(o =>
4141
{
4242
o.Diagnostics.EnableRefreshDetails = true;
43-
//o.Session.MaxLifetime = TimeSpan.FromSeconds(32);
44-
//o.Session.Lifetime = TimeSpan.FromSeconds(32);
45-
//o.Session.TouchInterval = TimeSpan.FromSeconds(9);
46-
//o.Session.IdleTimeout = TimeSpan.FromSeconds(15);
47-
//o.Token.AccessTokenLifetime = TimeSpan.FromSeconds(30);
48-
//o.Token.RefreshTokenLifetime = TimeSpan.FromSeconds(32);
43+
o.Session.MaxLifetime = TimeSpan.FromSeconds(32);
44+
o.Session.Lifetime = TimeSpan.FromSeconds(32);
45+
o.Session.TouchInterval = TimeSpan.FromSeconds(9);
46+
o.Session.IdleTimeout = TimeSpan.FromSeconds(15);
47+
o.Token.AccessTokenLifetime = TimeSpan.FromSeconds(30);
48+
o.Token.RefreshTokenLifetime = TimeSpan.FromSeconds(32);
4949
o.Login.MaxFailedAttempts = 2;
5050
o.Login.LockoutDuration = TimeSpan.FromSeconds(10);
5151
o.Identifiers.AllowMultipleUsernames = true;
@@ -63,7 +63,7 @@
6363

6464
builder.Services.AddUltimateAuthClient(o =>
6565
{
66-
//o.AutoRefresh.Interval = TimeSpan.FromSeconds(5);
66+
o.AutoRefresh.Interval = TimeSpan.FromSeconds(5);
6767
o.Reauth.Behavior = ReauthBehavior.RaiseEvent;
6868
//o.UAuthStateRefreshMode = UAuthStateRefreshMode.Validate;
6969
});

samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/wwwroot/app.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ h1:focus {
9292
min-height: 62vh;
9393
}
9494

95+
.text-secondary {
96+
color: var(--mud-palette-text-secondary);
97+
}
98+
9599
@keyframes uauth-logo-float {
96100
0% {
97101
transform: translateY(0) rotateY(0);

src/CodeBeam.UltimateAuth.Client/Infrastructure/SessionCoordinator.cs

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using CodeBeam.UltimateAuth.Client.Contracts;
33
using CodeBeam.UltimateAuth.Client.Diagnostics;
44
using CodeBeam.UltimateAuth.Client.Options;
5+
using CodeBeam.UltimateAuth.Core.Abstractions;
56
using CodeBeam.UltimateAuth.Core.Domain;
67
using Microsoft.AspNetCore.Components;
78
using Microsoft.Extensions.Options;
@@ -14,26 +15,28 @@ internal sealed class SessionCoordinator : ISessionCoordinator
1415
private readonly NavigationManager _navigation;
1516
private readonly UAuthClientOptions _options;
1617
private readonly UAuthClientDiagnostics _diagnostics;
18+
private readonly IClock _clock;
1719

1820
private PeriodicTimer? _timer;
1921
private CancellationTokenSource? _cts;
2022

2123
public event Action? ReauthRequired;
2224

23-
public SessionCoordinator(IUAuthClient client, NavigationManager navigation, IOptions<UAuthClientOptions> options, UAuthClientDiagnostics diagnostics)
25+
public SessionCoordinator(IUAuthClient client, NavigationManager navigation, IOptions<UAuthClientOptions> options, UAuthClientDiagnostics diagnostics, IClock clock)
2426
{
2527
_client = client;
2628
_navigation = navigation;
2729
_options = options.Value;
2830
_diagnostics = diagnostics;
31+
_clock = clock;
2932
}
3033

3134
public async Task StartAsync(CancellationToken cancellationToken = default)
3235
{
3336
if (!_options.AutoRefresh.Enabled)
3437
return;
3538

36-
if (_timer is not null)
39+
if (_cts is not null)
3740
return;
3841

3942
_diagnostics.MarkStarted();
@@ -44,48 +47,101 @@ public async Task StartAsync(CancellationToken cancellationToken = default)
4447
_ = RunAsync(_cts.Token);
4548
}
4649

50+
//private async Task RunAsync(CancellationToken ct)
51+
//{
52+
// try
53+
// {
54+
// while (await _timer!.WaitForNextTickAsync(ct))
55+
// {
56+
// _diagnostics.MarkAutomaticRefresh();
57+
// var result = await _client.Flows.RefreshAsync(isAuto: true);
58+
59+
// switch (result.Outcome)
60+
// {
61+
// case RefreshOutcome.Touched:
62+
// break;
63+
64+
// case RefreshOutcome.NoOp:
65+
// break;
66+
67+
// case RefreshOutcome.Success:
68+
// break;
69+
70+
// case RefreshOutcome.ReauthRequired:
71+
// switch (_options.Reauth.Behavior)
72+
// {
73+
// case ReauthBehavior.Redirect:
74+
// _navigation.NavigateTo(_options.Reauth.RedirectPath ?? _options.Endpoints.Login, forceLoad: true);
75+
// break;
76+
77+
// case ReauthBehavior.RaiseEvent:
78+
// ReauthRequired?.Invoke();
79+
// break;
80+
81+
// case ReauthBehavior.None:
82+
// break;
83+
// }
84+
// _diagnostics.MarkTerminated(CoordinatorTerminationReason.ReauthRequired);
85+
// return;
86+
// }
87+
// }
88+
// }
89+
// catch (OperationCanceledException)
90+
// {
91+
// // expected
92+
// }
93+
//}
94+
4795
private async Task RunAsync(CancellationToken ct)
4896
{
97+
var interval = _options.AutoRefresh.Interval ?? TimeSpan.FromMinutes(5);
98+
var next = _clock.UtcNow + interval;
99+
49100
try
50101
{
51-
while (await _timer!.WaitForNextTickAsync(ct))
102+
while (!ct.IsCancellationRequested)
52103
{
104+
if (_clock.UtcNow < next)
105+
{
106+
await Task.Delay(10, ct);
107+
continue;
108+
}
109+
110+
next = _clock.UtcNow + interval;
111+
53112
_diagnostics.MarkAutomaticRefresh();
113+
54114
var result = await _client.Flows.RefreshAsync(isAuto: true);
55115

56116
switch (result.Outcome)
57117
{
58118
case RefreshOutcome.Touched:
59-
break;
60-
61119
case RefreshOutcome.NoOp:
62-
break;
63-
64120
case RefreshOutcome.Success:
65121
break;
66122

67123
case RefreshOutcome.ReauthRequired:
124+
68125
switch (_options.Reauth.Behavior)
69126
{
70127
case ReauthBehavior.Redirect:
71-
_navigation.NavigateTo(_options.Reauth.RedirectPath ?? _options.Endpoints.Login, forceLoad: true);
128+
_navigation.NavigateTo(
129+
_options.Reauth.RedirectPath ?? _options.Endpoints.Login,
130+
forceLoad: true);
72131
break;
73132

74133
case ReauthBehavior.RaiseEvent:
75134
ReauthRequired?.Invoke();
76135
break;
77-
78-
case ReauthBehavior.None:
79-
break;
80136
}
137+
81138
_diagnostics.MarkTerminated(CoordinatorTerminationReason.ReauthRequired);
82139
return;
83140
}
84141
}
85142
}
86143
catch (OperationCanceledException)
87144
{
88-
// expected
89145
}
90146
}
91147

@@ -102,4 +158,26 @@ public async ValueTask DisposeAsync()
102158
{
103159
await StopAsync();
104160
}
161+
162+
internal async Task TickAsync()
163+
{
164+
_diagnostics.MarkAutomaticRefresh();
165+
166+
var result = await _client.Flows.RefreshAsync(true);
167+
168+
if (result.Outcome == RefreshOutcome.ReauthRequired)
169+
{
170+
switch (_options.Reauth.Behavior)
171+
{
172+
case ReauthBehavior.Redirect: _navigation.NavigateTo(_options.Reauth.RedirectPath ?? _options.Endpoints.Login, forceLoad: true);
173+
break;
174+
175+
case ReauthBehavior.RaiseEvent:
176+
ReauthRequired?.Invoke();
177+
break;
178+
}
179+
180+
_diagnostics.MarkTerminated(CoordinatorTerminationReason.ReauthRequired);
181+
}
182+
}
105183
}

tests/CodeBeam.UltimateAuth.Tests.Unit/Client/SessionCoordinatorTests.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
using CodeBeam.UltimateAuth.Client.Infrastructure;
1+
using CodeBeam.UltimateAuth.Client;
2+
using CodeBeam.UltimateAuth.Client.Contracts;
23
using CodeBeam.UltimateAuth.Client.Diagnostics;
4+
using CodeBeam.UltimateAuth.Client.Infrastructure;
35
using CodeBeam.UltimateAuth.Client.Options;
4-
using CodeBeam.UltimateAuth.Client.Contracts;
6+
using CodeBeam.UltimateAuth.Core.Domain;
7+
using CodeBeam.UltimateAuth.Tests.Unit.Helpers;
58
using Microsoft.AspNetCore.Components;
69
using Microsoft.Extensions.Options;
710
using Moq;
8-
using CodeBeam.UltimateAuth.Client;
9-
using CodeBeam.UltimateAuth.Core.Domain;
1011

1112
namespace CodeBeam.UltimateAuth.Tests.Unit;
1213

@@ -15,6 +16,7 @@ public class SessionCoordinatorTests
1516
[Fact]
1617
public async Task StartAsync_should_not_start_when_auto_refresh_disabled()
1718
{
19+
var clock = new TestClock();
1820
var client = new Mock<IUAuthClient>();
1921
var nav = new Mock<NavigationManager>();
2022
var diagnostics = new UAuthClientDiagnostics();
@@ -27,7 +29,7 @@ public async Task StartAsync_should_not_start_when_auto_refresh_disabled()
2729
}
2830
});
2931

30-
var coordinator = new SessionCoordinator(client.Object, nav.Object, options, diagnostics);
32+
var coordinator = new SessionCoordinator(client.Object, nav.Object, options, diagnostics, clock);
3133
await coordinator.StartAsync();
3234

3335
Assert.False(diagnostics.IsRunning);
@@ -36,6 +38,8 @@ public async Task StartAsync_should_not_start_when_auto_refresh_disabled()
3638
[Fact]
3739
public async Task ReauthRequired_should_raise_event()
3840
{
41+
var clock = new TestClock();
42+
3943
var client = new Mock<IUAuthClient>();
4044
var nav = new Mock<NavigationManager>();
4145
var diagnostics = new UAuthClientDiagnostics();
@@ -51,20 +55,19 @@ public async Task ReauthRequired_should_raise_event()
5155
AutoRefresh = new UAuthClientAutoRefreshOptions
5256
{
5357
Enabled = true,
54-
Interval = TimeSpan.FromMilliseconds(10)
58+
Interval = TimeSpan.FromSeconds(5)
5559
},
5660
Reauth = new UAuthClientReauthOptions
5761
{
5862
Behavior = ReauthBehavior.RaiseEvent
5963
}
6064
});
6165

62-
var coordinator = new SessionCoordinator(client.Object, nav.Object, options, diagnostics);
66+
var coordinator = new SessionCoordinator(client.Object, nav.Object, options, diagnostics, clock);
6367
var triggered = false;
6468
coordinator.ReauthRequired += () => triggered = true;
6569

66-
await coordinator.StartAsync();
67-
await Task.Delay(50);
70+
await coordinator.TickAsync();
6871

6972
Assert.True(triggered);
7073
Assert.True(diagnostics.IsTerminated);

0 commit comments

Comments
 (0)